Nuitka-0.6.19.1/0000700000372100037210000000000014167275622020273 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/0000700000372100037210000000000014167275622021435 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/run-tests0000700000372100037210000000233114166627112023320 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Main front-end to the tests of Nuitka. Has many options, read --help output. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought be there. sys.path.insert( 0, os.path.normpath( os.path.join( os.path.dirname(__file__), "..", ) ) ) # isort:start from nuitka.tools.testing.run_nuitka_tests.__main__ import main main() Nuitka-0.6.19.1/tests/packages/0000700000372100037210000000000014167275622023213 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/packages/package_import_success_after_failure/0000700000372100037210000000000014167275622032620 5ustar nuitka-buildslavenuitka-buildslave00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000Nuitka-0.6.19.1/tests/packages/package_import_success_after_failure/PackageImportSuccessAfterFailure.pyNuitka-0.6.19.1/tests/packages/package_import_success_after_failure/PackageImportSuccessAfterFailure0000600000372100037210000000451614166627112041116 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function # nuitka-project: --follow-import-to=variable_package ORIG = None def display_difference(dct): print(ORIG.symmetric_difference(dct)) # Python2 has this in globals() so force it there for Python3 # to have same ORIG. if str is bytes: e = None ORIG = set(globals()) print("Initial try on top level package:") try: import variable_package except BaseException as e: print("Occurred", str(e)) display_difference(globals()) print("Retry with submodule import:") try: from variable_package.SomeModule import Class4 except BaseException as e: print("Occurred", str(e)) display_difference(globals()) print("Try with import from submodule:") try: from variable_package import SomeModule except BaseException as e: print("Occurred", str(e)) display_difference(globals()) print("Try with variable import from top level package assigned before raise:") try: from variable_package import raisy except BaseException as e: print("Occurred", str(e)) display_difference(globals()) print("Try with variable import from top level package assigned after raise:") try: from variable_package import Class5 except BaseException as e: print("Occurred", str(e)) display_difference(globals()) print("Try with variable import from top level package assigned before raise:") try: from variable_package import Class3 except BaseException as e: print("Occurred", str(e)) display_difference(globals().keys()) Nuitka-0.6.19.1/tests/packages/package_import_success_after_failure/variable_package/0000700000372100037210000000000014167275622036060 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/packages/package_import_success_after_failure/variable_package/SomeModule.py0000600000372100037210000000165614166627112040507 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class Class4(object): VALUE = "some_value" Nuitka-0.6.19.1/tests/packages/package_import_success_after_failure/variable_package/__init__.py0000600000372100037210000000221714166627112040167 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import os class Class3(object): pass def raisy(): if os.getenv("SHALL_FAIL", "1") == "1": print("RAISING!") raise Exception("AHOJ") raisy() class Class5(object): PASSW = "Secret" def __init__(self): print(self.PASSW, 2 + 3) Nuitka-0.6.19.1/tests/packages/sub_package/0000700000372100037210000000000014167275622025457 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/packages/sub_package/kitty/0000700000372100037210000000000014167275622026623 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/packages/sub_package/kitty/smallkitty.py0000600000372100037210000000161614166627112031372 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # size = "small" Nuitka-0.6.19.1/tests/packages/sub_package/kitty/bigkitty.py0000600000372100037210000000161414166627112031021 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # size = "big" Nuitka-0.6.19.1/tests/packages/sub_package/kitty/__init__.py0000600000372100037210000000231514166627112030731 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys print("__name__ is", __name__) if sys.version_info[:2] != (3,2): print("__package__ is", __package__) else: print("__package__ is correct:", __package__ is None or __package__ == "kitty") print("From sys.modules", sys.modules["kitty"]) from kitty.speak.hello import speak Nuitka-0.6.19.1/tests/packages/sub_package/kitty/speak/0000700000372100037210000000000014167275622027726 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/packages/sub_package/kitty/speak/purr.py0000600000372100037210000000170714166627112031271 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def speak(): print("mrrruu") Nuitka-0.6.19.1/tests/packages/sub_package/kitty/speak/miau.py0000600000372100037210000000170514166627112031232 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def speak(): print("miau") Nuitka-0.6.19.1/tests/packages/sub_package/kitty/speak/__init__.py0000600000372100037210000000204314166627112032032 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # try: print("__loader__ present:", __loader__ is not None) except NameError: print("No __loader__ found, OK for Python2") print("OK,", __name__, "loaded.") Nuitka-0.6.19.1/tests/packages/sub_package/kitty/speak/hello.py0000600000372100037210000000203414166627112031376 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def speak(): print( "hello kitty" ) # Test Issue#115, in recursing modules, this was misbehaving. import types assert type(speak) == types.FunctionType Nuitka-0.6.19.1/tests/packages/run_all.py0000700000372100037210000000661314166627112025224 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for package tests of Nuitka. Package tests are typically aiming at checking specific module constellations in module mode and making sure the details are being right there. These are synthetic small packages, each of which try to demonstrate one or more points or special behaviour. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( compareWithCPython, createSearchMode, getTempDir, my_print, setup, ) def main(): setup(suite="packages") search_mode = createSearchMode() for filename in sorted(os.listdir(".")): if not os.path.isdir(filename) or filename.endswith(".build"): continue extra_flags = [ "--module", "expect_success", "remove_output", "two_step_execution", ] active = search_mode.consider(dirname=None, filename=filename) if active: my_print("Consider output of compiled package:", filename) filename_main = None filename_main = os.path.join( filename, "".join(part.title() for part in filename.split("_")) + ".py" ) if os.path.exists(filename_main): filename_main = os.path.basename(filename_main) else: filename_main = None if filename_main is None: for filename_main in os.listdir(filename): if not os.path.isdir(os.path.join(filename, filename_main)): continue if filename_main not in ("..", "."): break else: search_mode.onErrorDetected( """\ Error, no package in test directory '%s' found, incomplete test case.""" % filename ) extra_flags.append( "--include-package=%s" % os.path.basename(filename_main) ) extra_flags.append("--output-dir=%s" % getTempDir()) compareWithCPython( dirname=filename, filename=filename_main, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, ) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/syntax/0000700000372100037210000000000014167275622022763 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/syntax/ClassReturn.py0000600000372100037210000000142714166627112025602 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class X: return 3 Nuitka-0.6.19.1/tests/syntax/YieldInAsync35.py0000600000372100037210000000144414166627112026037 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # async def g(): yield from None Nuitka-0.6.19.1/tests/syntax/NonAsciiWithoutEncoding_2.py0000600000372100037210000000156314166627112030315 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # No encoding declared, but non-ASCII in that string. s = "'\0\"\n\r\t abcd\x85é\U00012fff\uD800\U0001D121xxx." Nuitka-0.6.19.1/tests/syntax/TryExceptAllNotLast.py0000600000372100037210000000153114166627112027216 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(): try: raise A except: print("caught") except A: print("hit") Nuitka-0.6.19.1/tests/syntax/AsyncgenReturn36.py0000600000372100037210000000145114166627112026452 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # async def gen(): yield 1 return 2 Nuitka-0.6.19.1/tests/syntax/BreakWithoutLoop.py0000600000372100037210000000154214166627112026575 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # marker1 def test_from_format(self): if sys.version_info >= (3, 3): break # marker2 Nuitka-0.6.19.1/tests/syntax/TryFinallyContinue_37.py0000600000372100037210000000155314166627112027450 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(): for i in range(10): try: undefined finally: continue Nuitka-0.6.19.1/tests/syntax/FutureBraces.py0000600000372100037210000000147214166627112025727 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import braces print("Look ma, braces.") Nuitka-0.6.19.1/tests/syntax/StarImportExtra.py0000600000372100037210000000157714166627112026453 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # try: from sys import not_there, * except Exception as e: print( "Star import with extra stuff not present gave", e ) Nuitka-0.6.19.1/tests/syntax/YieldInModule.py0000600000372100037210000000142014166627112026031 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # x = (yield i) Nuitka-0.6.19.1/tests/syntax/YieldFromInModule.py0000600000372100037210000000143414166627112026662 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # x = (yield from range(8)) Nuitka-0.6.19.1/tests/syntax/run_all.py0000700000372100037210000000423314166627112024770 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for syntax tests of Nuitka. In some cases, the ast module doesn't raise the syntax errors for us, but we need to check them manually and raise explicitly. This aims at showing we do it in the same way. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( compareWithCPython, createSearchMode, decideFilenameVersionSkip, setup, ) def main(): setup(suite="syntax", needs_io_encoding=True) search_mode = createSearchMode() for filename in sorted(os.listdir(".")): if not filename.endswith(".py"): continue if not decideFilenameVersionSkip(filename): continue active = search_mode.consider(dirname=None, filename=filename) if active: extra_flags = [ "expect_failure", "remove_output", "syntax_errors", "--nofollow-imports", ] compareWithCPython( dirname=None, filename=filename, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, ) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/syntax/NonlocalNotFound32.py0000600000372100037210000000154214166627112026722 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def testNonlocal(): x = 0 y = 0 def f(): nonlocal z f() testNonlocal() Nuitka-0.6.19.1/tests/syntax/UnpackNoTuple.py0000600000372100037210000000141014166627112026055 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # *a = 1 Nuitka-0.6.19.1/tests/syntax/SyntaxError.py0000600000372100037210000000154514166627112025636 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Test the syntax error case: def nested(): claxss ProxyBase(metaclass=ProxyType): pass Nuitka-0.6.19.1/tests/syntax/NonlocalForParameter32.py0000600000372100037210000000143314166627112027554 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(a): nonlocal a Nuitka-0.6.19.1/tests/syntax/UnpackTwoStars32.py0000600000372100037210000000145114166627112026427 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # foo, *bar, baz, *a, b = name.split('/') Nuitka-0.6.19.1/tests/syntax/MisplacedFutureImport.py0000600000372100037210000000151214166627112027617 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(): from __future__ import print_function print(locals()) Nuitka-0.6.19.1/tests/syntax/ModuleReturn.py0000600000372100037210000000144114166627112025756 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # lalala = 3 return lelele = 7 Nuitka-0.6.19.1/tests/syntax/DuplicateArgument.py0000600000372100037210000000142714166627112026752 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(a, a): pass Nuitka-0.6.19.1/tests/syntax/FutureUnknown.py0000600000372100037210000000144514166627112026167 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import not_existing Nuitka-0.6.19.1/tests/syntax/GlobalForParameter.py0000600000372100037210000000143114166627112027040 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(a): global a Nuitka-0.6.19.1/tests/syntax/YieldInGenexp38.py0000600000372100037210000000163214166627112026212 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def strangeLambdaGeneratorExpression(): x = ((yield) for i in (1,2) if (yield)) print("Strange lambda generator expression") print(list(x)) Nuitka-0.6.19.1/tests/syntax/GeneratorExpressions38.py0000600000372100037210000000202114166627112027670 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test case with generator expression form only allow until Python 3.7 """ def strangeLambdaGeneratorExpression(): x = ((yield) for i in (1, 2) if (yield)) print("Strange lambda generator expression:") print(list(x)) strangeLambdaGeneratorExpression() Nuitka-0.6.19.1/tests/syntax/LateFutureImport.py0000600000372100037210000000160414166627112026605 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Not allowed to do future imports that are not the first statements of the # module. a = 1 from __future__ import print_function Nuitka-0.6.19.1/tests/syntax/ContinueWithoutLoop.py0000600000372100037210000000152214166627112027333 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def test_from_format(self): if sys.version_info >= (3, 3): continue Nuitka-0.6.19.1/tests/syntax/IndentationError.py0000600000372100037210000000143714166627112026624 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def someFunc(): a b Nuitka-0.6.19.1/tests/syntax/GeneratorReturn_2.py0000600000372100037210000000155714166627112026710 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def g(): for a in range(3): yield a return 7 print("Yielder with return value", list(g())) Nuitka-0.6.19.1/tests/syntax/ExecWithNesting_2.py0000600000372100037210000000212714166627112026624 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # In Python2, it is not allowed to take closure variables, in a function that # has an "exec". For Python3, the problem doesn't exist, as there is no exec # statement anymore. def someFunctionWithUnqualifiedExecAndCallback(): exec "def f(): pass" def callback(): return nested someFunctionWithUnqualifiedExecAndCallback() Nuitka-0.6.19.1/tests/syntax/Importing32.py0000600000372100037210000000174314166627112025453 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def starImportFailure(): from doctest import * try: sys print("but it does not") except NameError: print("and it does") print("Star import needs to respect __all__", starImportFailure()) Nuitka-0.6.19.1/tests/syntax/ClosureDel_2.py0000600000372100037210000000171214166627112025614 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def deletingClosure(): a = 1 def closureTaker(): return a del a try: x = closureTaker() except Exception as e: print "Occurred %r" % e deletingClosure() Nuitka-0.6.19.1/tests/reflected/0000700000372100037210000000000014167275622023372 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/reflected/compile_itself.py0000700000372100037210000003174314166627112026747 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test Nuitka compiling itself and compiling itself in compiled form again. This should not only give no errors, but the same source for modules being compiled when Nuitka is running compiled and uncompiled, so we can discover changes in order of execution in this test. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start import difflib import shutil import subprocess import time from nuitka.tools.testing.Common import ( getTempDir, my_print, setup, test_logger, ) from nuitka.utils.Execution import wrapCommandForDebuggerForSubprocess from nuitka.utils.FileOperations import copyTree, listDir, removeDirectory from nuitka.utils.Importing import getSharedLibrarySuffix nuitka_main_path = os.path.join("..", "..", "bin", "nuitka") tmp_dir = getTempDir() # Cannot detect this more automatic, so we need to list them, avoiding # the ones not needed. PACKAGE_LIST = ( "nuitka", "nuitka/nodes", "nuitka/specs", "nuitka/nodes/shapes", "nuitka/tree", "nuitka/importing", "nuitka/build", "nuitka/freezer", "nuitka/codegen", "nuitka/codegen/templates", "nuitka/codegen/c_types", "nuitka/optimizations", "nuitka/finalizations", "nuitka/plugins", "nuitka/plugins/standard", "nuitka/plugins/commercial", "nuitka/pgo", "nuitka/constants", "nuitka/containers", "nuitka/utils", ) exe_suffix = ".exe" if os.name == "nt" else ".bin" def readSource(filename): if str is bytes: return open(filename, "rb").read() else: return open(filename, "rb").read().decode("latin1") def diffRecursive(dir1, dir2): # Complex in nature, pylint: disable=too-many-branches done = set() result = False for path1, filename in listDir(dir1): if "cache-" in path1: continue path2 = os.path.join(dir2, filename) done.add(path1) # Skip these binary files and scons build database of course. # TODO: Temporary ignore ".bin", until we have something better than marshal which behaves # differently in compiled Nuitka: if filename.endswith( ( ".o", ".os", ".obj", ".dblite", ".tmp", ".sconsign", ".txt", ".bin", ".const", ".exp", ) ): continue if not os.path.exists(path2): test_logger.warning("Only in %s: %s" % (dir1, filename)) result = False continue if os.path.isdir(path1): r = diffRecursive(path1, path2) if r: result = True elif os.path.isfile(path1): fromdate = time.ctime(os.stat(path1).st_mtime) todate = time.ctime(os.stat(path2).st_mtime) diff = difflib.unified_diff( a=readSource(path1).splitlines(), b=readSource(path2).splitlines(), fromfile=path1, tofile=path2, fromfiledate=fromdate, tofiledate=todate, n=3, ) diff_list = list(diff) if diff_list: for line in diff_list: try: my_print(line) except UnicodeEncodeError: my_print(repr(line)) result = True else: assert False, path1 for path1, filename in listDir(dir2): if "cache-" in path1: continue path2 = os.path.join(dir2, filename) if path1 in done: continue if not os.path.exists(path1): test_logger.warning("Only in %s: %s" % (dir2, filename)) result = False continue return result def _traceCompilation(path, pass_number): test_logger.info("Compiling '%s' (PASS %d)." % (path, pass_number)) def executePASS1(): test_logger.info( "PASS 1: Compiling to many compiled modules from compiler running from .py files." ) base_dir = os.path.join("..", "..") for package in PACKAGE_LIST: package = package.replace("/", os.path.sep) source_dir = os.path.join(base_dir, package) target_dir = package removeDirectory(path=target_dir, ignore_errors=False) os.mkdir(target_dir) for path, filename in listDir(target_dir): if filename.endswith(".so"): os.unlink(path) for path, filename in listDir(source_dir): if not filename.endswith(".py"): continue if filename.startswith(".#"): continue if filename != "__init__.py": _traceCompilation(path=path, pass_number=1) command = [ os.environ["PYTHON"], nuitka_main_path, "--module", "--nofollow-imports", "--plugin-enable=pylint-warnings", "--output-dir=%s" % target_dir, "--no-pyi-file", path, ] command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split() my_print("Command: ", " ".join(command)) result = subprocess.call(command) if result != 0: sys.exit(result) else: shutil.copyfile(path, os.path.join(target_dir, filename)) _traceCompilation(path=nuitka_main_path, pass_number=1) shutil.copyfile(nuitka_main_path, "nuitka-runner.py") command = [ os.environ["PYTHON"], nuitka_main_path, "--nofollow-imports", "--plugin-enable=pylint-warnings", "--output-dir=.", "--python-flag=-S", "nuitka-runner.py", ] command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split() my_print("Command: ", " ".join(command)) result = subprocess.call(command) if result != 0: sys.exit(result) shutil.move("nuitka-runner" + exe_suffix, "nuitka" + exe_suffix) scons_inline_copy_path = os.path.join(base_dir, "nuitka", "build", "inline_copy") if os.path.exists(scons_inline_copy_path): copyTree(scons_inline_copy_path, os.path.join("nuitka", "build", "inline_copy")) # Copy required data files. for filename in ( "nuitka/build/Backend.scons", "nuitka/plugins/standard/anti-bloat.yml", "nuitka/plugins/standard/implicit-imports.yml", "nuitka/plugins/standard/data-files.yml", ): shutil.copyfile( os.path.join(base_dir, filename), filename, ) copyTree( os.path.join(base_dir, "nuitka", "codegen", "templates_c"), os.path.join("nuitka", "codegen", "templates_c"), ) copyTree( os.path.join(base_dir, "nuitka", "build", "static_src"), os.path.join("nuitka", "build", "static_src"), ) copyTree( os.path.join(base_dir, "nuitka", "build", "include"), os.path.join("nuitka", "build", "include"), ) # The data composer tool, use it by source. copyTree( os.path.join(base_dir, "nuitka", "tools"), os.path.join("nuitka", "tools"), ) test_logger.info("OK.") def compileAndCompareWith(nuitka, pass_number): if "PYTHONHASHSEED" not in os.environ: os.environ["PYTHONHASHSEED"] = "0" base_dir = os.path.join("..", "..") for package in PACKAGE_LIST: package = package.replace("/", os.path.sep) source_dir = os.path.join(base_dir, package) for path, filename in listDir(source_dir): if not filename.endswith(".py"): continue if filename.startswith(".#"): continue path = os.path.join(source_dir, filename) if filename != "__init__.py": _traceCompilation(path=path, pass_number=pass_number) target = filename.replace(".py", ".build") target_dir = os.path.join(tmp_dir, target) removeDirectory(path=target_dir, ignore_errors=False) command = [ nuitka, "--module", "--plugin-enable=pylint-warnings", "--output-dir=%s" % tmp_dir, "--no-pyi-file", path, ] command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split() my_print("Command: ", " ".join(command)) exit_nuitka = subprocess.call(command) # In case of segfault or assertion triggered, run in debugger. if exit_nuitka in (-11, -6) and sys.platform != "nt": command2 = wrapCommandForDebuggerForSubprocess(*command) subprocess.call(command2) if exit_nuitka != 0: my_print("An error exit %s occurred, aborting." % exit_nuitka) sys.exit(exit_nuitka) has_diff = diffRecursive(os.path.join(package, target), target_dir) if has_diff: sys.exit("There were differences!") shutil.rmtree(target_dir) target_filename = filename.replace( ".py", getSharedLibrarySuffix(preferred=True) ) os.unlink(os.path.join(tmp_dir, target_filename)) def executePASS2(): test_logger.info( "PASS 2: Compiling from compiler running from entry .exe and many .so files." ) # Windows will load the compiled modules (pyd) only from PYTHONPATH, so we # have to add it. if os.name == "nt": os.environ["PYTHONPATH"] = ":".join(PACKAGE_LIST) compileAndCompareWith( nuitka=os.path.join(".", "nuitka" + exe_suffix), pass_number=2 ) # Undo the damage from above. if os.name == "nt": del os.environ["PYTHONPATH"] test_logger.info("OK.") def executePASS3(): test_logger.info( "PASS 3: Compiling from compiler running from .py files to single .exe." ) exe_path = os.path.join(tmp_dir, "nuitka" + exe_suffix) if os.path.exists(exe_path): os.unlink(exe_path) build_path = os.path.join(tmp_dir, "nuitka.build") if os.path.exists(build_path): shutil.rmtree(build_path) path = os.path.join("..", "..", "bin", "nuitka") _traceCompilation(path=path, pass_number=3) command = [ os.environ["PYTHON"], nuitka_main_path, path, "--output-dir=%s" % tmp_dir, "--python-flag=-S", "--follow-imports", # "--include-package=nuitka.plugins", ] my_print("Command: ", " ".join(command)) result = subprocess.call(command) if result != 0: sys.exit(result) shutil.rmtree(build_path) test_logger.info("OK.") def executePASS4(): test_logger.info("PASS 4: Compiling the compiler running from single exe.") exe_path = os.path.join(tmp_dir, "nuitka" + exe_suffix) compileAndCompareWith(exe_path, pass_number=4) test_logger.info("OK.") def executePASS5(): my_print("PASS 5: Compiling the compiler 'nuitka' package to single '.so' file.") path = os.path.join("..", "..", "nuitka") command = [ os.environ["PYTHON"], nuitka_main_path, "--plugin-enable=pylint-warnings", "--output-dir=%s" % tmp_dir, "--include-plugin-dir=%s" % path, "--nofollow-import-to=nuitka.build.inline_copy", "--nofollow-import-to=nuitka.build.include", "--nofollow-import-to=nuitka.build.static_src", "--module", path, ] result = subprocess.call(command) if result != 0: sys.exit(result) os.unlink(os.path.join(tmp_dir, "nuitka" + getSharedLibrarySuffix(preferred=True))) os.unlink(os.path.join(tmp_dir, "nuitka.pyi")) shutil.rmtree(os.path.join(tmp_dir, "nuitka.build")) def main(): setup(needs_io_encoding=True) executePASS1() executePASS2() executePASS3() executePASS4() shutil.rmtree("nuitka") executePASS5() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/plugins/0000700000372100037210000000000014167275622023116 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/plugins/run_all.py0000700000372100037210000000700514166627112025123 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for plugins tests of Nuitka. Plugin tests are typically aiming at covering plugin interfaces and their correctness, not concrete standard plugins. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( compareWithCPython, createSearchMode, getMainProgramFilename, my_print, setup, withPythonPathChange, ) def main(): # Complex stuff, even more should become common code though. setup(suite="plugins", needs_io_encoding=True) search_mode = createSearchMode() extra_options = os.environ.get("NUITKA_EXTRA_OPTIONS", "") # TODO: Add a directory test case scanner instead of duplicating this kind of code. for filename in sorted(os.listdir(".")): if ( not os.path.isdir(filename) or filename.endswith(".build") or filename.endswith(".dist") ): continue filename = os.path.relpath(filename) extra_flags = ["expect_success"] # We annotate some tests, use that to lower warnings. extra_flags.append("plugin_enable:pylint-warnings") extra_flags.append("remove_output") extra_flags.append("--follow-imports") plugin_files = [p for p in os.listdir(filename) if p.endswith("-plugin.py")] assert plugin_files extra_flags.extend( "user_plugin:" + os.path.abspath(os.path.join(filename, p)) for p in plugin_files ) if filename == "parameters": os.environ["NUITKA_EXTRA_OPTIONS"] = extra_options + " --trace-my-plugin" else: os.environ["NUITKA_EXTRA_OPTIONS"] = extra_options active = search_mode.consider(dirname=None, filename=filename) if active: my_print("Consider output of recursively compiled program:", filename) filename_main = getMainProgramFilename(filename) extra_python_path = [ os.path.abspath(os.path.join(filename, entry)) for entry in os.listdir(filename) if entry.startswith("path") ] with withPythonPathChange(extra_python_path): compareWithCPython( dirname=filename, filename=filename_main, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, ) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/plugins/parameters/0000700000372100037210000000000014167275622025261 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/plugins/parameters/parameter-using-plugin.py0000600000372100037210000000416414166627112032233 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Parameter using Nuitka plugin. """ import os import sys # from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginForTesting(NuitkaPluginBase): plugin_name = __name__.split(".")[-1] def __init__(self, trace_my_plugin): # demo only: extract and display my options list # check whether some specific option is set self.check = trace_my_plugin self.info("The 'trace' value is set to '%s'" % self.check) # do more init work here ... @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--trace-my-plugin", action="store_true", dest="trace_my_plugin", default=False, help="This is show in help output." ) def onModuleSourceCode(self, module_name, source_code): # if this is the main script and tracing should be done ... if module_name == "__main__" and self.check: self.info("") self.info(" Calls to 'math' module:") for i, l in enumerate(source_code.splitlines()): if "math." in l: self.info(" %i: %s" % (i+1, l)) self.info("") return source_code Nuitka-0.6.19.1/tests/plugins/parameters/ParametersMain.py0000600000372100037210000000177214166627112030546 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Just something to allow the plugin to look at. """ from __future__ import print_function import math print(math.pi) Nuitka-0.6.19.1/tests/optimizations/0000700000372100037210000000000014167275622024346 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/optimizations/Operations.py0000600000372100037210000000430314166627112027037 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This test is SPECIAL. Everything in here, MUST be statically optimized, # and be a print of a constant, or a function that becomes a return value # that is constant. print(not bool) print(not {}) print(not 7) print(bool or len) print(False or dict) print(type(Ellipsis)) print("a" in "abba") print("a" not in "abba") print(len("a"*10000)) print(len(10000*"a")) print(len((1,) *20000)) print(len(20000*(1,))) print(len([1]*30000)) print(len(30000*[1])) print(len(unicode("a")*40000)) print(len(40000*unicode("a"))) # For operations, we use function return values of local variables that will # have to become constant. def simpleAssignment(): x = 2 return x def inplaceOperationIncrement(): x = 2 x += 1 return x def inplaceOperationProduct(): x = 2 x *= 2 return x def inplaceOperationExponentiate(): x = 2 x **= 2 return x def inplaceOperationDecrement(): x = 2 x -= 8 return x # x //= 5 def inplaceOperationFloorDivison(): x = 2 x //= 5 return x def inplaceOperationModulus(): x = 2 x %= 3 return x def inplaceOperationAnd(): x = 2 x &= 2 return x def inplaceOperationOr(): x = 2 x |= 5 return x def inplaceOperationXor(): x = 2 x ^= 1 return x def inplaceOperationDivison(): x = 2 x /= 2 return x Nuitka-0.6.19.1/tests/optimizations/Len.py0000600000372100037210000000233314166627112025433 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print(len(range(266))) print(len(range(266,9999))) print(len(range(266,9999,3))) print(len(range(266,9999,-3))) print(len(range(22266,9999,-3))) print(len(range(22266,9998,-3))) print(len(range(22266,9997,-3))) print(len(range(22266,9996,-3))) print(len(range(0,3,3))) print(len([3,3.3])) print(len((3,3.3))) Nuitka-0.6.19.1/tests/optimizations/Iterations.py0000600000372100037210000000162514166627112027041 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # z = next(iter((3,4))) Nuitka-0.6.19.1/tests/optimizations/Conditions.py0000600000372100037210000000163114166627112027026 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print(1 if [1,2] else 2) Nuitka-0.6.19.1/tests/optimizations/FormatStrings36.py0000600000372100037210000000227214166627112027672 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Format string with local compile time constants fully optimized: def f(): a = "1" b = "2" return f'r:{a!r} and a:{a!a} and s:{a!s}' print(f()) # Empty f string fully optimized: def f(): return f'' print(f()) # Text only f string fully optimized: def f(): return f'some_text' print(f()) Nuitka-0.6.19.1/tests/optimizations/run_all.py0000700000372100037210000002025514166627112026355 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test runners test This shows that known good existing static optimization works and produces constant results. This should be used to preserve successful optimization at compile time against later changes breaking them undetected. """ from __future__ import print_function import os import sys # The test runner needs "lxml" itself. try: import lxml.etree except ImportError: print("Warning, no 'lxml' module installed, cannot do XML based tests.") sys.exit(0) # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( check_output, convertUsing2to3, createSearchMode, decideFilenameVersionSkip, my_print, setup, ) from nuitka.TreeXML import toString python_version = setup(suite="optimiations") search_mode = createSearchMode() def getKind(node): result = node.attrib["kind"] result = result.replace("Statements", "") result = result.replace("Statement", "") result = result.replace("Expression", "") return result def getRole(node, role): for child in node: if child.tag == "role" and child.attrib["name"] == role: return child return None def getSourceRef(filename, node): return "%s:%s" % (filename, node.attrib["line"]) def isConstantExpression(expression): kind = getKind(expression) return kind.startswith("Constant") or kind in ( "ImportModuleHard", "ImportModuleNameHard", "ModuleAttributeFileRef", "ModuleLoaderRef", ) def checkSequence(filename, statements): # Complex stuff, pylint: disable=too-many-branches for statement in statements: kind = getKind(statement) # Printing is fine. if kind == "PrintValue": (print_arg,) = getRole(statement, "value") if not isConstantExpression(print_arg): search_mode.onErrorDetected( "%s: Error, print of non-constant '%s'." % (getSourceRef(filename, statement), getKind(print_arg)) ) continue if kind == "PrintNewline": continue # Printing in Python3 is a function call whose return value is ignored. if kind == "Only": only_expression = getRole(statement, "expression")[0] if getKind(only_expression) == "CallNoKeywords": called_expression = getRole(only_expression, "called")[0] if getKind(called_expression) == "BuiltinRef": if called_expression.attrib["builtin_name"] == "print": continue if kind == "FrameModule": checkSequence(filename, getRole(statement, "statements")) continue if kind == "FrameFunction": checkSequence(filename, getRole(statement, "statements")) continue if kind == "AssignmentVariable": variable_name = statement.attrib["variable_name"] # Ignore "__spec__" assignment for Python3.4, it is not going # to be static. if variable_name == "__spec__": continue (assign_source,) = getRole(statement, "source") if getKind(assign_source) == "FunctionCreation": continue if not isConstantExpression(assign_source): search_mode.onErrorDetected( "Error, assignment from non-constant '%s'." % getKind(assign_source) ) continue if kind == "AssignmentAttribute": (assign_source,) = getRole(statement, "expression") if getKind(assign_source) == "ModuleAttributeSpecRef": continue search_mode.onErrorDetected( "Error, attribute assignment to '%s'." % getKind(assign_source) ) if kind in ("ReturnNone", "ReturnConstant"): continue print(toString(statement)) search_mode.onErrorDetected( "Error, non-print statement of unknown kind '%s'." % kind ) def main(): # Complex stuff, pylint: disable=too-many-branches for filename in sorted(os.listdir(".")): if not filename.endswith(".py") or filename.startswith("run_"): continue if not decideFilenameVersionSkip(filename): continue active = search_mode.consider(dirname=None, filename=filename) if active: # Apply 2to3 conversion if necessary. if python_version >= (3,): filename, changed = convertUsing2to3(filename) else: changed = False my_print("Consider", filename, end=" ") command = [ os.environ["PYTHON"], os.path.abspath(os.path.join("..", "..", "bin", "nuitka")), "--xml", "--quiet", "--module", filename, ] if search_mode.isCoverage(): # To avoid re-execution, which is not acceptable to coverage. if "PYTHONHASHSEED" not in os.environ: os.environ["PYTHONHASHSEED"] = "0" # Coverage modules hates Nuitka to re-execute, and so we must avoid # that. python_path = check_output( [ os.environ["PYTHON"], "-c", "import sys, os; print(os.pathsep.join(sys.path))", ] ) if sys.version_info >= (3,): python_path = python_path.decode("utf8") os.environ["PYTHONPATH"] = python_path.strip() command.insert(2, "--must-not-re-execute") command = ( command[0:1] + ["-S", "-m", "coverage", "run", "--rcfile", os.devnull, "-a"] + command[1:] ) result = check_output(command) # Parse the result into XML and check it. try: root = lxml.etree.fromstring(result) except lxml.etree.XMLSyntaxError: my_print("Problematic XML output:") my_print(result) raise module_body = root[0] module_statements_sequence = module_body[0] assert len(module_statements_sequence) == 1 module_statements = next(iter(module_statements_sequence)) try: checkSequence(filename, module_statements) for function in root.xpath('role[@name="functions"]/node'): (function_body,) = function.xpath('role[@name="body"]') function_statements_sequence = function_body[0] assert len(function_statements_sequence) == 1 function_statements = next(iter(function_statements_sequence)) checkSequence(filename, function_statements) if changed: os.unlink(filename) except SystemExit: my_print("FAIL.") raise my_print("OK.") search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/optimizations/HardImports.py0000600000372100037210000000217514166627112027155 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys import os def sysAttributes(): return ( sys.version_info, sys.version_info[0], sys.version_info.major, sys.version, sys.platform, sys.maxsize, ) def osAttributes(): return os.name Nuitka-0.6.19.1/tests/optimizations/Subscripts.py0000600000372100037210000000241414166627112027056 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print( (1,2,3)[1] ) print( (1,2,3)[1:] ) print( (1,2,3)[:2] ) print( (1,2,3)[:] ) print( (1,2,3)[1:2] ) print( (1,2,3,4,5,6)[1::2]) print( (1,2,3,4,5,6)[4::-2]) print( (1,2,3,4,5,6)[-1]) print( (1,2,3,4,5,6)[-3:]) print( (1,2,3,4,5,6)[:-1]) print( (1,2,3,4,5,6)[::]) print( (1,2,3,4,5,6)[-3:-1]) print( (1,2,3,4,5,6)[:-1:2]) print( (1,2,3,4,5,6)[-1::-2]) print( (1,2,3,4,5,6)[slice(-1,None,-2)]) Nuitka-0.6.19.1/tests/optimizations/Attributes.py0000600000372100037210000000204014166627112027036 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print((1).imag) print(int.__name__) print((1).__class__) print(getattr(1, "real")) print(getattr(1, "real", None)) print(hasattr(1, "real")) print((0.0).real) Nuitka-0.6.19.1/tests/optimizations/HardImports_2.py0000600000372100037210000000171514166627112027375 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys def sysOptionalAttribute(): return sys.maxint, sys.subversion Nuitka-0.6.19.1/tests/optimizations/DecodingOperations.py0000600000372100037210000000161514166627112030477 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print(chr(7)) Nuitka-0.6.19.1/tests/optimizations/ArgumentTypes.py0000600000372100037210000000167614166627112027535 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(b, *args, **kwargs): return type(args), type(kwargs) Nuitka-0.6.19.1/tests/optimizations/Calls.py0000600000372100037210000000177514166627112025764 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Optimization of calls TODO: This is only a placeholder, currently no real calls will be optimized. """ print(range(4)) Nuitka-0.6.19.1/tests/onefile/0000700000372100037210000000000014167275622023056 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/onefile/run_all.py0000700000372100037210000001263214166627112025065 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for onefile program tests of Nuitka. These tests aim at showing that one specific functions work in onefile mode, trying to find issues with that form of packaging. """ import os import sys # Find nuitka package relative to us. The replacement is for POSIX python # and Windows paths on command line. sys.path.insert( 0, os.path.normpath( os.path.join( os.path.dirname(os.path.abspath(__file__.replace("\\", os.sep))), "..", ".." ) ), ) # isort:start from nuitka.freezer.RuntimeTracing import getRuntimeTraceOfLoadedFiles from nuitka.tools.testing.Common import ( addExtendedExtraOptions, checkLoadedFileAccesses, checkRequirements, compareWithCPython, createSearchMode, decideFilenameVersionSkip, displayFileContents, displayRuntimeTraces, reportSkip, setup, test_logger, ) from nuitka.utils.Timing import TimerReport from nuitka.utils.Utils import getOS def displayError(dirname, filename): assert dirname is None inclusion_log_path = filename[:-3] + ".py.inclusion.log" displayFileContents("inclusion log", inclusion_log_path) def main(): python_version = setup(suite="onefile", needs_io_encoding=True) search_mode = createSearchMode() if getOS() == "Linux": addExtendedExtraOptions( "--linux-onefile-icon=../../doc/Logo/Nuitka-Logo-Symbol.svg" ) for filename in sorted(os.listdir(".")): if not filename.endswith(".py"): continue if not decideFilenameVersionSkip(filename): continue active = search_mode.consider(dirname=None, filename=filename) if not active: test_logger.info("Skipping %s" % filename) continue extra_flags = [ "expect_success", "remove_output", # Keep the binary, normally "remove_output" includes that. "--keep-binary", # Cache the CPython results for re-use, they will normally not change. "cpython_cache", # To understand what is slow. "timing", ] if filename == "KeyboardInteruptTest.py": if getOS() == "Darwin": reportSkip( "Exit code from KeybaordInterrupt on macOS is not yet good.", ".", filename, ) continue if python_version < (3,): reportSkip( "Python2 reports KeyboardInterrupt, but too late", ".", filename, ) continue if os.name == "nt": reportSkip( "Testing cannot send KeyboardInterrupt on Windows yet", ".", filename, ) continue extra_flags.append("--send-ctrl-c") # skip each test if their respective requirements are not met requirements_met, error_message = checkRequirements(filename) if not requirements_met: reportSkip(error_message, ".", filename) continue test_logger.info( "Consider output of onefile mode compiled program: %s" % filename ) # First compare so we know the program behaves identical. compareWithCPython( dirname=None, filename=filename, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, on_error=displayError, ) binary_filename = filename[:-3] + (".exe" if os.name == "nt" else ".bin") if filename == "KeyboardInteruptTest.py": continue # Then use "strace" on the result. with TimerReport( "Determining run time loaded files took %.2f", logger=test_logger ): loaded_filenames = getRuntimeTraceOfLoadedFiles( logger=test_logger, command=[binary_filename] ) illegal_accesses = checkLoadedFileAccesses( loaded_filenames=loaded_filenames, current_dir=os.getcwd() ) if illegal_accesses: displayError(None, filename) displayRuntimeTraces(test_logger, binary_filename) test_logger.warning( "Should not access these file(s): '%s'." % ",".join(illegal_accesses) ) search_mode.onErrorDetected(1) os.unlink(binary_filename) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/onefile/KeyboardInteruptTest.py0000600000372100037210000000241714166627112027563 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ In this test, we get killed after some time has passed, and want to see the KeyboardInterrupt exit. """ # nuitka-project: --onefile import sys import time print("Hello world, will you kill me?") print(sys.version_info) try: time.sleep(10) except KeyboardInterrupt: print("Received KeyboardInterrupt.") sys.exit(0) else: print("Received no KeyboardInterrupt.") sys.exit(1) Nuitka-0.6.19.1/tests/onefile/HelloWorldTest.py0000600000372100037210000000174014166627112026341 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function # nuitka-project: --onefile print("Hello Onefile World!")Nuitka-0.6.19.1/tests/standalone/0000700000372100037210000000000014167275622023565 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/standalone/PyQt5SSLSupport.py0000600000372100037210000000201114166627112027066 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from PyQt5.QtNetwork import QSslSocket # nuitka-skip-unless-imports: PyQt5.QtGui print("SSL support: %r" % (QSslSocket.supportsSsl(),)) Nuitka-0.6.19.1/tests/standalone/Win32ComUsing.py0000600000372100037210000000226014166627112026502 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that uses win32com superficially. Please help make it more useful, ideally by adding something that would work on every machine. """ # nuitka-project: --standalone from win32com import storagecon from win32com.shell import shell, shellcon # nuitka-skip-unless-imports: win32com print("OK.") Nuitka-0.6.19.1/tests/standalone/IdnaUsing.py0000600000372100037210000000203614166627112026015 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys import idna.core # nuitka-skip-unless-imports: idna.core print(idna.core, "idna.idnadata" in sys.modules) Nuitka-0.6.19.1/tests/standalone/BrotliUsing.py0000600000372100037210000000204114166627112026371 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import brotli # nuitka-skip-unless-imports: brotli print("Compressed data:", brotli.compress(b"README.txt")) print("OK.")Nuitka-0.6.19.1/tests/standalone/PyQt5Using.py0000600000372100037210000000371614166627112026132 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QSettings from PyQt5.QtCore import QMetaObject, QObject, pyqtSignal, pyqtSlot # This test is playing with configuration settings and checking that works. # nuitka-skip-unless-imports: PyQt5.QtGui app = QCoreApplication([]) app.setOrganizationName("BOGUS_NAME") app.setOrganizationDomain("bogosity.com") app.setApplicationName("BOGUS") print("OK.") # This test is using signals and will only work if PySide properly accepts # compiled functions as callables. class Communicate(QObject): speak = pyqtSignal(int) def __init__(self, name="", parent=None): QObject.__init__(self, parent) self.setObjectName(name) class Speaker(QObject): @pyqtSlot(int) def on_communicator_speak(self, stuff): print(stuff) speaker = Speaker() someone = Communicate(name="communicator", parent=speaker) QMetaObject.connectSlotsByName(speaker) print("The answer is:", end="") # emit 'speak' signal someone.speak.emit(42) print("Slot should have made output by now.") Nuitka-0.6.19.1/tests/standalone/CtypesUsing.py0000600000372100037210000000472414166627112026417 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # nuitka-project: --standalone import ctypes import os if os.name == "nt": # adapted from http://code.activestate.com/recipes/578513 from ctypes import wintypes # Lets allow this to match Windows API it reflects, # pylint: disable=invalid-name class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): _fields_ = [ ("cb", wintypes.DWORD), ("PageFaultCount", wintypes.DWORD), ("PeakWorkingSetSize", ctypes.c_size_t), ("WorkingSetSize", ctypes.c_size_t), ("QuotaPeakPagedPoolUsage", ctypes.c_size_t), ("QuotaPagedPoolUsage", ctypes.c_size_t), ("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t), ("QuotaNonPagedPoolUsage", ctypes.c_size_t), ("PagefileUsage", ctypes.c_size_t), ("PeakPagefileUsage", ctypes.c_size_t), ("PrivateUsage", ctypes.c_size_t), ] GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo GetProcessMemoryInfo.argtypes = [ wintypes.HANDLE, ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX), wintypes.DWORD, ] GetProcessMemoryInfo.restype = wintypes.BOOL counters = PROCESS_MEMORY_COUNTERS_EX() rv = GetProcessMemoryInfo( ctypes.windll.kernel32.GetCurrentProcess(), ctypes.byref(counters), ctypes.sizeof(counters), ) if not rv: raise ctypes.WinError() print("OK.") else: # TODO: How to get this to work. if False: libc = ctypes.CDLL("libc") printf = libc.printf printf("Hello, %s\n", "World!") print("OK.") Nuitka-0.6.19.1/tests/standalone/run_all.py0000700000372100037210000002367114166627112025601 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for standalone program tests of Nuitka. These tests aim at showing that one specific module works in standalone mode, trying to find issues with that packaging. """ import os import sys # Find nuitka package relative to us. The replacement is for POSIX python # and Windows paths on command line. sys.path.insert( 0, os.path.normpath( os.path.join( os.path.dirname(os.path.abspath(__file__.replace("\\", os.sep))), "..", ".." ) ), ) # isort:start from nuitka.freezer.RuntimeTracing import getRuntimeTraceOfLoadedFiles from nuitka.tools.testing.Common import ( checkLoadedFileAccesses, checkRequirements, compareWithCPython, createSearchMode, decideFilenameVersionSkip, displayFileContents, displayFolderContents, displayRuntimeTraces, reportSkip, setup, test_logger, ) from nuitka.utils.FileOperations import removeDirectory from nuitka.utils.Timing import TimerReport from nuitka.utils.Utils import getOS def displayError(dirname, filename): assert dirname is None dist_path = filename[:-3] + ".dist" displayFolderContents("dist folder", dist_path) inclusion_log_path = filename[:-3] + ".py.inclusion.log" displayFileContents("inclusion log", inclusion_log_path) def main(): # Complex stuff, even more should become common code or project options though. # pylint: disable=too-many-branches,too-many-statements python_version = setup(suite="standalone", needs_io_encoding=True) search_mode = createSearchMode() for filename in sorted(os.listdir(".")): if not filename.endswith(".py"): continue if not decideFilenameVersionSkip(filename): continue active = search_mode.consider(dirname=None, filename=filename) if not active: test_logger.info("Skipping %s" % filename) continue extra_flags = [ "expect_success", "--standalone", "remove_output", # Cache the CPython results for re-use, they will normally not change. "cpython_cache", # To understand what is slow. "timing", ] # skip each test if their respective requirements are not met requirements_met, error_message = checkRequirements(filename) if not requirements_met: reportSkip(error_message, ".", filename) continue if filename == "Urllib3Using.py" and os.name == "nt": reportSkip( "Socket module early import not working on Windows currently", ".", filename, ) continue if "Idna" in filename: # For the warnings of Python2. if python_version < (3,): extra_flags.append("ignore_stderr") if filename == "CtypesUsing.py": extra_flags.append("plugin_disable:pylint-warnings") if filename == "GtkUsing.py": # Don't test on platforms not supported by current Debian testing, and # which should be considered irrelevant by now. if python_version < (2, 7): reportSkip("irrelevant Python version", ".", filename) continue # For the warnings. extra_flags.append("ignore_warnings") if filename.startswith("Win"): if os.name != "nt": reportSkip("Windows only test", ".", filename) continue if filename == "TkInterUsing.py": if getOS() == "Darwin": reportSkip("Not working macOS yet", ".", filename) continue if getOS() == "Windows": reportSkip("Can hang on Windows CI.", ".", filename) continue # For the plug-in information. extra_flags.append("plugin_enable:tk-inter") if filename == "FlaskUsing.py": # For the warnings. extra_flags.append("ignore_warnings") # TODO: Once we have a noqt Plugin, we should use that. if filename == "MatplotlibUsing.py": # For the plugin warnings. extra_flags.append("ignore_warnings") if filename == "NumpyUsing.py": # TODO: Disabled for now. reportSkip("numpy.test not fully working yet", ".", filename) continue if filename == "PandasUsing.py": extra_flags.append("plugin_enable:numpy") extra_flags.append("plugin_disable:pylint-warnings") extra_flags.append("plugin_disable:pyqt5") extra_flags.append("plugin_disable:pyside2") extra_flags.append("plugin_disable:pyside6") if filename == "PmwUsing.py": extra_flags.append("plugin_enable:pmw-freezer") if filename == "OpenGLUsing.py": # For the warnings. extra_flags.append("ignore_warnings") if filename == "GlfwUsing.py": # For the warnings. extra_flags.append("plugin_enable:numpy") if filename == "PasslibUsing.py": # For the warnings. extra_flags.append("ignore_warnings") if filename == "Win32ComUsing.py": # For the warnings. extra_flags.append("ignore_warnings") if filename.startswith(("PySide2", "PySide6", "PyQt5", "PyQt6")): # Don't test on platforms not supported by current Debian testing, and # which should be considered irrelevant by now. if python_version < (2, 7) or ((3,) <= python_version < (3, 7)): reportSkip("irrelevant Python version", ".", filename) continue # For the plug-in information if filename.startswith("PySide2"): extra_flags.append("plugin_enable:pyside6") elif filename.startswith("PySide6"): extra_flags.append("plugin_enable:pyside6") elif filename.startswith("PyQt5"): extra_flags.append("plugin_enable:pyqt5") elif filename.startswith("PyQt6"): extra_flags.append("plugin_enable:pyqt6") test_logger.info( "Consider output of standalone mode compiled program: %s" % filename ) # First compare so we know the program behaves identical. compareWithCPython( dirname=None, filename=filename, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, on_error=displayError, ) # Second check if glibc libraries haven't been accidentally # shipped with the standalone executable found_glibc_libs = [] for dist_filename in os.listdir(os.path.join(filename[:-3] + ".dist")): if os.path.basename(dist_filename).startswith( ( "ld-linux-x86-64.so", "libc.so.", "libpthread.so.", "libm.so.", "libdl.so.", "libBrokenLocale.so.", "libSegFault.so", "libanl.so.", "libcidn.so.", "libcrypt.so.", "libmemusage.so", "libmvec.so.", "libnsl.so.", "libnss_compat.so.", "libnss_db.so.", "libnss_dns.so.", "libnss_files.so.", "libnss_hesiod.so.", "libnss_nis.so.", "libnss_nisplus.so.", "libpcprofile.so", "libresolv.so.", "librt.so.", "libthread_db-1.0.so", "libthread_db.so.", "libutil.so.", ) ): found_glibc_libs.append(dist_filename) if found_glibc_libs: test_logger.warning( "Should not ship glibc libraries with the standalone executable (found %s)" % found_glibc_libs ) sys.exit(1) binary_filename = os.path.join( filename[:-3] + ".dist", filename[:-3] + (".exe" if os.name == "nt" else "") ) # Then use "strace" on the result. with TimerReport( "Determining run time loaded files took %.2f", logger=test_logger ): loaded_filenames = getRuntimeTraceOfLoadedFiles( logger=test_logger, command=[binary_filename] ) illegal_accesses = checkLoadedFileAccesses( loaded_filenames=loaded_filenames, current_dir=os.getcwd() ) if illegal_accesses: displayError(None, filename) displayRuntimeTraces(test_logger, binary_filename) test_logger.warning( "Should not access these file(s): '%r'." % illegal_accesses ) search_mode.onErrorDetected(1) removeDirectory(filename[:-3] + ".dist", ignore_errors=True) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/standalone/ShlibUsing.py0000600000372100037210000000171614166627112026207 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # nuitka-skip-unless-imports: pyexpat import pyexpat print(pyexpat.__doc__) Nuitka-0.6.19.1/tests/standalone/PendulumUsing.py0000600000372100037210000000215714166627112026737 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Pendulum standalone basic test. When this import works, locales are there. """ # nuitka-project: --standalone from __future__ import print_function import pendulum.locales # nuitka-skip-unless-imports: pendulum.locales print("OK")Nuitka-0.6.19.1/tests/standalone/LxmlUsing.py0000600000372100037210000000217714166627112026064 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Lxml standalone basic test. """ from __future__ import print_function import lxml.etree # nuitka-skip-unless-imports: lxml.etree tree = lxml.etree.fromstring("value") assert tree.tag == "root" assert tree.text == "value" print("OK") Nuitka-0.6.19.1/tests/standalone/FlaskUsing.py0000600000372100037210000000216014166627112026200 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from flask import Flask # nuitka-skip-unless-imports: flask app = Flask(__name__) @app.route("/") def main(): return "Welcome!" if __name__ == "__main__": pass # TODO: Find something other meaningful to do. # app.run() Nuitka-0.6.19.1/tests/standalone/zip_importer/0000700000372100037210000000000014167275622026310 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/standalone/zip_importer/ZipImporterMain.py0000600000372100037210000000225414166627112031752 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # nuitka-project: --standalone # nuitka-project: --include-data-file={MAIN_DIRECTORY}/for_import.zip=for_import.zip import sys, os zip_filename = os.path.join(os.path.dirname(__file__) or ".", "for_import.zip") assert os.path.exists(zip_filename) sys.path.insert(0, zip_filename) import zip_module Nuitka-0.6.19.1/tests/standalone/PandasUsing.py0000600000372100037210000000177414166627112026360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Low coverage Pandas importing test. """ import pandas as pd # nuitka-skip-unless-imports: pandas print(pd.__version__)Nuitka-0.6.19.1/tests/standalone/TkInterUsing.py0000600000372100037210000000274714166627112026533 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ TkInter standalone test, trying to make sure it loads. """ # nuitka-project: --standalone # nuitka-project: --enable-plugin=tk-inter from __future__ import print_function # Python3 changed module name. if str is bytes: import Tkinter as tkinter else: import tkinter # nuitka-skip-unless-expression: __import__("Tkinter" if sys.version_info[0] < 3 else "tkinter") try: root = tkinter.Tk() # this will fail in absence of TCL except tkinter.TclError as e: print("TCLError exception happened.") assert "connect to display" in str(e) or "no display" in str(e), str(e) else: print("OK") Nuitka-0.6.19.1/tests/standalone/Urllib3Using.py0000600000372100037210000000617014166627112026461 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function # testing JSON content import json import os # test ssl import socket import ssl from threading import Thread import urllib3 # nuitka-skip-unless-imports: urllib3,ssl if str is bytes: # running on python2, pylint: disable=import-error,I0021 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler #running on python3 else: from http.server import HTTPServer, BaseHTTPRequestHandler started = False def runHTTPServer(): class myServer(BaseHTTPRequestHandler): def do_GET(self): if self.path == "/": self.path = "/index.html" try: file_to_open = open(self.path[1:], "rb").read() self.send_response(200) self.end_headers() self.wfile.write(file_to_open) except IOError: self.send_response(404) self.end_headers() # No logging due to races. def log_request(self, code): pass global port global server for port in range(8020, 9000): server_address = ("127.0.0.1", port) try: server = HTTPServer(server_address, myServer) except OSError: continue else: break global started started = True server.serve_forever() Thread(target=runHTTPServer).start() while not started: pass print("Server started.") # testing request http = urllib3.PoolManager() r = http.request("GET", "http://localhost:%d/" % port) # print response print(r.status, r.data) # make a temporary test file with open("testjson.json", "w") as f: f.write('{"origin": "some, value"}') r = http.request("GET", "http://localhost:%d/testjson.json" % port) data = json.loads(r.data.decode("utf-8")) if "Date" in data: del data["Date"] print("DATA:", data) os.remove("testjson.json") server.shutdown() print("Server shutdown") # TODO: Testing via network is not allowed, but SSL on localhost # is not easy. if False: hostname = "www.google.com" context = ssl.create_default_context() with socket.create_connection((hostname, 443)) as sock: with context.wrap_socket(sock, server_hostname=hostname) as ssock: print(ssock.version()) print("OK.") Nuitka-0.6.19.1/tests/standalone/GtkUsing.py0000600000372100037210000000216114166627112025666 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ pygtk standalone basic test. """ from __future__ import print_function import warnings warnings.filterwarnings("ignore", "") import sys import gtk import pygtk # nuitka-skip-unless-imports: pygtk pygtk.require("2.0") print("OK") Nuitka-0.6.19.1/tests/standalone/PyQt5Plugins.py0000600000372100037210000000176514166627112026470 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from PyQt5 import QtGui # nuitka-skip-unless-imports: PyQt5.QtGui print(QtGui.QImageReader.supportedImageFormats()) Nuitka-0.6.19.1/tests/standalone/MatplotlibUsing.py0000600000372100037210000000263314166627112027254 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test using matplotlib, should actually do something with it. """ import matplotlib # pylint:disable=unused-import # nuitka-skip-unless-imports: matplotlib # nuitka-project: --standalone # Make sure, the usual bad ones are not included with anti-bloat. # nuitka-project: --enable-plugin=anti-bloat # nuitka-project: --noinclude-setuptools-mode=error # nuitka-project: --noinclude-pytest-mode=error # nuitka-project: --noinclude-custom-mode=numpy.distutils:error # nuitka-project: --noinclude-custom-mode=IPython:error print("OK.")Nuitka-0.6.19.1/tests/standalone/NumpyUsing.py0000600000372100037210000000257714166627112026264 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function # nuitka-skip-unless-imports: numpy # nuitka-project: --standalone # nuitka-project: --enable-plugin=numpy # Make sure, the usual bad ones are not included with anti-bloat. # nuitka-project: --enable-plugin=anti-bloat # nuitka-project: --noinclude-setuptools-mode=error # nuitka-project: --noinclude-pytest-mode=error # nuitka-project: --noinclude-custom-mode=numpy.distutils:error import numpy as np a = np.arange(15).reshape(3, 5) print("An array", a) print("OK.")Nuitka-0.6.19.1/tests/standalone/OpenGLUsing.py0000600000372100037210000000166314166627112026273 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import OpenGL # nuitka-skip-unless-imports: OpenGL Nuitka-0.6.19.1/tests/standalone/PySide6Using.py0000600000372100037210000000321714166627112026427 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This test is using signals and will only work if PySide properly accepts # compiled functions as callables. from __future__ import print_function from PySide6.QtCore import QMetaObject, QObject, Signal, Slot # nuitka-skip-unless-imports: PySide6.QtCore class Communicate(QObject): speak = Signal(int) def __init__(self, name="", parent=None): QObject.__init__(self, parent) self.setObjectName(name) class Speaker(QObject): @Slot(int) def on_communicator_speak(self, stuff): print(stuff) speaker = Speaker() someone = Communicate(name="communicator", parent=speaker) QMetaObject.connectSlotsByName(speaker) print("The answer is:", end="") # emit 'speak' signal someone.speak.emit(42) print("Slot should have made output by now.") Nuitka-0.6.19.1/tests/standalone/PasslibUsing.py0000600000372100037210000000205214166627112026535 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from passlib.hash import sha512_crypt as sha512 # nuitka-skip-unless-imports: passlib print("hello") print(len(sha512.using(rounds=1000).hash("password"))) print("bye") Nuitka-0.6.19.1/tests/standalone/GlfwUsing.py0000600000372100037210000000165614166627112026050 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import glfw # nuitka-skip-unless-imports: glfwNuitka-0.6.19.1/tests/standalone/RsaUsing.py0000600000372100037210000000245314166627112025672 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import rsa # nuitka-skip-unless-imports: rsa (tambe_pub, tambe_priv) = rsa.newkeys(512) message = "beautiful Tambe!".encode("utf8") encrypted_msg = rsa.encrypt(message, tambe_pub) message = rsa.decrypt(encrypted_msg, tambe_priv) def encryption_decryption(): """Function to test encryption and decryption""" assert message.decode("utf8") == "beautiful Tambe!" if __name__ == "__main__": encryption_decryption() Nuitka-0.6.19.1/tests/standalone/SocketUsing.py0000600000372100037210000000273614166627112026401 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- coding: utf-8 -*- # Copyright 2021, Paweł Kierzkowski, mailto: # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that shows that the socket module can properly be used. """ import signal import socket import sys # Set up a timeout, seems to happen that below call stalls. def onTimeout(_signum, _frame): sys.exit(0) # Not available on Windows, but there we didn't see the problem anyway, # not going to make this use threading for now. try: signal.signal(signal.SIGALRM, onTimeout) signal.alarm(1) except AttributeError: pass # Call to socket.getfqdn with a non-local address will cause libresolv.so glibc # library to be loaded socket.getfqdn("1.1.1.1") Nuitka-0.6.19.1/tests/standalone/PmwUsing.py0000600000372100037210000000203314166627112025702 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import Pmw # nuitka-skip-unless-expression: __import__("Tkinter" if sys.version_info[0] < 3 else "tkinter") # nuitka-skip-unless-imports: Pmw print("OK.")Nuitka-0.6.19.1/tests/standalone/Issue116_2.py0000600000372100037210000000163514166627112025701 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python test originally created or extracted from other peoples work. The # parts from me are licensed as below. It is at least Free Software where # it's copied from other people. In these cases, that will normally be # indicated. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("4B4159".decode("hex")) Nuitka-0.6.19.1/tests/programs/0000700000372100037210000000000014167275622023267 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/0000700000372100037210000000000014167275622027362 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/0000700000372100037210000000000014167275622032000 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package1/0000700000372100037210000000000014167275622034325 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package1/SomeModuleC.py0000600000372100037210000000140114166627112037043 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package1/SomeModuleD.py0000600000372100037210000000140114166627112037044 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package1/__init__.py0000600000372100037210000000140114166627112036426 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package2/0000700000372100037210000000000014167275622034326 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package2/SomeModuleB.py0000600000372100037210000000140114166627112037043 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package2/SomeModuleA.py0000600000372100037210000000140114166627112037042 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/sub_package2/__init__.py0000600000372100037210000000140114166627112036427 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/some_package/__init__.py0000600000372100037210000000140114166627112034101 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/pkgutil_itermodules/PkgUtilIterModulesMain.py0000600000372100037210000000255014166627112034273 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import pkgutil import some_package.sub_package1.SomeModuleC import some_package.sub_package1.SomeModuleD import some_package.sub_package2.SomeModuleA import some_package.sub_package2.SomeModuleB print("Checking with 'pkg_util.iter_modules' what was included:") pkg = __import__("some_package") print("Package is", pkg) it = pkgutil.iter_modules(pkg.__path__) for r in it: print(r[1], r[2]) if r[2]: sub_pkg = __import__("some_package." + r[1]) for r2 in pkgutil.iter_modules(sub_pkg.__path__): print(" ", r2[1], r2[2]) print("Done") Nuitka-0.6.19.1/tests/programs/stdlib_overload/0000700000372100037210000000000014167275622026443 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/stdlib_overload/StdlibOverloadMain.py0000600000372100037210000000216614166627112032540 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Main importing nearby package") import pyexpat from some_package import normal_importing, star_importing try: print(pyexpat.defined_in_pyexpat) except AttributeError: print("Must be Python3, where absolute imports are default.") print("Main importing from package doing star import") print("Main importing from package doing normal import") print("Done.") Nuitka-0.6.19.1/tests/programs/stdlib_overload/pyexpat.py0000600000372100037210000000143714166627112030510 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # defined_in_pyexpat = "see me" Nuitka-0.6.19.1/tests/programs/stdlib_overload/some_package/0000700000372100037210000000000014167275622031061 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/stdlib_overload/some_package/star_importing.py0000600000372100037210000000225414166627112034473 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Make a star import, and demonstrate that it has impact on the modules dict. """ from __future__ import print_function from .pyexpat import * # pylint: disable=unused-wildcard-import,wildcard-import print("some_package.star_importing, doing the star import") print("Before", sorted(x for x in dir() if x != "__compiled__")) lala = 1 print("After", sorted(x for x in dir() if x != "__compiled__")) print("Finished") Nuitka-0.6.19.1/tests/programs/stdlib_overload/some_package/pyexpat.py0000600000372100037210000000145214166627112033123 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # defined_in_pyexpat_subpackage = "see me" Nuitka-0.6.19.1/tests/programs/stdlib_overload/some_package/normal_importing.py0000600000372100037210000000157114166627112035013 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import pyexpat print("Imported pyexpat, should use our one.") print([x for x in dir(pyexpat) if x != "__compiled__"]) Nuitka-0.6.19.1/tests/programs/stdlib_overload/some_package/__init__.py0000600000372100037210000000140114166627112033162 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/named_imports/0000700000372100037210000000000014167275622026130 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/named_imports/NamedImportsMain.py0000600000372100037210000000151614166627112031710 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from some_package import SomeModule print(__name__, "imported", SomeModule) Nuitka-0.6.19.1/tests/programs/named_imports/some_package/0000700000372100037210000000000014167275622030546 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/named_imports/some_package/sub_package/0000700000372100037210000000000014167275622033012 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/named_imports/some_package/sub_package/SomeModule.py0000600000372100037210000000140114166627112035425 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/named_imports/some_package/SomeModule.py0000600000372100037210000000140114166627112033161 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/named_imports/some_package/__init__.py0000600000372100037210000000147014166627112032655 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .sub_package import SomeModule print(SomeModule) Nuitka-0.6.19.1/tests/programs/dunderinit_imports/0000700000372100037210000000000014167275622027211 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/dunderinit_imports/package/0000700000372100037210000000000014167275622030604 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/dunderinit_imports/package/SubModule.py0000600000372100037210000000143514166627112033054 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .__init__ import value Nuitka-0.6.19.1/tests/programs/dunderinit_imports/package/__init__.py0000600000372100037210000000153114166627112032711 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("Package as __name__", __name__) value = 1 Nuitka-0.6.19.1/tests/programs/dunderinit_imports/DunderInitImportsMain.py0000600000372100037210000000143214166627112034007 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import package.SubModule Nuitka-0.6.19.1/tests/programs/case_imports1/0000700000372100037210000000000014167275622026040 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports1/path1/0000700000372100037210000000000014167275622027055 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports1/path1/Some_Package/0000700000372100037210000000000014167275622031373 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports1/path1/Some_Package/__init__.py0000600000372100037210000000143714166627112033505 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Package") Nuitka-0.6.19.1/tests/programs/case_imports1/path1/Some_Module.py0000600000372100037210000000143614166627112031637 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Module") Nuitka-0.6.19.1/tests/programs/case_imports1/CasedImportingMain.py0000600000372100037210000000145014166627112032123 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import Some_Module import some_package Nuitka-0.6.19.1/tests/programs/case_imports1/path2/0000700000372100037210000000000014167275622027056 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports1/path2/some_module.py0000600000372100037210000000143614166627112031740 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is some_module") Nuitka-0.6.19.1/tests/programs/case_imports1/path2/some_package/0000700000372100037210000000000014167275622031474 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports1/path2/some_package/__init__.py0000600000372100037210000000143714166627112033606 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is some_package") Nuitka-0.6.19.1/tests/programs/main_raises2/0000700000372100037210000000000014167275622025643 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/main_raises2/ErrorRaising.py0000600000372100037210000000145014166627112030617 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def raiseException(): return 1 / 0 Nuitka-0.6.19.1/tests/programs/main_raises2/ErrorInFunctionMain.py0000600000372100037210000000207014166627112032103 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Just plain exception from the function level, supposed to report the correct file and line def generator_function(): import ErrorRaising x = (lambda: ErrorRaising.raiseException() for z in range(3)) next(x)() def normal_function(): y = generator_function() y() normal_function() Nuitka-0.6.19.1/tests/programs/package_init_import/0000700000372100037210000000000014167275622027277 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_init_import/PackageInitImportMain.py0000600000372100037210000000146714166627112034034 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import some_package print(some_package.PackageLocal) Nuitka-0.6.19.1/tests/programs/package_init_import/some_package/0000700000372100037210000000000014167275622031715 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_init_import/some_package/PackageLocal.py0000600000372100037210000000176014166627112034575 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys print( "Imported PackageLocal", __name__, "in", __package__ if __package__ is not None or sys.version_info[:2] != (3, 2) else ".".join(__name__.split(".")[:-1]), ) Nuitka-0.6.19.1/tests/programs/package_init_import/some_package/__init__.py0000600000372100037210000000222114166627112034017 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys print( "This is some_package", __name__, "in", "__package__: ", __package__ if __package__ is not None or sys.version_info[:2] != (3, 2) else ".".join(__name__.split(".")[:-1]), ) try: import PackageLocal except ImportError: print("This must be Python3, doing local import then.") from . import PackageLocal Nuitka-0.6.19.1/tests/programs/reimport_main_static/0000700000372100037210000000000014167275622027503 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/reimport_main_static/ImportItselfStaticMain.py0000600000372100037210000000160214166627112034446 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys import ImportItselfStaticMain print("Here I am before import", __name__) print("Here I am after import", __name__) Nuitka-0.6.19.1/tests/programs/multiprocessing_using/0000700000372100037210000000000014167275622027723 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/multiprocessing_using/MultiprocessingUsingMain.py0000600000372100037210000000223114166627112035271 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that checks that accelerated mode usage of multiprocessing works too. """ # nuitka-project-if: {OS} == "Windows": # nuitka-project: --enable-plugin=multiprocessing # nuitka-project-if: {OS} != "Windows": # nuitka-project: --disable-plugin=multiprocessing from multiprocessing import freeze_support if __name__ == "__main__": freeze_support() from foo import entry entry.main() Nuitka-0.6.19.1/tests/programs/multiprocessing_using/foo/0000700000372100037210000000000014167275622030506 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/multiprocessing_using/foo/__main__.py0000600000372100037210000000150414166627112032574 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from foo import entry if __name__ == "__main__": entry.main() Nuitka-0.6.19.1/tests/programs/multiprocessing_using/foo/entry.py0000600000372100037210000000333614166627112032222 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from multiprocessing import Pipe, Process class MyProcess(Process): def __init__(self, connection): super(MyProcess, self).__init__() self.connection = connection self.close_issued = False def run(self): while not self.close_issued: op, arg = self.connection.recv() if op == "add": self.connection.send(arg + 1) elif op == "close": self.close_issued = True elif op == "method": self.connection.send(repr(self.run)) def main(): server_channel, client_channel = Pipe() my_process = MyProcess(client_channel) my_process.start() server_channel.send(("add", 4)) print(server_channel.recv()) server_channel.send(("add", 12)) print(server_channel.recv()) server_channel.send(("method", None)) print(("compiled" in server_channel.recv()) == ("compiled" in repr(MyProcess.run))) server_channel.send(("close", 0)) Nuitka-0.6.19.1/tests/programs/multiprocessing_using/foo/__init__.py0000600000372100037210000000140114166627112032607 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/reimport_main_dynamic/0000700000372100037210000000000014167275622027640 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/reimport_main_dynamic/ImportItselfDynamicMain.py0000600000372100037210000000161714166627112034746 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys print("Here I am before import", __name__) c = "ImportItselfDynamicMain" __import__(c) print("Here I am after import", __name__) Nuitka-0.6.19.1/tests/programs/run_all.py0000700000372100037210000001524614167275603025307 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for program tests of Nuitka. Program tests are typically aiming at checking specific module constellations and making sure the details are being right there. These are synthetic small programs, each of which try to demonstrate one or more points or special behaviour. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( compareWithCPython, createSearchMode, my_print, reportSkip, scanDirectoryForTestCaseFolders, setup, withPythonPathChange, ) def main(): # Complex stuff, even more should become common code though. # pylint: disable=too-many-branches,too-many-statements python_version = setup(suite="programs", needs_io_encoding=True) search_mode = createSearchMode() extra_options = os.environ.get("NUITKA_EXTRA_OPTIONS", "") for filename, filename_main in scanDirectoryForTestCaseFolders("."): # For these, we expect that they will fail. expected_errors = [ "module_exits", "main_raises", "main_raises2", "package_contains_main", ] # After Python3 those have been made to work. if python_version < (3, 5): expected_errors.append("cyclic_imports") # Allowed with Python3, packages need no more "__init__.py" if python_version < (3,): expected_errors.append("package_missing_init") # Allowed with Python3.5 only: if python_version < (3, 5): expected_errors.append("package_init_issue") # Allowed with Python3, name imports can be module imports if python_version < (3,): expected_errors.append("named_imports") extra_variant = [] if filename not in expected_errors: extra_flags = ["expect_success"] else: extra_flags = ["expect_failure"] # We annotate some tests, use that to lower warnings. extra_flags.append("plugin_enable:pylint-warnings") if filename in ( "reimport_main_static", "package_missing_init", "dash_import", "package_contains_main", "case_imports3", "import_variants", "package_init_import", "pkgutil_itermodules", ): extra_flags.append("ignore_warnings") extra_flags.append("remove_output") extra_flags.append("--follow-imports") # Use the original __file__ value, at least one case warns about things # with filename included, but for pkgutil iteration, make sure we do not # see original Python dirs. if filename != "pkgutil_itermodules": extra_flags.append("--file-reference-choice=original") else: extra_flags.append("--file-reference-choice=runtime") # Run it as a package and also as directory. if filename == "package_program": # Not really supported for 2.6 if python_version >= (2, 7): extra_variant.append("--python-flag=-m") # Cannot include the files with syntax errors, these would then become # ImportError, but that's not the test. In all other cases, use two # step execution, which will not add the program original source to # PYTHONPATH. if filename != "syntax_errors": extra_flags.append("two_step_execution") else: extra_flags.append("binary_python_path") if filename == "plugin_import": os.environ["NUITKA_EXTRA_OPTIONS"] = ( extra_options + " --include-package=some_package" ) elif filename == "reimport_main_dynamic": if python_version < (3,): os.environ[ "NUITKA_EXTRA_OPTIONS" ] = extra_options + " --include-plugin-directory=%s" % ( os.path.abspath(filename) ) else: os.environ[ "NUITKA_EXTRA_OPTIONS" ] = extra_options + " --include-plugin-files=%s/*.py" % ( os.path.abspath(filename) ) extra_flags.append("ignore_warnings") elif filename == "multiprocessing_using": # TODO: Still true? if sys.platform == "darwin" and python_version >= (3, 8): reportSkip("Hangs for unknown reasons", ".", filename) continue else: os.environ["NUITKA_EXTRA_OPTIONS"] = extra_options active = search_mode.consider(dirname=None, filename=filename) if active: my_print("Consider output of recursively compiled program:", filename) extra_python_path = [ os.path.abspath(os.path.join(filename, entry)) for entry in os.listdir(filename) if entry.startswith("path") ] if extra_python_path: my_print("Applying extra PYTHONPATH %r." % extra_python_path) with withPythonPathChange(extra_python_path): compareWithCPython( dirname=filename, filename=filename_main, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=False, ) if extra_variant: my_print("Extra variation %r." % extra_variant) compareWithCPython( dirname=filename, filename=filename_main, extra_flags=extra_flags + extra_variant, search_mode=search_mode, needs_2to3=False, ) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/programs/dash_main/0000700000372100037210000000000014167275622025212 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/dash_main/Dash-Main.py0000600000372100037210000000145114166627112027322 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is running from", __file__) Nuitka-0.6.19.1/tests/programs/unicode_bom/0000700000372100037210000000000014167275622025552 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/unicode_bom/unicode_bom.py0000600000372100037210000000151614166627112030406 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # import unicodedata print("This is from file with BOM unicode marker") Nuitka-0.6.19.1/tests/programs/unicode_bom/UnicodeBomMain.py0000600000372100037210000000170314166627112030752 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Program that imports a BOM using module. """ from __future__ import print_function import unicode_bom # pylint: disable=unused-import print("Importing unicode BOM file:") print("OK.") Nuitka-0.6.19.1/tests/programs/package_init_issue/0000700000372100037210000000000014167275622027115 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_init_issue/PackageInitIssueMain.py0000600000372100037210000000142514166627112033462 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import some_package Nuitka-0.6.19.1/tests/programs/package_init_issue/some_package/0000700000372100037210000000000014167275622031533 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_init_issue/some_package/child_package/0000700000372100037210000000000014167275622034271 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_init_issue/some_package/child_package/SomeModule.py0000600000372100037210000000143614166627112036714 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .. import child_package Nuitka-0.6.19.1/tests/programs/package_init_issue/some_package/child_package/__init__.py0000600000372100037210000000143314166627112036377 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .SomeModule import * Nuitka-0.6.19.1/tests/programs/package_init_issue/some_package/__init__.py0000600000372100037210000000143614166627112033644 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .child_package import * Nuitka-0.6.19.1/tests/programs/module_exits/0000700000372100037210000000000014167275622025770 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/module_exits/Main.py0000600000372100037210000000152514166627112027225 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print(type(__builtins__)) import ErrorExitingModule print("Should not get here!") Nuitka-0.6.19.1/tests/programs/module_exits/ErrorExitingModule.py0000600000372100037210000000154514166627112032132 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys print(type(__builtins__)) sys.exit("Module doing sys.exit") print("This won't happen!") Nuitka-0.6.19.1/tests/programs/pkgutil_usage/0000700000372100037210000000000014167275622026132 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_usage/package/0000700000372100037210000000000014167275622027525 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/pkgutil_usage/package/DATA_FILE.txt0000600000372100037210000000001514166627112031566 0ustar nuitka-buildslavenuitka-buildslave00000000000000DATA_CONTENT Nuitka-0.6.19.1/tests/programs/pkgutil_usage/package/__init__.py0000600000372100037210000000161614166627112031636 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import pkgutil __version__ = ( pkgutil.get_data(__package__ or __name__, "DATA_FILE.txt").decode("ascii").strip() ) print(__version__) Nuitka-0.6.19.1/tests/programs/pkgutil_usage/PkgUtilUsageMain.py0000600000372100037210000000142014166627112031646 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import package Nuitka-0.6.19.1/tests/programs/relative_import/0000700000372100037210000000000014167275622026474 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/relative_import/RelativeImportMain.py0000600000372100037210000000151214166627112032614 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import absolute_import import dircache print(dircache) Nuitka-0.6.19.1/tests/programs/relative_import/dircache.py0000600000372100037210000000140114166627112030600 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/package_contains_main/0000700000372100037210000000000014167275622027564 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_contains_main/PackageContainsMain.py0000600000372100037210000000142514166627112033773 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from . import local Nuitka-0.6.19.1/tests/programs/package_contains_main/local.py0000600000372100037210000000144114166627112031224 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Imported local package") Nuitka-0.6.19.1/tests/programs/package_contains_main/__init__.py0000600000372100037210000000140114166627112031665 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/plugin_import/0000700000372100037210000000000014167275622026157 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/plugin_import/PluginImportMain.py0000600000372100037210000000153314166627112031765 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # name = "some_module" module = getattr(__import__("some_package", fromlist=[name]), name) Nuitka-0.6.19.1/tests/programs/plugin_import/some_package/0000700000372100037210000000000014167275622030575 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/plugin_import/some_package/some_module.py0000600000372100037210000000141514166627112033454 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("hi") Nuitka-0.6.19.1/tests/programs/plugin_import/some_package/__init__.py0000600000372100037210000000140314166627112032700 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Nuitka-0.6.19.1/tests/programs/package_overload/0000700000372100037210000000000014167275622026555 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_overload/Main.py0000600000372100037210000000152414166627112030011 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from foo import bar, bar2, not_overloaded print(bar, not_overloaded) print(bar2) Nuitka-0.6.19.1/tests/programs/package_overload/foo/0000700000372100037210000000000014167275622027340 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_overload/foo/bar2.py0000600000372100037210000000140114166627112030530 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/package_overload/foo/__init__.py0000600000372100037210000000143714166627112031452 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # bar = 42 not_overloaded = 45 Nuitka-0.6.19.1/tests/programs/package_overload/foo/bar.py0000600000372100037210000000140114166627112030446 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/import_variants/0000700000372100037210000000000014167275622026510 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/import_variants/ImportVariationsMain.py0000600000372100037210000000175514166627112033205 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import some_package.Child2 print("*** Main: Importing") print("*** Main: Imported") print("*** Main: Some package", some_package) print("*** Main: Imported package child", some_package.Child2) Nuitka-0.6.19.1/tests/programs/import_variants/some_package/0000700000372100037210000000000014167275622031126 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/import_variants/some_package/Child2.py0000600000372100037210000000211214166627112032575 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("*** Child2: Begin", __name__) try: import Child1 except ImportError: print("This must be Python3, doing local import then.") from . import Child1 print("*** Child2: Child2 is in", __package__) print("*** Child2: Imported nearby child", Child1) print("*** Child2: End") Nuitka-0.6.19.1/tests/programs/import_variants/some_package/Child3.py0000600000372100037210000000146614166627112032611 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("*** Child3: Begin") print("*** Child3: End") Nuitka-0.6.19.1/tests/programs/import_variants/some_package/Child1.py0000600000372100037210000000166214166627112032605 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function from . import Child3 as localname print("*** Child1: Begin") print("*** Child1: Imported Child3", localname) print("*** Child1: End") Nuitka-0.6.19.1/tests/programs/import_variants/some_package/__init__.py0000600000372100037210000000174214166627112033237 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("*** some_package: Coming from '%s'" % __file__.replace(".pyc", ".py")) print("*** some_package: Path is '%s'" % __path__) print("*** some_package: Package is '%s'" % __package__) Nuitka-0.6.19.1/tests/programs/package_program/0000700000372100037210000000000014167275622026411 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_program/PackageAsMain/0000700000372100037210000000000014167275622031035 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_program/PackageAsMain/__main__.py0000600000372100037210000000313614166627112033126 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test case, where __main__ is the main program in a directory. """ from __future__ import print_function import sys # There is a fake module with just "__name__" for package mode created by CPython. real_name = __name__ print("Hello world!") print("I am thinking of myself as __name__", repr(__name__)) print("Module object has __name__", repr(sys.modules[real_name].__name__)) print("My package value is", repr(__package__)) if not __package__: print("Module has package value", repr(sys.modules[real_name].__package__)) print("Module repr", sys.modules[real_name]) print("__file__", __file__) print("Try to import from module in main package:") for_import = "something from __main__" try: from . import for_import as value print("Imported", value) except (ImportError, SystemError, ValueError) as e: print("Gave exception:", e) Nuitka-0.6.19.1/tests/programs/package_program/PackageAsMain/__init__.py0000600000372100037210000000157014166627112033145 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function for_import = "something from __init__" print("Importing", __name__, "package") Nuitka-0.6.19.1/tests/programs/package_module_collision/0000700000372100037210000000000014167275622030302 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_module_collision/something.py0000600000372100037210000000144114166627112032645 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Importing something.py") Nuitka-0.6.19.1/tests/programs/package_module_collision/PackageAndModuleNamedSameMain.py0000600000372100037210000000160514166627112036356 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import Something import something print("This would collide on Windows generated source names:") print(Something) print(something) Nuitka-0.6.19.1/tests/programs/package_module_collision/Something/0000700000372100037210000000000014167275622032237 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_module_collision/Something/__init__.py0000600000372100037210000000145214166627112034346 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Importing Something/__init__.py") Nuitka-0.6.19.1/tests/programs/main_raises/0000700000372100037210000000000014167275622025561 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/main_raises/ErrorRaising.py0000600000372100037210000000145014166627112030535 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def raiseException(): return 1 / 0 Nuitka-0.6.19.1/tests/programs/main_raises/ErrorMain.py0000600000372100037210000000161714166627112030032 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Just plain exception from the module level, supposed to report the correct file and line import ErrorRaising ErrorRaising.raiseException() Nuitka-0.6.19.1/tests/programs/dash_import/0000700000372100037210000000000014167275622025600 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/dash_import/dash-module.py0000600000372100037210000000146114166627112030352 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Module with dash imported as", __name__) Nuitka-0.6.19.1/tests/programs/dash_import/plus+module.py0000600000372100037210000000146114166627112030414 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Module with plus imported as", __name__) Nuitka-0.6.19.1/tests/programs/dash_import/DashImportMain.py0000600000372100037210000000157014166627112031030 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # __import__("dash-module") b = "dash-module" __import__(b) __import__("plus+module") c = "plus+module" __import__(c) Nuitka-0.6.19.1/tests/programs/case_imports2/0000700000372100037210000000000014167275622026041 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports2/path1/0000700000372100037210000000000014167275622027056 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports2/path1/some_module.py0000600000372100037210000000140114166627112031730 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/case_imports2/path1/some_package/0000700000372100037210000000000014167275622031474 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports2/path1/some_package/__init__.py0000600000372100037210000000140114166627112033575 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/case_imports2/CasedImportingMain.py0000600000372100037210000000145014166627112032124 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import Some_Module import some_package Nuitka-0.6.19.1/tests/programs/case_imports2/path2/0000700000372100037210000000000014167275622027057 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports2/path2/Some_Package/0000700000372100037210000000000014167275622031375 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports2/path2/Some_Package/__init__.py0000600000372100037210000000143714166627112033507 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Package") Nuitka-0.6.19.1/tests/programs/case_imports2/path2/Some_Module.py0000600000372100037210000000143614166627112031641 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Module") Nuitka-0.6.19.1/tests/programs/deep/0000700000372100037210000000000014167275622024204 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/deep/DeepProgramMain.py0000600000372100037210000000153614166627112027571 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import some_package.deep_package.DeepDeepChild import some_package.DeepChild print("Done.") Nuitka-0.6.19.1/tests/programs/deep/some_package/0000700000372100037210000000000014167275622026622 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/deep/some_package/deep_package/0000700000372100037210000000000014167275622031212 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/deep/some_package/deep_package/DeepDeepChild.py0000600000372100037210000000155414166627112034204 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function from .. import DeepBrother print("This is DeepDeepChild talking.") Nuitka-0.6.19.1/tests/programs/deep/some_package/deep_package/__init__.py0000600000372100037210000000167014166627112033323 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys print("The deep package has __package__", __package__) print("The deep package has __package__", sys.modules[__name__].__package__) Nuitka-0.6.19.1/tests/programs/deep/some_package/DeepBrother.py0000600000372100037210000000172414166627112031377 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("This is deep brother module talking.", __name__) def someBrotherFunction(): pass print("The __module__ of function here is", someBrotherFunction.__module__) Nuitka-0.6.19.1/tests/programs/deep/some_package/DeepChild.py0000600000372100037210000000161514166627112031014 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("Importing child.") class A: pass print("Class defined here, has these vars", vars(A)) Nuitka-0.6.19.1/tests/programs/deep/some_package/__init__.py0000600000372100037210000000140114166627112030723 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/programs/package_missing_init/0000700000372100037210000000000014167275622027436 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_missing_init/PackageMissingInitMain.py0000600000372100037210000000163614166627112034330 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import some_package.some_module import some_package.sub_package.some_sub_module print(some_package.__package__) print(some_package.sub_package.__package__) Nuitka-0.6.19.1/tests/programs/package_missing_init/some_package/0000700000372100037210000000000014167275622032054 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_missing_init/some_package/sub_package/0000700000372100037210000000000014167275622034320 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_missing_init/some_package/sub_package/some_sub_module.py0000600000372100037210000000172014166627112040047 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This must be Python3 which no longer needs __init__.py to accept a package.") import sys print("The parent path is", sys.modules["some_package.sub_package"].__path__) def s(): pass print(s) Nuitka-0.6.19.1/tests/programs/package_missing_init/some_package/some_module.py0000600000372100037210000000170414166627112034734 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This must be Python3 which no longer needs __init__.py to accept a package.") import sys print("The parent path is", sys.modules["some_package"].__path__) def f(): pass print(f) Nuitka-0.6.19.1/tests/programs/with space/0000700000372100037210000000000014167275622025316 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/with space/Space Main.py0000700000372100037210000000147214166627112027571 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Hello from main program with space in its paths") Nuitka-0.6.19.1/tests/programs/case_imports3/0000700000372100037210000000000014167275622026042 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports3/path1/0000700000372100037210000000000014167275622027057 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports3/path1/Some_Package/0000700000372100037210000000000014167275622031375 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports3/path1/Some_Package/__init__.py0000600000372100037210000000145214166627112033504 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Package from path1") Nuitka-0.6.19.1/tests/programs/case_imports3/path1/Some_Module.py0000600000372100037210000000145114166627112031636 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Module from path1") Nuitka-0.6.19.1/tests/programs/case_imports3/CasedImportingMain.py0000600000372100037210000000206314166627112032126 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # try: import some_module except ImportError: print("Cannot import wrongly cased module.") else: print("OK, imported wrongly cased module.") try: import some_package except ImportError: print("Cannot import wrongly cased package.") else: print("OK, imported wrongly cased package.") Nuitka-0.6.19.1/tests/programs/case_imports3/path2/0000700000372100037210000000000014167275622027060 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports3/path2/Some_Package/0000700000372100037210000000000014167275622031376 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/case_imports3/path2/Some_Package/__init__.py0000600000372100037210000000145214166627112033505 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Package from path2") Nuitka-0.6.19.1/tests/programs/case_imports3/path2/Some_Module.py0000600000372100037210000000145114166627112031637 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("This is Some_Module from path2") Nuitka-0.6.19.1/tests/programs/package_code/0000700000372100037210000000000014167275622025654 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_code/PackageInitCodeMain.py0000600000372100037210000000144014166627112032000 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import some_package.SomeModule Nuitka-0.6.19.1/tests/programs/package_code/some_package/0000700000372100037210000000000014167275622030272 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_code/some_package/SomeModule.py0000600000372100037210000000145214166627112032713 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Thanks for importing SomeModule") Nuitka-0.6.19.1/tests/programs/package_code/some_package/__init__.py0000600000372100037210000000145114166627112032400 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Thanks for importing", __name__) Nuitka-0.6.19.1/tests/programs/cyclic_imports/0000700000372100037210000000000014167275622026312 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/cyclic_imports/CyclicImportsMain.py0000600000372100037210000000144114166627112032251 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import cyclic_importing_package Nuitka-0.6.19.1/tests/programs/cyclic_imports/cyclic_importing_package/0000700000372100037210000000000014167275622033323 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/cyclic_imports/cyclic_importing_package/Child2.py0000600000372100037210000000153514166627112035002 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Child2:", __name__) from . import Child1 print("Value of Child1", Child1.__name__) Nuitka-0.6.19.1/tests/programs/cyclic_imports/cyclic_importing_package/Child1.py0000600000372100037210000000153514166627112035001 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Child1:", __name__) from . import Child2 print("Value of Child2", Child2.__name__) Nuitka-0.6.19.1/tests/programs/cyclic_imports/cyclic_importing_package/__init__.py0000600000372100037210000000147414166627112035436 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("package __init__:", __name__) from . import Child1 Nuitka-0.6.19.1/tests/programs/module_attributes/0000700000372100037210000000000014167275622027022 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/0000700000372100037210000000000014167275622031665 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/Nearby1.py0000600000372100037210000000320514166627112033534 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print( "__package__: ", __package__ if __package__ is not None or sys.version_info[:2] != (3, 2) else ".".join(__name__.split(".")[:-1]), ) Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/__init__.py0000600000372100037210000000300014166627112033763 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print("__package__: ", __package__) Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/0000700000372100037210000000000014167275622034531 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/Nearby2.py0000600000372100037210000000320514166627112036401 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print( "__package__: ", __package__ if __package__ is not None or sys.version_info[:2] != (3, 2) else ".".join(__name__.split(".")[:-1]), ) Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/package_level3/0000700000372100037210000000000014167275622037376 5ustar nuitka-buildslavenuitka-buildslave00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/package_level3/Nearby3.pyNuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/package_level3/Nearby0000600000372100037210000000320514166627112040535 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print( "__package__: ", __package__ if __package__ is not None or sys.version_info[:2] != (3, 2) else ".".join(__name__.split(".")[:-1]), ) ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/package_level3/__init__.pyNuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/package_level3/__init0000600000372100037210000000300014166627112040547 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print("__package__: ", __package__) Nuitka-0.6.19.1/tests/programs/module_attributes/package_level1/package_level2/__init__.py0000600000372100037210000000300014166627112036627 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__cached__" in d: d["__cached__"] = "<__cached__ removed>" if "__spec__" in d: d["__spec__"].loader = "loader removed" d["__spec__"].origin = "origin removed" d["__spec__"].submodule_search_locations = "submodule_search_locations removed" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) print("__name__: ", __name__) print("__package__: ", __package__) Nuitka-0.6.19.1/tests/programs/module_attributes/ModuleAttributesMain.py0000600000372100037210000000265614166627112033502 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that covers all module attributes. """ from __future__ import print_function import package_level1.Nearby1 import package_level1.package_level2.Nearby2 import package_level1.package_level2.package_level3 import package_level1.package_level2.package_level3.Nearby3 def displayDict(d): d = dict(d) del d["displayDict"] del d["__builtins__"] if "__loader__" in d: d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d["__file__"] = "<__file__ removed>" if "__compiled__" in d: del d["__compiled__"] import pprint return pprint.pformat(d) print(displayDict(globals())) # pylint: disable=unused-import Nuitka-0.6.19.1/tests/programs/absolute_import/0000700000372100037210000000000014167275622026477 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/absolute_import/foobar/0000700000372100037210000000000014167275622027747 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/absolute_import/foobar/local.py0000600000372100037210000000155714166627112031417 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Just trace the import. """ from __future__ import print_function print("This is for relative import.") Nuitka-0.6.19.1/tests/programs/absolute_import/foobar/util.py0000600000372100037210000000153414166627112031275 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module that provides a function for import. """ def someFunction(): return "hi" Nuitka-0.6.19.1/tests/programs/absolute_import/foobar/foobar.py0000600000372100037210000000202314166627112031562 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Using absolute import, do from module imports. """ from __future__ import absolute_import, print_function from foobar import util from . import local # pylint: disable=unused-import class Foobar(object): def __init__(self): print(util.someFunction()) Nuitka-0.6.19.1/tests/programs/absolute_import/foobar/__init__.py0000600000372100037210000000143414166627112032056 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from .foobar import Foobar Nuitka-0.6.19.1/tests/programs/absolute_import/AbsoluteImportMain.py0000600000372100037210000000147714166627112032634 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import foobar if __name__ == "__main__": foobar.Foobar() Nuitka-0.6.19.1/tests/programs/syntax_errors/0000700000372100037210000000000014167275622026211 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/syntax_errors/SyntaxErrorsMain.py0000600000372100037210000000206714166627112032054 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function try: from SyntaxErroring import x except Exception as e: print("Importing with syntax error gave:", type(e), e) try: from IndentationErroring import x except Exception as e: print("Importing with indentation error gave:", type(e), e) print("Finished.") Nuitka-0.6.19.1/tests/programs/syntax_errors/SyntaxErroring.py0000600000372100037210000000144014166627112031554 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class x(metaclass=y): pass Nuitka-0.6.19.1/tests/programs/syntax_errors/IndentationErroring.py0000600000372100037210000000142714166627112032547 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def f(): x y Nuitka-0.6.19.1/tests/programs/package_prevents_submodule/0000700000372100037210000000000014167275622030667 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_prevents_submodule/PackagePreventsSubmoduleMain.py0000600000372100037210000000563414166627112037014 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import imp import os import sys ORIG = None attemptImports = None # Nuitka gives warnings, that even if disabled touch this. __warningregistry__ = {} def diff(dct): print("globals diff", ORIG.symmetric_difference(dct)) mdiff = START.symmetric_difference(sys.modules) # Python2 does strange thing with relative imports, that we do not. if str is bytes: if "some_package.os" in mdiff: mdiff.remove("some_package.os") print("Modules diff", mdiff) START = set(sys.modules) ORIG = set(globals()) def attemptImports(prefix): print(prefix, "GO1:") try: import some_package except BaseException as e: print("Exception occurred", e) else: print("Import success.", some_package.__name__) diff(globals()) print(prefix, "GO2:") try: from some_package.some_module import Class4 except BaseException as e: print("Exception occurred", e) else: print("Import success.", Class4) diff(globals()) print(prefix, "GO3:") try: from some_package import some_module except BaseException as e: print("Exception occurred", e) else: print("Import success.", some_module.__name__) diff(globals()) print(prefix, "GO4:") try: from some_package import raiseError except BaseException as e: print("Exception occurred", e) else: print("Import success.", raiseError.__name__) diff(globals()) print(prefix, "GO5:") try: from some_package import Class5 except BaseException as e: print("Exception occurred", e) else: print("Import success.", Class5) diff(globals()) print(prefix, "GO6:") try: from some_package import Class3 except BaseException as e: print("Exception occurred", e) else: print("Import success.", Class3) diff(globals().keys()) os.environ["TEST_SHALL_RAISE_ERROR"] = "1" attemptImports("With expected errors") os.environ["TEST_SHALL_RAISE_ERROR"] = "0" attemptImports("With error resolved") del sys.modules["some_package"] attemptImports("With deleted module") Nuitka-0.6.19.1/tests/programs/package_prevents_submodule/some_package/0000700000372100037210000000000014167275622033305 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/programs/package_prevents_submodule/some_package/some_module.py0000600000372100037210000000144014166627112036162 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class Class4(object): pass Nuitka-0.6.19.1/tests/programs/package_prevents_submodule/some_package/__init__.py0000600000372100037210000000206614166627112035416 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import os print( "This is", __name__, "code with error raise", os.environ.get("TEST_SHALL_RAISE_ERROR"), ) class Class3(object): pass def raiseError(): raise Exception("AHOJ") if os.environ.get("TEST_SHALL_RAISE_ERROR") == "1": raiseError() class Class5(object): pass Nuitka-0.6.19.1/tests/basics/0000700000372100037210000000000014167275622022701 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/tests/basics/HelloWorld_2.py0000600000372100037210000000240614166627112025545 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- coding: utf-8 -*- # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print "Hello World from module main code" def printHelloWorld(): print "Hello World from function main code" print printHelloWorld printHelloWorld() def printHelloWorld2(arg): print arg print printHelloWorld2 printHelloWorld2("Hello World from function positional argument") printHelloWorld2(arg="Hello World from function keyword argument") def printHelloWorld3(arg="Hello World from function default argument"): print arg print printHelloWorld3 printHelloWorld3() Nuitka-0.6.19.1/tests/basics/ListContractions.py0000600000372100037210000000536314166627112026560 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Cover list contractions and a few special things in them. """ from __future__ import print_function # Tests do bad things, pylint: disable=redefined-outer-name,possibly-unused-variable def displayDict(d): result = "{" for key, value in sorted(d.items()): result += "%s: %s" % (key, value) result += "}" print("List contraction on the module level:") x = [(u if u % 2 == 0 else 0) for u in range(10)] print(x) print("List contraction on the function level:") def someFunction(): x = [(u if u % 2 == 0 else 0) for u in range(10)] print(x) someFunction() print("List contractions with no, 1 one 2 conditions:") def otherFunction(): print([x for x in range(8)]) print([x for x in range(8) if x % 2 == 1]) print([x for x in range(8) if x % 2 == 1 if x > 4]) otherFunction() print("Complex list contractions with more than one for:") def complexContractions(): print([(x, y) for x in range(3) for y in range(5)]) seq = range(3) res = [(i, j, k) for i in iter(seq) for j in iter(seq) for k in iter(seq)] print(res) complexContractions() print("Contraction for 2 for statements and one final if referring to first for:") def trickyContraction(): class Range: def __init__(self, value): self.value = value def __iter__(self): print("Giving range iter to", self.value) return iter(range(self.value)) def Cond(y): print("Checking against", y) return y == 1 r = [(x, z, y) for x in Range(3) for z in Range(2) for y in Range(4) if Cond(y)] print("result is", r) trickyContraction() def lambdaWithcontraction(x): l = lambda x: [z for z in range(x)] r = l(x) print("Lambda contraction locals:", displayDict(locals())) lambdaWithcontraction(3) print("Contraction that gets a 'del' on the iterator variable:", end=" ") def allowedDelOnIteratorVariable(z): x = 2 del x return [x * z for x in range(z)] print(allowedDelOnIteratorVariable(3)) Nuitka-0.6.19.1/tests/basics/ExceptionRaising33.py0000600000372100037210000000266214166627112026676 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys print("Testing exception changes between generator switches:") def yieldExceptionInteraction(): def yield_raise(): try: raise KeyError("caught") except KeyError: yield from sys.exc_info() yield from sys.exc_info() yield from sys.exc_info() g = yield_raise() print("Initial yield from catch in generator", next(g)) print("Checking from outside of generator", sys.exc_info()[0]) print("Second yield from the catch reentered", next(g)) print("Checking from outside of generator", sys.exc_info()[0]) print("After leaving the catch generator yielded", next(g)) yieldExceptionInteraction() Nuitka-0.6.19.1/tests/basics/GlobalStatement.py0000600000372100037210000000736014166627112026342 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys x = 2 def someFunction1(): x = 3 return x def someFunction2(): global x x = 4 return x def someFunction3(): return x def someNestedGlobalUser1(): z = 1 # Nested function that uses a global z doesn't affect the local variable z at all. def setZ(): global z z = 3 setZ() return z def someNestedGlobalUser2(): z = 1 # Nested function that uses a global z doesn't affect the local variable z at # all. This doesn't change if it's done inside an exec block. exec( """ def setZ(): global z z = 3 setZ() """ ) return z def someNestedGlobalUser3a(): # Nested function that uses a exec variable scope z and a global z, changes z to be # the global one only. We verify that by looking at locals. This means that the global # statement inside the function of exec changes the effect of the z. exec( """ z = 1 def setZ(): global z z = 3 setZ() """ ) return z, locals().keys() == ["setZ"] def someNestedGlobalUser3b(): # Nested function that uses a exec variable scope z and a global z, changes # z to be the global one only. We verify that by looking at locals. exec( """ z = 1 """ ) if sys.version_info[0] < 3: return z, locals().keys() == ["z"] else: return locals().keys() == [] def someNestedGlobalUser4(): z = 1 # This one proves that the local variable z is entirely ignored, and that the global z # has the value 2 inside setZ(). exec( """ z = 2 def setZ(): global z z = 3*z setZ() """ ) return z def someNestedGlobalUser5(): z = 1 # Without a global statement, z affects the local variable z. exec( """ z = 3 """ ) return z def someNestedGlobalUser6(): # Without a global statement, a local variable z is created. exec( """ z = 7 """ ) return z print("Function that shadows a global variable with a local variable") print(someFunction1()) print( "Function that accesses and changes a global variable declared with a global statement" ) print(someFunction2()) print("Function that uses a global variable") print(someFunction3()) print("Functions that uses a global variable in a nested function in various ways:") print(someNestedGlobalUser1, someNestedGlobalUser1()) del z print(someNestedGlobalUser2, someNestedGlobalUser2()) del z print(someNestedGlobalUser3a, someNestedGlobalUser3a()) del z print(someNestedGlobalUser3b, someNestedGlobalUser3b()) print(someNestedGlobalUser4, (someNestedGlobalUser4(), z)) del z print(someNestedGlobalUser5, someNestedGlobalUser5()) z = 9 print(someNestedGlobalUser6, (someNestedGlobalUser6(), z)) x = 7 def f(): x = 1 def g(): global x def i(): def h(): return x return h() return i() return g() print(f()) global global_already global_already = 1 Nuitka-0.6.19.1/tests/basics/TryYieldFinally.py0000600000372100037210000000443014166627112026334 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def tryContinueFinallyTest(): for x in range(10): try: if x % 2 == 1: continue finally: yield x yield "-" def tryBreakFinallyTest(): for x in range(10): try: if x == 5: break finally: yield x yield "-" def tryFinallyAfterYield(): try: yield 3 finally: print("Executing finally") def tryReturnFinallyYield(): try: return finally: yield 1 def tryReturnExceptYield(): try: return except StopIteration: print("Caught StopIteration") yield 2 except: yield 1 else: print("No exception") def tryStopIterationExceptYield(): try: raise StopIteration except StopIteration: print("Caught StopIteration") yield 2 except: yield 1 else: print("No exception") print("Check if finally is executed in a continue using for loop:") print(tuple(tryContinueFinallyTest())) print("Check if finally is executed in a break using for loop:") print(tuple(tryBreakFinallyTest())) print("Check what try yield finally something does:") print(tuple(tryFinallyAfterYield())) print("Check if yield is executed in finally after return:") print(tuple(tryReturnFinallyYield())) print("Check if yield is executed in except after return:") print(tuple(tryReturnExceptYield())) print("Check if yield is executed in except after StopIteration:") print(tuple(tryReturnExceptYield())) Nuitka-0.6.19.1/tests/basics/TryReturnFinally.py0000600000372100037210000000543214166627112026550 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # In this test we show that return in try/finally executes the finally part # just fine. from __future__ import print_function import sys def eight(): return 8 def nine(): return 9 def raisy1(): return 1 / 0 def raisy2(): return 1() def raisy3(arg): raise TypeError(arg) def returnInTried(for_call): try: print("returnInTried with exception info in tried block:", sys.exc_info()) return for_call() finally: print("returnInTried with exception info in final block:", sys.exc_info()) def returnInFinally(for_call): try: print("returnInFinally with exception info in tried block:", sys.exc_info()) finally: print("returnInFinally with exception info in final block:", sys.exc_info()) return for_call() print("Standard try finally with return in tried block:") print("result", returnInTried(eight)) print("*" * 80) print("Standard try finally with return in final block:") print("result", returnInFinally(nine)) print("*" * 80) print("Exception raising try finally with return in tried block:") try: print("result", returnInTried(raisy1)) except Exception as e: print("Gave exception", repr(e)) print("*" * 80) print("Exception raising try finally with return in final block:") try: print("result", returnInFinally(raisy2)) except Exception as e: print("Gave exception", repr(e)) print("*" * 80) try: raisy3("unreal 1") except Exception as outer_e: print("Exception raising try finally with return in tried block:") try: print("result", returnInTried(raisy1)) except Exception as e: print("Gave exception", repr(e)) print("Handler exception remains:", repr(outer_e)) print("*" * 80) try: raisy3("unreal 2") except Exception as outer_e: print("Exception raising try finally with return in final block:") try: print("result", returnInFinally(raisy2)) except Exception as e: print("Gave exception", repr(e)) print("Handler exception remains:", repr(outer_e)) print("*" * 80) Nuitka-0.6.19.1/tests/basics/LateClosureAssignment.py0000600000372100037210000000525314166627112027527 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def closureTest1(): # Assign, but the value is not supposed to be used by the function, instead the later # update is effective. d = 1 def subby(): return d d = 22222 * 2222 return subby() def closureTest2(): # Using a closure variable that is not initialized at the time it is closured should # work as well. def subby(): return d d = 2222 * 2222 return subby() def closureTest3(): def subby(): return undefined_global try: return subby() except NameError: return 88 d = 1 def scopeTest4(): try: return d d = 1 except UnboundLocalError as e: return repr(e) print("Test closure where value is overwritten:", closureTest1()) print("Test closure where value is assigned only late:", closureTest2()) print("Test function where closured value is never assigned:", closureTest3()) print("Scope test where UnboundLocalError is expected:", scopeTest4()) def function(): pass class ClosureLocalizerClass: print("Function before assigned in a class:", function) function = 1 print("Function after it was assigned in class:", function) ClosureLocalizerClass() def ClosureLocalizerFunction(): try: function = function print("Function didn't give unbound local error") except UnboundLocalError as e: print( "Function gave unbound local error when accessing function before assignment:", repr(e), ) ClosureLocalizerFunction() class X: def __init__(self, x): self.x = x def changingClosure(): print("Changing a closure taken value after it was taken.") a = 1 def closureTaker(): return X(a) x = closureTaker() a = 2 print("Closure value first time:", x.x) x = closureTaker() print("Closure value second time:", x.x) changingClosure() Nuitka-0.6.19.1/tests/basics/Assignments32.py0000600000372100037210000001331514166627112025712 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print("Basic assignment forms from various iterables:") a, b = 1, 2 # simple sequence assignment print(a, b) a, b = ["green", "blue"] # list assignment print(a, b) a, b = "XY" # string assignment print(a, b) a, b = range(1, 5, 2) # any iterable will do print(a, b) print("Using braces on unpacking side:") (a, b), c = "XY", "Z" # a = 'X', b = 'Y', c = 'Z' print(a, b, c) print("Too many values:") try: (a, b), c = "XYZ" # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b, c) print("Too few values:") try: (a, b), c = "XY" # ERROR -- need more than 1 value to unpack except Exception as e: print(repr(e)) print(a, b, c) print("More complex right hand side, consisting of multiple values:") (a, b), c, = [1, 2], "this" # a = '1', b = '2', c = 'this' print(a, b, c) print("More complex right hand side, too many values:") try: (a, b), (c,) = [1, 2], "this" # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b, c) print("Extended sequence * unpacking:") a, *b = 1, 2, 3, 4, 5 # a = 1, b = [2,3,4,5] print(a, b) *a, b = 1, 2, 3, 4, 5 # a = [1,2,3,4], b = 5 print(a, b) a, *b, c = 1, 2, 3, 4, 5 # a = 1, b = [2,3,4], c = 5 print(a, b) a, *b = "X" # a = 'X', b = [] print(a, b) *a, b = "X" # a = [], b = 'X' print(a, b) a, *b, c = "XY" # a = 'X', b = [], c = 'Y' print(a, b) a, *b, c = "X...Y" # a = 'X', b = ['.','.','.'], c = 'Y' print(a, b, c) a, b, *c = 1, 2, 3 # a = 1, b = 2, c = [3] print(a, b, c) a, b, c, *d = 1, 2, 3 # a = 1, b = 2, c = 3, d = [] print(a, b, c, d) (a, b), c = [1, 2], "this" # a = '1', b = '2', c = 'this' print(a, b, c) (a, b), *c = [1, 2], "this" # a = '1', b = '2', c = ['this'] print(a, b, c) (a, b), c, *d = [1, 2], "this" # a = '1', b = '2', c = 'this', d = [] print(a, b, c, d) (a, b), *c, d = [1, 2], "this" # a = '1', b = '2', c = [], d = 'this' print(a, b, c, d) (a, b), (c, *d) = [1, 2], "this" # a = '1', b = '2', c = 't', d = ['h', 'i', 's'] print(a, b, c, d) *a, = (1, 2) # a = [1,2] print("Extended sequence * unpacking with non-iterable:") try: *a, = 1 # ERROR -- 'int' object is not iterable except Exception as e: print(repr(e)) print(a) print("Extended sequence * unpacking with list:") *a, = [1] # a = [1] print(a) print("Extended sequence * unpacking with tuple:") *a, = (1,) # a = [1] print(a) print("Extended sequence * unpacking with fixed right side:") *a, b = [1] # a = [], b = 1 print(a, b) *a, b = (1,) # a = [], b = 1 print(a, b) print("Unpacking too many values:") try: (a, b), c = 1, 2, 3 # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b, c) print("Unpacking with star argument changes error:") try: (a, b), *c = 1, 2, 3 # ERROR - 'int' object is not iterable except Exception as e: print(repr(e)) print(a, b, c) print("Unpacking with star argument after tuple unpack:") (a, b), *c = "XY", 2, 3 # a = 'X', b = 'Y', c = [2,3] print(a, b, c) print("Extended sequence unpacking, nested:") try: (a, b), c = 1, 2, 3 # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b, c) *(a, b), c = 1, 2, 3 # a = 1, b = 2, c = 3 print(a, b, c) *(a, b), = 1, 2 # a = 1, b = 2 print(a, b) *(a, b), = "XY" # a = 'X', b = 'Y' print(a, b) try: *(a, b), = "this" # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b) *(a, *b), = "this" # a = 't', b = ['h', 'i', 's'] print(a, b) *(a, *b), c = "this" # a = 't', b = ['h', 'i'], c = 's' print(a, b, c) *(a, *b), = 1, 2, 3, 3, 4, 5, 6, 7 # a = 1, b = [2, 3, 3, 4, 5, 6, 7] print(a, b) try: *(a, *b), (*c,) = 1, 2, 3, 3, 4, 5, 6, 7 # ERROR -- 'int' object is not iterable except Exception as e: print(repr(e)) print("unchanged", a, b, c) print("Unpacking with nested stars:") *(a, *b), c = 1, 2, 3, 3, 4, 5, 6, 7 # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7 print(a, b, c) print("Unpacking with even more nested stars:") *(a, *b), (*c,) = 1, 2, 3, 4, 5, "XY" # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y'] print(a, b, c) *(a, *b), c, d = 1, 2, 3, 3, 4, 5, 6, 7 # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7 print("starting", a, b, c, d) try: *(a, *b), (c, d) = 1, 2, 3, 3, 4, 5, 6, 7 # ERROR -- 'int' object is not iterable except Exception as e: print(repr(e)) print("unchanged", a, b, c, d) try: *(a, *b), (*c, d) = 1, 2, 3, 3, 4, 5, 6, 7 # ERROR -- 'int' object is not iterable except Exception as e: print(repr(e)) print(a, b, c, d) try: *(a, b), c = "XY", 3 # ERROR -- need more than 1 value to unpack except Exception as e: print(repr(e)) print("unchanged", a, b, c) *(*a, b), c = "XY", 3 # a = [], b = 'XY', c = 3 print(a, b, c) (a, b), c = "XY", 3 # a = 'X', b = 'Y', c = 3 print(a, b, c) *(a, b), c = "XY", 3, 4 # a = 'XY', b = 3, c = 4 print(a, b, c) *(*a, b), c = "XY", 3, 4 # a = ['XY'], b = 3, c = 4 print(a, b, c) try: (a, b), c = "XY", 3, 4 # ERROR -- too many values to unpack except Exception as e: print(repr(e)) print(a, b, c) Nuitka-0.6.19.1/tests/basics/Assignments.py0000600000372100037210000001340614166627112025546 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Assignment tests, cover most forms of them. """ from __future__ import print_function import sys # Tests are dirty on purpose. # # pylint: disable=broad-except,global-variable-undefined,redeclared-assigned-name # pylint: disable=global-variable-not-assigned,invalid-name,self-assigning-variable def someFunction(): a = 2 print("Simple assignment to variable:", a) b = c = 3 print("Assignment to 2 variables", b, c) z = [1, 2, 3] z[2] = z[1] = 5 print("Assignment to list subscripts:", z) d, e = 1, 2 print("Assignment to variable tuple:", d, e) [f, g] = 7, 9 print("Assignment to variable list:", f, g) j = [h, i] = (7, 9) print("Complex Assignment from variable list:", j, type(j), h, i) a, (b, c) = 1, (2, 3) print("Assignment to nested tuples:", a, b, c) v = [1, 2, 3, 4] v[2:3] = (8, 9) print("Assignment to list slice", v) def varargsFunction(*args): f1, f2, f3, f4 = args print("Assignment from list", f1, f2, f3, f4) def otherFunction(): class Iterable: def __iter__(self): return iter(range(3)) a, b, c = Iterable() print("Assignments from iterable", a, b, c) print("Assignments from too small iterable", end=" ") try: f, g = (1,) except Exception as e: print("gave", type(e), repr(e)) try: print(f) except UnboundLocalError: print("Variable f is untouched") try: print(g) except UnboundLocalError: print("Variable g is untouched") print("Assignments from too large iterable", end=" ") try: d, j = 1, 2, 3 except Exception as e: print("gave", type(e), repr(e)) try: print(d) except UnboundLocalError: print("Variable d is untouched") try: print(j) except UnboundLocalError: print("Variable j is untouched") class BasicIterClass: def __init__(self, n): self.n = n self.i = 0 def __next__(self): res = self.i if res >= self.n: raise StopIteration self.i = res + 1 return res if sys.version_info[0] < 3: def next(self): return self.__next__() class IteratingSequenceClass: def __init__(self, n): self.n = n def __iter__(self): return BasicIterClass(self.n) print("Exception from iterating over too short class:", end=" ") try: a, b, c = IteratingSequenceClass(2) except ValueError: print("gave", sys.exc_info()) def anotherFunction(): d = {} print("Assignment to dictionary with comma subscript:", end="") # d["f"] = 3 d["a", "b"] = 6 d["c", "b"] = 9 print(sorted(d.items())) def swapVariables(): print("Strange swap form:") a = 1 b = 2 a, b, a = b, a, b print(a, b) def interuptedUnpack(): a = 1 b = 2 print("Assignment from a too short tuple to multiple targets:", end=" ") try: s = (a,) c, d = s except ValueError as e: print("gives ValueError", repr(e)) try: print(c) except UnboundLocalError as e: print("and then nothing is assigned:", repr(e)) else: del d del a, b z = [] try: a, z.unknown, b = 1, 2, 3 except AttributeError: print("Interrupted unpack, leaves value assigned", a) def multiTargetInterrupt(): a = 1 b = 2 print("Multiple, overlapping targets", end="") d = c, d = a, b print(d, c, end="") del c del d c, d = d = a, b print(d, c) print("Error during multiple assignments", end="") del c del d e = 9 z = [] try: c, d = e, z.a = a, b except AttributeError: print("having attribute error", c, d, e) del c del d e = 9 print("Error during multiple assignments", end="") try: c, d = z.a, e = a, b except AttributeError: print("having attribute error", c, d, e) def optimizeableTargets(): a = [1, 2] a[int(1)] = 3 print("Optimizable slice operation, results in", a) def complexDel(): a = b = c = d = 1 del a, b, (c, d) try: print(c) except UnboundLocalError as e: print("yes, del worked", repr(e)) def sliceDel(): # Python3 ranges are not lists. a = list(range(6)) del a[2:4] print("Del slice operation, results in", a) def globalErrors(): global unassigned_1, unassigned_2 try: unassigned_1 = unassigned_1 except NameError as e: print("Accessing unassigned global gives", repr(e)) try: del unassigned_2 except NameError as e: print("Del on unassigned global gives", repr(e)) someFunction() varargsFunction(1, 2, 3, 4) otherFunction() anotherFunction() swapVariables() interuptedUnpack() multiTargetInterrupt() optimizeableTargets() complexDel() sliceDel() globalErrors() Nuitka-0.6.19.1/tests/basics/Classes32.py0000600000372100037210000000641514166627112025017 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # try: from collections.abc import OrderedDict except ImportError: from collections import OrderedDict print("Call order of Python3 metaclasses:") def a(): x = 1 class A: print("Class body a.A is evaluating closure x", x) print("Called", a) return A def b(): class B: pass print("Called", b) return B def displayable(dictionary): return sorted(dictionary.items()) def m(): class M(type): def __new__(cls, class_name, bases, attrs, **over): print( "Metaclass M.__new__ cls", cls, "name", class_name, "bases", bases, "dict", displayable(attrs), "extra class defs", displayable(over), ) return type.__new__(cls, class_name, bases, attrs) def __init__(self, name, bases, attrs, **over): print( "Metaclass M.__init__", name, bases, displayable(attrs), displayable(over), ) super().__init__(name, bases, attrs) def __prepare__(metacls, bases, **over): # @NoSelf print("Metaclass M.__prepare__", metacls, bases, displayable(over)) return OrderedDict() print("Called", m) return M def d(): print("Called", d) return 1 def e(): print("Called", e) return 2 class C1(a(), b(), other=d(), metaclass=m(), yet_other=e()): import sys # TODO: Enable this. # print("C1 locals type is", type(sys._getframe().f_locals)) print("OK, class created", C1) print("Attribute C1.__dict__ has type", type(C1.__dict__)) print("Function local classes can be made global and get proper __qualname__:") def someFunctionWithLocalClassesMadeGlobal(): # Affects __qualname__ only in Python3.4 or higher, not in Python3.2 global C class C: pass class D: pass try: print("Nested class qualname is", D.__qualname__) except AttributeError: # Python3.2 pass try: print("Local class made global qualname is", C.__qualname__) except AttributeError: pass someFunctionWithLocalClassesMadeGlobal() print("Function in a class with private name") class someClassWithPrivateArgumentNames: def f(self, *, __kw: 1): pass print(someClassWithPrivateArgumentNames.f.__annotations__) print("OK.") Nuitka-0.6.19.1/tests/basics/PrintFuture.py0000600000372100037210000000153714166627112025544 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("hallo welt", end=", ") print("this is the end") Nuitka-0.6.19.1/tests/basics/GeneratorExpressions.py0000600000372100037210000001322614166627112027444 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Generator expression tests """ from __future__ import print_function import inspect print("Generator expression that demonstrates the timing:") def iteratorCreationTiming(): def getIterable(x): print("Getting iterable", x) return Iterable(x) class Iterable: def __init__(self, x): self.x = x # pylint: disable=invalid-name self.values = list(range(x)) self.count = 0 def __iter__(self): print("Giving iterator now", self.x) return self def __next__(self): print("Next of", self.x, "is", self.count) if len(self.values) > self.count: self.count += 1 return self.values[self.count - 1] else: print("Raising StopIteration for", self.x) raise StopIteration # Python2/3 compatibility. next = __next__ def __del__(self): print("Deleting", self.x) gen = ((y, z) for y in getIterable(3) for z in getIterable(2)) print("Using generator", gen) next(gen) res = tuple(gen) print(res) print("*" * 20) try: next(gen) except StopIteration: print("Usage past end gave StopIteration exception as expected.") try: print("Generator state then is", inspect.getgeneratorstate(gen)) except AttributeError: pass print("Its frame is now", gen.gi_frame) print("Early aborting generator:") gen2 = ((y, z) for y in getIterable(3) for z in getIterable(2)) del gen2 iteratorCreationTiming() print("Generator expressions that demonstrate the use of conditions:") print(tuple(x for x in range(8) if x % 2 == 1)) print(tuple(x for x in range(8) if x % 2 == 1 for z in range(8) if z == x)) print(tuple(x for (x, y) in zip(list(range(2)), list(range(4))))) print("Directory of generator expressions:") for_dir = (x for x in [1]) gen_dir = dir(for_dir) print(sorted(g for g in gen_dir)) def genexprSend(): x = (x for x in range(9)) print("Sending too early:") try: x.send(3) except TypeError as e: print("Gave expected TypeError with text:", e) try: z = next(x) except StopIteration as e: print("Gave expected (3.10) StopIteration with text:", repr(e)) else: print("Next return value (pre 3.10)", z) try: y = x.send(3) except StopIteration as e: print("Gave expected (3.10) StopIteration with text:", repr(e)) else: print("Send return value", y) try: print("And then next gave", next(x)) except StopIteration as e: print("Gave expected (3.10) StopIteration with text:", repr(e)) print("Throwing an exception to it.") try: x.throw(2) assert False except TypeError as e: print("Gave expected TypeError:", e) print("Throwing an exception to it.") try: x.throw(ValueError(2)) except ValueError as e: print("Gave expected ValueError:", e) try: next(x) print("Next worked even after thrown error") except StopIteration as e: print("Gave expected stop iteration after throwing exception in it:", e) print("Throwing another exception from it.") try: x.throw(ValueError(5)) except ValueError as e: print("Gave expected ValueError with text:", e) print("Generator expressions have send too:") genexprSend() def genexprClose(): x = (x for x in range(9)) print("Immediate close:") x.close() print("Closed once") x.close() print("Closed again without any trouble") genexprClose() def genexprThrown(): def checked(z): if z == 3: raise ValueError return z x = (checked(x) for x in range(9)) try: for count, value in enumerate(x): print(count, value) except ValueError: print(count + 1, ValueError) try: next(x) print( "Allowed to do next() after raised exception from the generator expression" ) except StopIteration: print("Exception in generator, disallowed next() afterwards.") genexprThrown() def nestedExpressions(): a = [x for x in range(10)] b = (x for x in (y for y in a)) print("nested generator expression", list(b)) nestedExpressions() def lambdaGenerators(): a = 1 x = lambda: (yield a) print("Simple lambda generator", x, x(), list(x())) y = lambda: ((yield 1), (yield 2)) print("Complex lambda generator", y, y(), list(y())) lambdaGenerators() def functionGenerators(): # Like lambdaGenerators, to show how functions behave differently if at all. a = 1 def x(): yield a print("Simple function generator", x, x(), list(x())) def y(): yield ((yield 1), (yield 2)) print("Complex function generator", y, y(), list(y())) functionGenerators() Nuitka-0.6.19.1/tests/basics/Slots.py0000600000372100037210000000313614166627112024356 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class W1(object): def __init__(self): self.__hidden = 5 class W2(object): __slots__ = ["__hidden"] def __init__(self): self.__hidden = 5 class _W1(object): def __init__(self): self.__hidden = 5 class _W2(object): __slots__ = ["__hidden"] def __init__(self): self.__hidden = 5 class a_W1(object): def __init__(self): self.__hidden = 5 class a_W2(object): __slots__ = ["__hidden"] def __init__(self): self.__hidden = 5 class W1_(object): def __init__(self): self.__hidden = 5 class W2_(object): __slots__ = ["__hidden"] def __init__(self): self.__hidden = 5 for w in (W1, W2, _W1, _W2, a_W1, a_W2, W1_, W2_): try: print(w) print(dir(w)) a = w() except AttributeError: print("bug in %s" % w) Nuitka-0.6.19.1/tests/basics/FunctionObjects.py0000600000372100037210000000317414166627112026353 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that covers attributes if function objects. """ from __future__ import print_function def func(_arg1, _arg2, _arg3, **_star): """ Some documentation. """ print("Starting out: func, __name__:", func, func.__name__) print("Changing its name:") func.__name__ = "renamed" print("With new name: func, __name__:", func, func.__name__) print("Documentation initially:", func.__doc__) print("Changing its doc:") func.__doc__ = "changed doc" + chr(0) + " with 0 character" print("Documentation updated:", repr(func.__doc__)) print("Setting its dict") func.my_value = "attached value" print("Reading its dict", func.my_value) print("__code__ dir") print(dir(func.__code__)) def func2(_arg1, arg2="default_arg2", arg3="default_arg3"): x = arg2 + arg3 return x print("func __defaults__", func2.__defaults__) print("function varnames", func2.__code__.co_varnames) Nuitka-0.6.19.1/tests/basics/TryExceptFrames.py0000600000372100037210000000440114166627112026333 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys def displayDict(d): if "__loader__" in d: d = dict(d) d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d = dict(d) d["__file__"] = "<__file__ removed>" import pprint return pprint.pformat(d) counter = 1 class X: def __init__(self): global counter self.counter = counter counter += 1 def __del__(self): print("X.__del__ occurred", self.counter) def raising(doit): _x = X() def nested(): if doit: 1 / 0 try: return nested() except ZeroDivisionError: print("Changing closure variable value.") # This is just to prove that closure variables get updates in frame # locals. doit = 5 raise # Call it without an exception raising(False) def catcher(): try: raising(True) except ZeroDivisionError: print("Catched.") print("Top traceback code is '%s'." % sys.exc_info()[2].tb_frame.f_code.co_name) print( "Second traceback code is '%s'." % sys.exc_info()[2].tb_next.tb_frame.f_code.co_name ) print( "Third traceback code is '%s'." % sys.exc_info()[2].tb_next.tb_next.tb_frame.f_code.co_name ) print( "Third traceback locals (function) are", displayDict(sys.exc_info()[2].tb_next.tb_next.tb_frame.f_locals), ) catcher() print("Good bye.") Nuitka-0.6.19.1/tests/basics/ComparisonChains.py0000600000372100037210000001032314166627112026506 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Comparison chains are multiple comparisons in one expression. """ from __future__ import print_function # pylint: disable=redefined-outer-name def simple_comparisons(x, y): if "a" <= x <= y <= "z": print("One") if "a" <= x <= "z": print("Two") if "a" <= x > "z": print("Three") print("Simple comparisons:") simple_comparisons("c", "d") def side_effect(): print("") return 7 def side_effect_comparisons(): print("Should have side effect:") print(1 < side_effect() < 9) print("Should not have side effect due to short circuit:") print(3 < 2 < side_effect() < 9) print("Check for expected side effects only:") side_effect_comparisons() def function_torture_is(): a = (1, 2, 3) for x in a: for y in a: for z in a: print(x, y, z, ":", x is y is z, x is not y is not z) function_torture_is() print("Check if lambda can have expression chains:", end="") def function_lambda_with_chain(): a = (1, 2, 3) x = lambda x: x[0] < x[1] < x[2] print("lambda result is", x(a)) function_lambda_with_chain() print("Check if generators can have expression chains:", end="") def generator_function_with_chain(): x = (1, 2, 3) yield x[0] < x[1] < x[2] print(list(generator_function_with_chain())) print("Check if list contractions can have expression chains:", end="") def contraction_with_chain(): return [x[0] < x[1] < x[2] for x in [(1, 2, 3)]] print(contraction_with_chain()) print("Check if generator expressions can have expression chains:", end="") def genexpr_with_chain(): return (x[0] < x[1] < x[2] for x in [(1, 2, 3)]) print(list(genexpr_with_chain())) print("Check if class bodies can have expression chains:", end="") class ClassWithComparisonChainInBody: x = (1, 2, 3) print(x[0] < x[1] < x[2]) x = (1, 2, 3) print(x[0] < x[1] < x[2]) class CustomOps(int): def __lt__(self, other): print("enter <", self, other) return True def __gt__(self, other): print("enter >", self, other) return False print("Custom ops, to enforce chain eval order and short circuit:", end="") print(CustomOps(7) < CustomOps(8) > CustomOps(6)) print("Custom ops, doing short circuit:", end="") print(CustomOps(8) > CustomOps(7) < CustomOps(6)) def inOperatorChain(): print("In operator chains:") print(3 in [3, 4] in [[3, 4]]) print(3 in [3, 4] not in [[3, 4]]) if 3 in [3, 4] in [[3, 4]]: print("Yes") else: print("No") if 3 in [3, 4] not in [[3, 4]]: print("Yes") else: print("No") inOperatorChain() # Make sure the values are called and order is correct: class TracingLessThan(object): def __init__(self, name, value): self.name = name self.value = value def __repr__(self): return "" % (self.name, self.value) def __lt__(self, other): print( "less than called for:", self, other, self.value, other.value, self.value < other.value, ) if self.value < other.value: print("good") return 7 else: print("bad") return 0 a = TracingLessThan("a", 1) b = TracingLessThan("b", 2) c = TracingLessThan("c", 0) print(a < b < c) print("*" * 80) a = TracingLessThan("a", 2) b = TracingLessThan("b", 1) c = TracingLessThan("c", 0) print(a < b < c) Nuitka-0.6.19.1/tests/basics/Decorators.py0000600000372100037210000000313414166627112025355 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def decorator1(f): print("Executing decorator 1") def deco_f(): return f() + 2 return deco_f def decorator2(f): print("Executing decorator 2") def deco_f(): return f() * 2 return deco_f # Result of function now depends on correct order of applying the decorators @decorator1 @decorator2 def function1(): return 3 print(function1()) def deco_returner1(): print("Executing decorator returner D1") return decorator1 def deco_returner2(): print("Executing decorator returner D2") return decorator2 @deco_returner1() @deco_returner2() def function2(): return 3 print(function2()) # Same as function2, but without decorator syntax. def function3(): return 3 function3 = deco_returner1()(deco_returner2()(function3)) print(function3()) Nuitka-0.6.19.1/tests/basics/Operators.py0000600000372100037210000000367214166627112025235 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function a = 3 b = 7 c = [7, 8] d = 15 print("+", a + b) print("-", a - b) print("*", a * b) print("/", a / b) print("//", a // b) print("%", b % a) print("& (2)", a & b) print("| (2)", a | b) print("& (3)", a & b & d) print("| (3)", a | b | d) print("^ (2)", a ^ b) print("^ (3)", a ^ b ^ d) print("**", a ** b) print("<<", a << b) print(">>", b >> a) print("in", b in c) print("not in", b not in c) print("<", a < b) print(">", a > b) print("==", a == b) print("<=", a <= b) print(">=", a >= b) print("!=", a != b) print("is", a is b) print("is not", a is not b) print("~", ~b) print("-", -b) print("+", +b) l = {("a", "c"): "a,c", "b": 2, "c": 3, "d": 4} l["l",] = "6" print("Extended slicing:") print("Should be a,c:", l["a", "c"]) print("Short form of extended slicing:") d = {} # d[1] = 1 d[1,] = 2 d[1, 2] = 3 d[1, 2, 3] = 4 L = list(d) L.sort() print(L) s = "Some information" ss = s[-1] print("Constant subscript of string", ss) print("Slicing on a list:") l = [1, 3, 5, 7, 11, 13, 17] print(l[None:None]) n = None print(l[n:n]) print(l[3:n]) print(l[n:3]) value = None try: x = value[1] except Exception as e: print("Indexing None gives", repr(e)) Nuitka-0.6.19.1/tests/basics/ExceptionRaising32.py0000600000372100037210000000170114166627112026666 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def raisy(): raise ValueError() from None try: print("Raising exception in a function 'from None':") raisy() except (ValueError, TypeError) as e: print("Caught as", repr(e)) Nuitka-0.6.19.1/tests/basics/Branching.py0000600000372100037210000000773014166627112025151 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Some random branching to cover most common cases. """ from __future__ import print_function def branchingFunction(a, b, c): print("branchingFunction:", a, b, c) print("a or b", a or b) print("a and b", a and b) print("not a", not a) print("not b", not b) print("Simple branch with both branches") if a: l = "YES" else: l = "NO" print(a, "->", l) print("Simple not branch with both branches") if not a: l = "YES" else: l = "NO" print(not a, "->", l) print("Simple branch with a nested branch in else path:") if a: m = "yes" else: if True: m = "no" print(a, "->", m) print("Triple 'and' chain:") v = "NO" if a and b and c: v = "YES" print(a, b, c, "->", v) print("Triple or chain:") k = "NO" if a or b or c: k = "YES" print(a, b, c, "->", k) print("Nested 'if not' chain:") p = "NO" if not a: if not b: p = "YES" print("not a, not b", not a, not b, "->", p) print("or condition in braces:") q = "NO" if a or b: q = "YES" print("(a or b) ->", q) print("Braced if not with two 'or'") if not (a or b or c): q = "YES" else: q = "NO" print("not (a or b or c)", q) print("Braced if not with one 'or'") q = "NO" if not (b or b): q = "YES" print("not (b or b)", q) print("Expression a or b", a or b) print("Expression not(a or b)", not (a or b)) print("Expression a and (b+5)", a and (b + 5)) print("Expression (b if b else 2)", (b if b else 2)) print("Expression (a and (b if b else 2))", (a and (b if b else 2))) print("Braced if not chain with 'and' and conditional expression:") if not (a and (b if b else 2)): print("oki") print("Nested if chain with outer else:") d = 1 if a: if b or c: if d: print("inside nest") else: print("outer else") print("Complex conditional expression:") v = (3 if a + 1 else 0) or (b or (c * 2 if c else 6) if b - 1 else a and b and c) print(v) if True: print("Predictable branch taken") branchingFunction(1, 0, 3) x = 3 def optimizationVictim(): if x: pass else: pass if x: pass pass optimizationVictim() def dontOptimizeSideEffects(): print( "Lets see, if conditional expression in known true values are correctly handled:" ) def returnTrue(): print("function 'returnTrue' was called as expected") return True def returnFalse(): print("function 'returnFalse' should not have beeen called") return False if (returnTrue() or returnFalse(),): print("Taken branch as expected.") else: print("Bad branch taken.") dontOptimizeSideEffects() def dontOptimizeTruthCheck(): class A: def __nonzero__(self): raise ValueError __bool__ = __nonzero__ a = A() if a: pass try: print("Check that branch conditions are not optimized way: ", end="") dontOptimizeTruthCheck() print("FAIL.") except ValueError: print("OK.") Nuitka-0.6.19.1/tests/basics/OrderChecks.py0000600000372100037210000003506714166627112025456 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def separator(): print("*" * 80) def dictOrderCheck(): def key1(): print("key1 called") return 1 def key2(): print("key2 called") return 2 def value1(): print("value1 called") return 11 def value2(): print("value2 called") return 22 print("Checking order of calls in dictionary creation from callables:") print({key1(): value1(), key2(): value2()}) try: (1 / 0)[1.0j / 0] = 1.0 / 0 except ZeroDivisionError as e: print("Expected exception caught:", repr(e)) try: (1 / 0)[1.0 / 0] = 1 except ZeroDivisionError as e: print("Expected exception caught:", repr(e)) try: (1 / 0)[1] = 1.0 / 0 except ZeroDivisionError as e: print("Expected exception caught:", repr(e)) def listOrderCheck(): def value1(): print("value1 called") return 11 def value2(): print("value2 called") return 22 print([value1(), value2()]) def sliceOrderCheck(): print("Slices:") d = list(range(10)) def lvalue(): print("lvalue", end=" ") return d def rvalue(): print("rvalue", end=" ") return range(2) def rvalue4(): print("rvalue", end=" ") return range(4) def low(): print("low", end=" ") return 0 def high(): print("high", end=" ") return 4 def step(): print("step", end=" ") return 2 print("Complex slice lookup:", end=" ") print(lvalue()[low() : high() : step()]) print("Complex slice assignment:", end=" ") lvalue()[low() : high() : step()] = rvalue() print(d) print("Complex slice del:", end=" ") del lvalue()[low() : high() : step()] print(d) print("Complex inplace slice operation", end=" ") # TODO: This gives an error in CPython, but not in Nuitka. # lvalue()[ low() : high() : step() ] += rvalue() print(d) d = list(range(10)) print("Simple slice lookup", end=" ") print(lvalue()[low() : high()]) print("Simple slice assignment", end=" ") lvalue()[3 + low() : 3 + high()] = rvalue() print(d) print("Simple slice del", end=" ") del lvalue()[3 + low() : 3 + high()] print(d) print("Simple inplace slice operation", end=" ") lvalue()[low() : high()] += rvalue4() print(d) def subscriptOrderCheck(): print("Subscripts:") d = {} def lvalue(): print("lvalue", end=" ") return d def rvalue(): print("rvalue", end=" ") return 2 def subscript(): print("subscript", end=" ") return 1 print("Assigning subscript:") lvalue()[subscript()] = rvalue() print(d) print("Lookup subscript:") print(lvalue()[subscript()]) print("Deleting subscript:") del lvalue()[subscript()] print(d) def attributeOrderCheck(): def lvalue(): print("lvalue", end=" ") return lvalue def rvalue(): print("rvalue", end=" ") return 2 print("Attribute assignment order:") lvalue().xxx = rvalue() print("Assigned was indeed:", lvalue.xxx) print("Checking attribute assignment to unassigned value from unassigned:") try: undefined_global_zzz.xxx = undefined_global_yyy except Exception as e: print("Expected exception caught:", repr(e)) else: assert False try: (1 / 0).x = 1.0 / 0 except ZeroDivisionError as e: print("Expected exception caught:", repr(e)) def compareOrderCheck(): def lvalue(): print("lvalue", end=" ") return 1 def rvalue(): print("rvalue", end=" ") return 2 print("Comparisons:") print("==", lvalue() == rvalue()) print("<=", lvalue() <= rvalue()) print(">=", lvalue() >= rvalue()) print("!=", lvalue() != rvalue()) print(">", lvalue() > rvalue()) print("<", lvalue() < rvalue()) print("Comparison used in bool context:") print("==", "yes" if lvalue() == rvalue() else "no") print("<=", "yes" if lvalue() <= rvalue() else "no") print(">=", "yes" if lvalue() >= rvalue() else "no") print("!=", "yes" if lvalue() != rvalue() else "no") print(">", "yes" if lvalue() > rvalue() else "no") print("<", "yes" if lvalue() < rvalue() else "no") def operatorOrderCheck(): def left(): print("left operand", end=" ") return 1 def middle(): print("middle operand", end=" ") return 3 def right(): print("right operand", end=" ") return 2 print("Operations:") print("+", left() + middle() + right()) print("-", left() - middle() - right()) print("*", left() * middle() * right()) print("/", left() / middle() / right()) print("%", left() % middle() % right()) print("**", left() ** middle() ** right()) def generatorOrderCheck(): print("Generators:") def default1(): print("default1", end=" ") return 1 def default2(): print("default2", end=" ") return 2 def default3(): print("default3", end=" ") return 3 def value(x): print("value", x, end=" ") return x def generator(a=default1(), b=default2(), c=default3()): print("generator entry") yield value(a) yield value(b) yield value(c) print("generator exit") result = list(generator()) print("Result", result) def classOrderCheck(): print("Checking order of class constructions:") class B1: pass class B2: pass def base1(): print("base1", end=" ") return B1 def base2(): print("base2", end=" ") return B2 def deco1(cls): print("deco1", end=" ") return cls def deco2(cls): print("deco2") return B2 @deco2 @deco1 class X(base1(), base2()): print("class body", end=" ") print def inOrderCheck(): print("Checking order of in operator:") def container(): print("container", end=" ") return [3] def searched(): print("searched", end=" ") return 3 print("in:", searched() in container()) print("not in:", searched() not in container()) def unpackOrderCheck(): class TraceRelease: def __init__(self, value): self.value = value def __del__(self): print("Deleting iteration value", self.value) pass print("Unpacking values:") class Iterable: def __init__(self): self.consumed = 2 def __iter__(self): return Iterable() def __del__(self): print("Deleted iterable with", self.consumed) def next(self): print("Next with state", self.consumed) if self.consumed: self.consumed -= 1 else: raise StopIteration return TraceRelease(self.consumed) __next__ = next iterable = Iterable() class RejectAttributeOwnership: def __setattr__(self, key, value): print("Setting", key, value.value) try: RejectAttributeOwnership().x, RejectAttributeOwnership().y = a, b = iterable except Exception as e: print("Caught", repr(e)) return a, b def superOrderCheck(): print("Built-in super:") try: super(zzz, xxx) except Exception as e: print("Expected exception caught super 2", repr(e)) def isinstanceOrderCheck(): print("Built-in isinstance:") try: isinstance(zzz, xxx) except Exception as e: print("Expected exception caught isinstance 2", repr(e)) def rangeOrderCheck(): print("Built-in range:") try: range(zzz, yyy, xxx) except Exception as e: print("Expected exception caught range 3", repr(e)) try: range(zzz, xxx) except Exception as e: print("Expected exception caught range 2", repr(e)) def importOrderCheck(): print("Built-in __import__:") def name(): print("name", end=" ") def globals(): print("globals", end=" ") def locals(): print("locals", end=" ") def fromlist(): print("fromlist", end=" ") def level(): print("level") try: __import__(name(), globals(), locals(), fromlist(), level()) except Exception as e: print("Expected exception caught __import__ 5", repr(e)) def hasattrOrderCheck(): print("Built-in hasattr:") try: hasattr(zzz, yyy) except Exception as e: print("Expected exception caught hasattr", repr(e)) def getattrOrderCheck(): print("Built-in getattr:") try: getattr(zzz, yyy) except Exception as e: print("Expected exception caught getattr 2", repr(e)) try: getattr(zzz, yyy, xxx) except Exception as e: print("Expected exception caught getattr 3", repr(e)) def default(): print("default used") print("Default side effects:", end=" ") print(getattr(1, "real", default())) def typeOrderCheck(): print("Built-in type:") try: type(zzz, yyy, xxx) except Exception as e: print("Expected exception caught type 3", repr(e)) def iterOrderCheck(): print("Built-in iter:") try: iter(zzz, xxx) except Exception as e: print("Expected exception caught iter 2", repr(e)) def openOrderCheck(): print("Built-in open:") try: open(zzz, yyy, xxx) except Exception as e: print("Expected exception caught open 3", repr(e)) def unicodeOrderCheck(): print("Built-in unicode:") try: unicode(zzz, yyy, xxx) except Exception as e: print("Expected exception caught unicode", repr(e)) def longOrderCheck(): print("Built-in long:") try: long(zzz, xxx) except Exception as e: print("Expected exception caught long 2", repr(e)) def intOrderCheck(): print("Built-in int:") try: int(zzz, xxx) except Exception as e: print("Expected exception caught int", repr(e)) def nextOrderCheck(): print("Built-in next:") try: next(zzz, xxx) except Exception as e: print("Expected exception caught next 2", repr(e)) def callOrderCheck(): print("Checking nested call arguments:") class A: def __del__(self): print("Doing del inner object") def check(obj): print("Outer function") def p(obj): print("Inner function") check(p(A())) def boolOrderCheck(): print("Checking order of or/and arguments:") class A(int): def __init__(self, value): self.value = value def __del__(self): print("Doing del of %s" % self) def __bool__(self): print("Test of %s" % self) return self.value != 0 __nonzero__ = __bool__ def __str__(self): return "<%s %r>" % (self.__class__.__name__, self.value) class B(A): pass class C(A): pass print("Two arguments, A or B:") for a in range(2): for b in range(2): print("Case %d or %d" % (a, b)) r = A(a) or B(b) print(r) del r # TODO: The order of deletion does not exactly match, which we accept for # now. if True: print("Three arguments, A or B or C:") for a in range(2): for b in range(2): for c in range(2): print("Case %d or %d or %d" % (a, b, c)) r = A(a) or B(b) or C(c) print(r) del r print("Two arguments, A and B:") for a in range(2): for b in range(2): print("Case %d and %d" % (a, b)) r = A(a) and B(b) print(r) del r # See above if True: print("Three arguments, A and B and C:") for a in range(2): for b in range(2): for c in range(2): print("Case %d and %d and %d" % (a, b, c)) r = A(a) and B(b) and C(c) print(r) del r def comparisonChainOrderCheck(): print("Checking order of comparison chains:") class A(int): def __init__(self, value): self.value = value def __del__(self): print("Doing del of %s" % self) def __le__(self, other): print("Test of %s <= %s" % (self, other)) return self.value <= other.value def __str__(self): return "<%s %r>" % (self.__class__.__name__, self.value) class B(A): pass class C(A): pass # See above, not really doing it right. if False: print("Three arguments, A <= B <= C:") for a in range(3): for b in range(3): for c in range(3): print("Case %d <= %d <= %d" % (a, b, c)) r = A(a) <= B(b) <= C(c) print(r) del r dictOrderCheck() separator() listOrderCheck() separator() subscriptOrderCheck() separator() attributeOrderCheck() separator() operatorOrderCheck() separator() compareOrderCheck() separator() sliceOrderCheck() separator() generatorOrderCheck() separator() classOrderCheck() separator() inOrderCheck() separator() unpackOrderCheck() separator() superOrderCheck() separator() isinstanceOrderCheck() separator() rangeOrderCheck() separator() importOrderCheck() separator() hasattrOrderCheck() separator() getattrOrderCheck() separator() typeOrderCheck() separator() iterOrderCheck() separator() openOrderCheck() separator() unicodeOrderCheck() separator() nextOrderCheck() separator() longOrderCheck() separator() intOrderCheck() separator() callOrderCheck() separator() boolOrderCheck() separator() comparisonChainOrderCheck() Nuitka-0.6.19.1/tests/basics/BuiltinsTest.py0000600000372100037210000004062014166627112025702 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test that should cover sporadic usages of built-ins that we implemented. """ # pylint: disable=broad-except,global-variable-not-assigned,redefined-outer-name # pylint: disable=comparison-with-itself,use-dict-literal,use-list-literal # pylint: disable=consider-using-with,invalid-bytes-returned,unspecified-encoding # pylint: disable=invalid-str-returned,no-self-use,unnecessary-comprehension from __future__ import print_function # Patch away "__file__" path in a hard to detect way. This will make sure, # repeated calls to locals really get the same dictionary. import os from math import copysign def someFunctionWritingLocals(): x = 1 r = locals() # This is without effect on r. It doesn't mention y at all y = 2 # This adds z to the locals, but only that. r["z"] = 3 del x try: z except Exception as e: print("Accessing z writing to locals gives Exception", e) return r, y def someFunctionWritingLocalsContainingExec(): _x = 1 r = locals() # This is without effect on r. It doesn't mention y at all y = 2 # This adds z to the locals, but only that. r["z"] = 3 try: z except Exception as e: print("Accessing z writing to locals in exec function gives Exception", e) return r, y # Note: This exec is dead code, and still changes the behaviour of # CPython, because it detects exec during parse already. # pylint: disable=exec-used,unreachable exec("") print("Testing locals():") print(someFunctionWritingLocals()) print(someFunctionWritingLocalsContainingExec()) def displayDict(d): if "__loader__" in d: d = dict(d) d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d = dict(d) d["__file__"] = "<__file__ removed>" if "__compiled__" in d: d = dict(d) del d["__compiled__"] import pprint return pprint.pformat(d) print("Vars on module level", displayDict(vars())) module_locals = locals() module_locals["__file__"] = os.path.basename(module_locals["__file__"]) del module_locals print("Use of locals on the module level", displayDict(locals())) def someFunctionUsingGlobals(): g = globals() g["hallo"] = "du" global hallo print("hallo", hallo) # false alarm, pylint: disable=undefined-variable print("Testing globals():") someFunctionUsingGlobals() print("Testing dir():") print("Module dir", end=" ") def someFunctionUsingDir(): q = someFunctionUsingGlobals() print("Function dir", dir()) return q someFunctionUsingDir() print("Making a new type, with type() and 3 args:", end=" ") NewClass = type("Name", (object,), {}) print(NewClass, NewClass()) print("None has type", type(None)) print( "Constant ranges", range(2), range(1, 6), range(3, 0, -1), range(3, 8, 2), range(5, -5, -3), ) print("Border cases", range(0), range(-1), range(-1, 1)) print("Corner case large negative value", range(-(2 ** 100))) print( "Corner case with large start/end values in small range", range(2 ** 100, 2 ** 100 + 2), ) try: print("Range with 0 step gives:", end=" ") print(range(3, 8, 0)) except ValueError as e: print(repr(e)) try: print("Range with float:", end=" ") print(range(1.0)) except TypeError as e: print("Gives exception:", repr(e)) try: print("Empty range call", end=" ") print(range()) except TypeError as e: print("Gives exception:", e) print("List from iterable", list("abc"), list()) try: print("List from sequence", end=" ") print(list(sequence=(0, 1, 2))) except TypeError as e: print("Gives exception:", e) print("Tuple from iterable", tuple("cda"), tuple()) try: print("Tuple from sequence", end=" ") print(tuple(sequence=(0, 1, 2))) except TypeError as e: print("Gives exception:", e) print( "Dictionary from iterable and keywords", displayDict(dict(("ab", (1, 2)), f=1, g=1)) ) print("More constant dictionaries", {"two": 2, "one": 1}, {}, dict()) g = {"two": 2, "one": 1} print("Variable dictionary", dict(g)) print( "Found during optimization", dict(dict({"le": 2, "la": 1}), fu=3), dict(named=dict({"le": 2, "la": 1})), ) print("Floats from constants", float("3.0"), float()) try: print("Float keyword arg", end=" ") except TypeError as e: print(float(x=9.0)) print("Found during optimization", float(float("3.2")), float(float(11.0))) print( "Complex from constants", complex("3.0j"), complex(real=9.0), complex(imag=9.0), complex(1, 2), complex(), ) print( "Found during optimization", complex(float("3.2")), complex(real=float(11.0)), complex(imag=float(11.0)), ) print("Strs from constants", str("3.3"), str(object=9.1), str()) print("Found during optimization", str(float("3.3")), str(object=float(12.0))) print("Bools from constants", bool("3.3"), bool(0), bool()) print("Found during optimization", bool(float("3.3")), bool(range(0))) print("Ints from constants", int("3"), int("f", 16), int("0101", base=2), int(0), int()) try: print("Int keyword arg1", end=" ") print(int(x="9")) print(int(x="e", base=16)) except TypeError as e: print("Gives exception:", e) print("Found ints during optimization", int(int("3")), int(int(0.0))) try: print( "Longs from constants", long("3"), long(x="9"), long("f", 16), long(x="e", base=16), long("0101", base=2), long(0), long(), ) print("Found longs during optimization", long(long("3")), long(x=long(0.0))) except NameError: print("Python3 has no long type.") try: print("Int with only base", int(base=2), end=" ") except Exception as e: print("Caused", repr(e)) else: print("Worked") try: print("Int with large base", int(2, 37), end=" ") except Exception as e: print("Caused", repr(e)) else: print("Worked") try: print("Long with only base", int(base=2), end=" ") except Exception as e: print("Caused", repr(e)) else: print("Worked") print("Oct from constants", oct(467), oct(0)) print("Found during optimization", oct(int("3"))) print("Hex from constants", hex(467), hex(0)) print("Found during optimization", hex(int("3"))) print("Bin from constants", bin(467), bin(0)) print("Found during optimization", bin(int("3"))) try: int(1, 2, 3) except Exception as e: print("Too many args gave", repr(e)) try: int(y=1) except Exception as e: print("Wrong arg", repr(e)) f = 3 print("Unoptimized call of int", int("0" * f, base=16)) try: d = {"x": "12", "base": 8} print("Dict star argument call of int", end=" ") print(int(**d)) except TypeError as e: print("Gives exception:", e) base = 16 try: value = unicode("20") except NameError: print("Python3: Has unicode by default.") value = "20" print("Unoptimized calls of int with unicode args", int(value, base), int(value)) base = 37 try: print("Int with large base", int(2, base), end=" ") except Exception as e: print("Caused", repr(e)) else: print("Worked") try: print(chr()) except Exception as e: print("Disallowed without args", repr(e)) try: print(ord()) except Exception as e: print("Disallowed without args", repr(e)) try: print(ord(s=1)) except Exception as e: print("Disallowed keyword args", repr(e)) try: print(ord(1, 2)) except Exception as e: print("Too many plain args", repr(e)) try: print(ord(1, s=2)) except Exception as e: print("Too many args, some keywords", repr(e)) try: print(sum()) except Exception as e: print("Disallowed without args", repr(e)) x = range(17) print("Sum of range(17) is", sum(x)) print("Sum of range(17) starting with 5 is", sum(x, 5)) try: print(str("1", offer=2)) except Exception as e: print("Too many args, some keywords", repr(e)) # TODO: This is calls, not really builtins. a = 2 print("Can optimize the star list argness away", int(*(a,)), end=" ") print("Can optimize the empty star list arg away", int(*tuple()), end=" ") print("Can optimize the empty star dict arg away", int(**dict())) print("Dict building with keyword arguments", dict(), dict(a=f)) print( "Dictionary entirely from constant args", displayDict(dict(q="Guido", w="van", e="Rossum", r="invented", t="Python", y="")), ) a = 5 print("Instance check recognises", isinstance(a, int)) try: print("Instance check with too many arguments", isinstance(a, float, int)) except Exception as e: print("Too many args", repr(e)) try: print("Instance check with too many arguments", isinstance(a)) except Exception as e: print("Too few args", repr(e)) def usingIterToCheckIterable(a): try: iter(a) except TypeError: print("not iterable") else: print("ok") usingIterToCheckIterable(1) print( "Nested constant, dict inside a list, referencing a built-in compile time constant", end=" ", ) print([dict(type=int)]) print("nan and -nan sign checks:") print("nan:", float("nan"), copysign(1.0, float("nan"))) print("-nan:", float("-nan"), copysign(1.0, float("-nan"))) print("Using != to detect nan floats:") a = float("nan") if a != a: print("is nan") else: print("isn't nan") print("inf and -inf sign checks:") print("inf:", float("inf"), copysign(1.0, float("inf"))) print("-inf:", float("-inf"), copysign(1.0, float("-inf"))) class CustomStr(str): pass class CustomBytes(bytes): pass class CustomByteArray(bytearray): pass values = [ b"100", b"", bytearray(b"100"), CustomStr("100"), CustomBytes(b"100"), CustomByteArray(b"100"), ] for x in values: try: print("int", repr(x), int(x), int(x, 2)) except (TypeError, ValueError) as e: print("caught", repr(e)) try: print("long", repr(x), long(x), long(x, 2)) except (TypeError, ValueError) as e: print("caught", repr(e)) except NameError: print("Python3 has no long") z = range(5) try: next(z) except TypeError as e: print("caught", repr(e)) try: open() except TypeError as e: print("Open without arguments gives", repr(e)) print("Type of id values:", type(id(id))) class OtherBytesSubclass(bytes): pass class BytesOverload: def __bytes__(self): return OtherBytesSubclass() b = BytesOverload() v = bytes(b) if type(v) is bytes: print("Bytes overload ineffective (expected for Python2)") elif isinstance(v, bytes): print("Bytes overload successful.") else: print("Oops, must not happen.") class OtherFloatSubclass(float): pass class FloatOverload: def __float__(self): return OtherFloatSubclass() b = FloatOverload() v = float(b) if type(v) is float: print("Float overload ineffective (must not happen)") elif isinstance(v, float): print("Float overload successful.") else: print("Oops, must not happen.") class OtherStrSubclass(str): pass class StrOverload: def __str__(self): return OtherStrSubclass() b = StrOverload() v = str(b) if type(v) is str: print("Str overload ineffective (must not happen)") elif isinstance(v, str): print("Str overload successful.") else: print("Oops, must not happen.") if str is bytes: # makes sense with Python2 only. class OtherUnicodeSubclass(unicode): # pylint: disable=undefined-variable pass class UnicodeOverload: def __unicode__(self): return OtherUnicodeSubclass() b = UnicodeOverload() v = unicode(b) # pylint: disable=undefined-variable if type(v) is unicode: # pylint: disable=undefined-variable print("Unicode overload ineffective (must not happen)") elif isinstance(v, unicode): # pylint: disable=undefined-variable print("Unicode overload successful.") else: print("Oops, must not happen.") class OtherIntSubclass(int): pass class IntOverload: def __int__(self): return OtherIntSubclass() b = IntOverload() v = int(b) if type(v) is int: print("Int overload ineffective (must not happen)") elif isinstance(v, int): print("Int overload successful.") else: print("Oops, must not happen.") if str is bytes: # Makes sense with Python2 only, no long for Python3. class OtherLongSubclass(long): # pylint: disable=undefined-variable pass class LongOverload: def __long__(self): return OtherLongSubclass() b = LongOverload() v = long(b) # pylint: disable=undefined-variable if type(v) is long: # pylint: disable=undefined-variable print("Long overload ineffective (must not happen)") elif isinstance(v, long): # pylint: disable=undefined-variable print("Long overload successful.") else: print("Oops, must not happen.") class OtherComplexSubclass(complex): pass class ComplexOverload: def __complex__(self): return OtherComplexSubclass() b = ComplexOverload() v = complex(b) if type(v) is complex: print("Complex overload ineffective (must happen)") elif isinstance(v, complex): print("Oops, must not happen.") else: print("Oops, must not happen.") print("Tests for abs():") print(abs(-(1000000 ** 10))) print(abs(len([1, 2, 3]))) print(abs(-100)) print(abs(float("nan"))) print("abs() with list:") try: print(abs([1, 2])) except Exception as e: print("caught ", repr(e)) # Making a condition >42 incrementally True def S1(): print("Yielding 40") yield 40 print("Yielding 60") yield 60 print("Yielding 30") yield 30 # Making a condition >42 incrementally False def S2(): print("Yielding 60") yield 60 print("Yielding 40") yield 40 print("Yielding 30") yield 30 # Test for "all" built-in print(all(x > 42 for x in S1())) print(all(x > 42 for x in S2())) print("Disallowed all() without args:") try: print(all()) except Exception as e: print("caught ", repr(e)) print("all() with float not iterable:") try: print(all(1.0)) except Exception as e: print("caught ", repr(e)) print("all() with float type not iterable:") try: print(any(float)) except Exception as e: print("caught ", repr(e)) print("all with compile time lists:") print(all([None, None, None])) print(all([None, 4, None])) print(all([])) print(all([0] * 20000)) print(all([0] * 255)) print("all with compile time ranges:") print(all(range(1, 10000))) print(all(range(10000))) print(all(range(2, 999, 4))) print("all with compile time strings and bytes:") print(all("Nuitka rocks!")) print(all("string")) print(all(u"unicode")) print(all(b"bytes")) print(all(b"bytes\0")) print(any(x > 42 for x in S1())) print(any(x > 42 for x in S2())) print("Disallowed any() without args:") try: print(any()) except Exception as e: print("caught ", repr(e)) print("any() with float not iterable:") try: print(any(1.0)) except Exception as e: print("caught ", repr(e)) print("any() with float type not iterable:") try: print(any(float)) except Exception as e: print("caught ", repr(e)) print("any() with sets:") print(any(set([0, 1, 2, 3, 3]))) print(any({1: "One", 2: "Two"})) print("any with compile time lists:") print(any([None, None, None])) print(any([None, 4, None])) print(any([])) print(any([0] * 20000)) print(any([0] * 255)) print("any with compile time ranges:") print(any(range(1, 10000))) print(any(range(10000))) print(any(range(2, 999, 4))) print("any with compile time strings and bytes:") print(any("Nuitka rocks!")) print(any("string")) print(any(u"unicode")) print(any(b"bytes")) print(any(b"bytes\0")) print("Tests for zip():") print(zip("abc", "cdd")) print(zip([1, 2, 3], [2, 3, 4])) print(zip([1, 2, 3], "String")) try: zip(1, "String") except TypeError as e: print("Occured", repr(e)) print(zip()) x = [(u, v) for (u, v) in zip(range(8), reversed(range(8)))] print(x) for v in zip([1, 2, 3], "String"): print(v) Nuitka-0.6.19.1/tests/basics/ParameterErrors32.py0000600000372100037210000000355314166627112026537 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def kwfunc(a, *, k): pass print("Call function with mixed arguments with too wrong keyword argument.") try: kwfunc(k=3, b=5) except TypeError as e: print(repr(e)) print("Call function with mixed arguments with too little positional arguments.") try: kwfunc(k=3) except TypeError as e: print(repr(e)) print("Call function with mixed arguments with too little positional arguments.") try: kwfunc(3) except TypeError as e: print(repr(e)) print("Call function with mixed arguments with too many positional arguments.") try: kwfunc(1, 2, k=3) except TypeError as e: print(repr(e)) def kwfuncdefaulted(a, b=None, *, c=None): pass print( "Call function with mixed arguments and defaults but too many positional arguments." ) try: kwfuncdefaulted(1, 2, 3) except TypeError as e: print(repr(e)) def kwfunc2(a, *, k, l, m): pass print( "Call function with mixed arguments with too little positional and keyword-only arguments." ) try: kwfunc2(1, l=2) except TypeError as e: print(repr(e)) try: kwfunc2(1) except TypeError as e: print(repr(e)) Nuitka-0.6.19.1/tests/basics/OrderChecks27.py0000600000372100037210000000344314166627112025620 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def setOrderCheck(): print("Checking order of set literals:") def one(): print("one") return "one" def two(): print("two") return "two" return {one(), two()} def raiseOrderCheck(): print("Checking order of raises:") def exception_type(): print("exception_type", end="") return ValueError def exception_value(): print("exception_value", end="") return 1 def exception_tb(): print("exception_value", end="") return None print("3 args", end="") try: raise exception_type(), exception_value(), exception_tb() except Exception as e: print("caught", repr(e)) print("2 args", end="") try: raise exception_type(), exception_value() except Exception as e: print("caught", repr(e)) print("1 args", end="") try: raise exception_type() except Exception as e: print("caught", repr(e)) setOrderCheck() raiseOrderCheck() Nuitka-0.6.19.1/tests/basics/TryExceptFinally.py0000600000372100037210000000434314166627112026521 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # "Some doc" from __future__ import print_function def one(): return 1 def tryScope1(x): try: try: x += one() finally: print("Finally is executed") try: _z = one() finally: print("Deep Nested finally is executed") except: print("Exception occurred") else: print("No exception occurred") tryScope1(1) print("*" * 20) tryScope1([1]) def tryScope2(x, someExceptionClass): try: x += 1 except someExceptionClass as e: print("Exception class from argument occurred:", someExceptionClass, repr(e)) else: print("No exception occurred") def tryScope3(x): if x: try: x += 1 except TypeError: print("TypeError occurred") else: print("Not taken") print("*" * 20) tryScope2(1, TypeError) tryScope2([1], TypeError) print("*" * 20) tryScope3(1) tryScope3([1]) tryScope3([]) print("*" * 20) def tryScope4(x): try: x += 1 except: print("exception occurred") else: print("no exception occurred") finally: print("finally obeyed") tryScope4(1) tryScope4([1]) def tryScope5(): import sys print("Exception info is initially", sys.exc_info()) try: try: undefined_global += 1 finally: print("Exception info in 'finally' clause is", sys.exc_info()) except: pass tryScope5() Nuitka-0.6.19.1/tests/basics/Inspection.py0000600000372100037210000001061414166627112025364 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Tests uncompiled functions and compiled functions responses to inspect and isistance. """ from __future__ import print_function import inspect import pprint import sys import types def displayDict(d, remove_keys=()): if "__loader__" in d: d = dict(d) d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d = dict(d) d["__file__"] = "<__file__ removed>" if "__compiled__" in d: d = dict(d) del d["__compiled__"] for remove_key in remove_keys: if remove_key in d: d = dict(d) del d[remove_key] return pprint.pformat(d) def compiledFunction(a, b): pass print("Function inspect.isfunction:", inspect.isfunction(compiledFunction)) print( "Function isinstance types.FunctionType:", isinstance(compiledFunction, types.FunctionType), ) print( "Function isinstance tuple containing types.FunctionType:", isinstance(compiledFunction, (int, types.FunctionType)), ) print("Compiled spec:", inspect.getargspec(compiledFunction)) print("Compiled args:", inspect.formatargspec(*inspect.getargspec(compiledFunction))) # Even this works. assert type(compiledFunction) == types.FunctionType class CompiledClass: def __init__(self): pass def compiledMethod(self): pass assert inspect.isfunction(CompiledClass) is False assert isinstance(CompiledClass, types.FunctionType) is False assert inspect.ismethod(compiledFunction) is False assert inspect.ismethod(CompiledClass) is False assert inspect.ismethod(CompiledClass.compiledMethod) == (sys.version_info < (3,)) assert inspect.ismethod(CompiledClass().compiledMethod) is True assert bool(type(CompiledClass.compiledMethod) == types.MethodType) == ( sys.version_info < (3,) ) print("Compiled method:", inspect.getargspec(CompiledClass().compiledMethod)) print( "Compiled class:", inspect.formatargspec(*inspect.getargspec(CompiledClass().compiledMethod)), ) def compiledGenerator(): yield 1 assert inspect.isfunction(compiledGenerator) is True assert inspect.isgeneratorfunction(compiledGenerator) is True assert isinstance(compiledGenerator(), types.GeneratorType) is True assert type(compiledGenerator()) == types.GeneratorType assert isinstance(compiledGenerator, types.GeneratorType) is False assert inspect.ismethod(compiledGenerator()) is False assert inspect.isfunction(compiledGenerator()) is False assert inspect.isgenerator(compiledFunction) is False assert inspect.isgenerator(compiledGenerator) is False assert inspect.isgenerator(compiledGenerator()) is True def someFunction(a): assert inspect.isframe(sys._getframe()) # print("Running frame getframeinfo()", inspect.getframeinfo(sys._getframe())) # TODO: The locals of the frame are not updated. # print("Running frame arg values", inspect.getargvalues(sys._getframe())) someFunction(2) class C: print( "Class locals", displayDict( sys._getframe().f_locals, remove_keys=("__qualname__", "__locals__") ), ) print("Class flags", sys._getframe().f_code.co_flags) def f(): print("Func locals", sys._getframe().f_locals) print("Func flags", sys._getframe().f_code.co_flags) f() def g(): yield ("Generator object locals", sys._getframe().f_locals) yield ("Generator object flags", sys._getframe().f_code.co_flags) for line in g(): print(*line) print("Generator function flags", g.__code__.co_flags) print("Module frame locals", displayDict(sys._getframe().f_locals)) print("Module flags", sys._getframe().f_code.co_flags) print("Module code name", sys._getframe().f_code.co_name) print("Module frame dir", dir(sys._getframe())) Nuitka-0.6.19.1/tests/basics/Referencing.py0000600000372100037210000005644514166627112025514 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. """ # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) from nuitka.tools.testing.Common import executeReferenceChecked # isort:start # Tests do all bad things: # pylint: disable=misplaced-bare-raise,raising-bad-type,reimported,undefined-variable # pylint: disable=broad-except,eval-used,redefined-outer-name,unused-argument,unused-variable # pylint: disable=attribute-defined-outside-init,bare-except,lost-exception,pointless-statement # pylint: disable=exec-used,global-statement,invalid-name,not-callable,super-init-not-called x = 17 # Just a function return a constant. Functions don't become any smaller. Let's # get that right. def simpleFunction1(): return 1 # Do a bit of math with a local variable, assigning to its value and then doing # an overwrite of that, trying that math again. This should cover local access # a bit. def simpleFunction2(): y = 3 * x y = 3 return x * 2 * y # A local function is being returned. This covers creation of local functions # and their release. No closure variables involved yet. def simpleFunction3(): def contained(): return x return contained # Again, local function being return, but this time with local variable taken # as a closure. We use value from defaulted argument, so it cannot be replaced. def simpleFunction4(a=1): y = a def contained(): return y return contained # Default argument and building a list as local variables. Also return them, # so they are not optimized away. def simpleFunction5(a=2): c = 1 f = [a, a + c] return c, f def simpleFunction6(): for _b in range(6): pass for _c in (1, 2, 3, 4, 5, 6): pass def simpleFunction7(b=1): for _b in range(6): pass def simpleFunction8(): c = [] c.append(x) def simpleFunction9(a=1 * 2): if a == a: pass u = None def simpleFunction10(a=1 * 2): x = [u for u in range(8)] def simpleFunction11(): f = 1 while f < 8: f += 1 v = None def simpleFunction12(): a = [(u, v) for (u, v) in zip(range(8), range(8))] return a def cond(): return 1 def simpleFunction13(a=1 * 2): pass def simpleFunction14p(x): try: simpleFunction14p(1, 1) # pylint: disable=too-many-function-args except TypeError as _e: pass try: simpleFunction14p(1, 1) # pylint: disable=too-many-function-args except TypeError: pass def simpleFunction14(): simpleFunction14p(3) def simpleFunction15p(x): try: try: x += 1 finally: try: x *= 1 finally: _z = 1 except: pass def simpleFunction15(): simpleFunction15p([1]) def simpleFunction16(): class EmptyClass: pass return EmptyClass def simpleFunction17(): class EmptyObjectClass: pass return EmptyObjectClass() def simpleFunction18(): closured = 1 class NonEmptyClass: def __init__(self, a, b): self.a = a self.b = b inside = closured return NonEmptyClass(133, 135) def simpleFunction19(): lam = lambda l: l + 1 return lam(9), lam def simpleFunction20(): try: a = [] a[1] except IndexError as _e: pass def simpleFunction21(): class EmptyBaseClass: def base(self): return 3 class EmptyObjectClass(EmptyBaseClass): pass result = EmptyObjectClass() c = result.base() return result, c def simpleFunction22(): return True is False and False is not None def simpleFunction23(): not 2 def simpleFunction24p(x): pass def simpleFunction24(): simpleFunction24p(x=3) def simpleFunction25(): class X: f = 1 def inplace_adder(b): X.f += b return inplace_adder(6 ** 8) def simpleFunction26(): class X: f = [5] def inplace_adder(b): X.f += b return inplace_adder([1, 2]) def simpleFunction27(): a = {"g": 8} def inplace_adder(b): a["g"] += b return inplace_adder(3) def simpleFunction28(): a = {"g": [8], "h": 2} def inplace_adder(b): a["g"] += b return inplace_adder([3, 5]) def simpleFunction29(): return "3" in "7" def simpleFunction30(): def generatorFunction(): yield 1 yield 2 yield 3 def simpleFunction31(): def generatorFunction(): yield 1 yield 2 yield 3 a = [] for y in generatorFunction(): a.append(y) for z in generatorFunction(): a.append(z) def simpleFunction32(): def generatorFunction(): yield 1 gen = generatorFunction() next(gen) def simpleFunction33(): def generatorFunction(): a = 1 yield a a = [] for y in generatorFunction(): a.append(y) def simpleFunction34(): try: raise ValueError except: pass def simpleFunction35(): try: raise ValueError(1, 2, 3) except: pass def simpleFunction36(): try: raise (TypeError, (3, x, x, x)) except TypeError: pass def simpleFunction37(): l = [1, 2, 3] try: _a, _b = l except ValueError: pass def simpleFunction38(): class Base: pass class Parent(Base): pass def simpleFunction39(): class Parent(object): pass def simpleFunction40(): def myGenerator(): yield 1 myGenerator() def simpleFunction41(): a = b = 2 return a, b def simpleFunction42(): a = b = 2 * x return a, b def simpleFunction43(): class D: pass a = D() a.b = 1 def simpleFunction47(): def reraisy(): def raisingFunction(): raise ValueError(3) def reraiser(): raise try: raisingFunction() except: reraiser() try: reraisy() except: pass def simpleFunction48(): class BlockExceptions: def __enter__(self): pass def __exit__(self, exc, val, tb): return True with BlockExceptions(): raise ValueError() template = "lala %s lala" def simpleFunction49(): c = 3 d = 4 a = x, y = b, e = (c, d) return a, y, b, e b = range(10) def simpleFunction50(): def getF(): def f(): for i in b: yield i return f f = getF() for x in range(2): _r = list(f()) def simpleFunction51(): g = (x for x in range(9)) try: g.throw(ValueError, 9) except ValueError as _e: pass def simpleFunction52(): g = (x for x in range(9)) try: g.throw(ValueError(9)) except ValueError as _e: pass def simpleFunction53(): g = (x for x in range(9)) try: g.send(9) except TypeError as _e: pass def simpleFunction54(): g = (x for x in range(9)) next(g) try: g.send(9) except TypeError as _e: pass def simpleFunction55(): g = (x for x in range(9)) try: g.close() except ValueError as _e: pass def simpleFunction56(): """Throw into finished generator.""" g = (x for x in range(9)) list(g) try: g.throw(ValueError(9)) except ValueError as _e: pass def simpleFunction60(): x = 1 y = 2 def f(a=x, b=y): return a, b f() f(2) f(3, 4) def simpleFunction61(): a = 3 b = 5 try: a = a * 2 return a finally: a / b def simpleFunction62(): a = 3 b = 5 try: a = a * 2 return a finally: return a / b class X: def __del__(self): # Super used to reference leak. x = super() raise ValueError(1) def simpleFunction63(): def superUser(): X() try: superUser() except Exception: pass def simpleFunction64(): x = 2 y = 3 z = eval("x * y") return z def simpleFunction65(): import array a = array.array("b", b"") assert a == eval(repr(a), {"array": array.array}) d = {"x": 2, "y": 3} z = eval(repr(d), d) return z def simpleFunction66(): import types return type(simpleFunction65) == types.FunctionType def simpleFunction67(): length = 100000 pattern = "1234567890\00\01\02\03\04\05\06" q, r = divmod(length, len(pattern)) teststring = pattern * q + pattern[:r] return teststring def simpleFunction68(): from random import randrange x = randrange(18) def simpleFunction69(): pools = [tuple()] g = ((len(pool) == 0,) for pool in pools) next(g) def simpleFunction70(): def gen(): try: undefined_yyy except Exception: pass yield sys.exc_info() try: undefined_xxx except Exception: return list(gen()) def simpleFunction71(): try: undefined_global except Exception: try: try: raise finally: undefined_global except Exception: pass def simpleFunction72(): try: for _i in range(10): try: undefined_global finally: break except Exception: pass def simpleFunction73(): for _i in range(10): try: undefined_global finally: return 7 def simpleFunction74(): import os # @Reimport return os def simpleFunction75(): def raising_gen(): try: raise TypeError except TypeError: yield g = raising_gen() next(g) try: g.throw(RuntimeError()) except RuntimeError: pass def simpleFunction76(): class MyException(Exception): def __init__(self, obj): self.obj = obj class MyObj: pass def inner_raising_func(): raise MyException(MyObj()) try: inner_raising_func() except MyException: try: try: raise finally: raise except MyException: pass class weirdstr(str): def __getitem__(self, index): return weirdstr(str.__getitem__(self, index)) def simpleFunction77(): return filter(lambda x: x >= "33", weirdstr("1234")) def simpleFunction78(): a = "x = 2" exec(a) def simpleFunction79(): "some doc" simpleFunction79.__doc__ = simpleFunction79.__doc__.replace("doc", "dok") simpleFunction79.__doc__ += " and more" + simpleFunction79.__name__ def simpleFunction80(): "some doc" del simpleFunction80.__doc__ def simpleFunction81(): def f(): yield 1 j j = 1 x = list(f()) def simpleFunction82(): def f(): yield 1 j j = 1 x = f.__doc__ def simpleFunction83(): x = list(range(7)) x[2] = 5 j = 3 x += [h * 2 for h in range(j)] def simpleFunction84(): x = tuple(range(7)) j = 3 x += tuple([h * 2 for h in range(j)]) def simpleFunction85(): x = list(range(7)) x[2] = 3 x *= 2 def simpleFunction86(): x = "something" x += "" def simpleFunction87(): x = 7 x += 2000 class C: def f(self): pass def __iadd__(self, other): return self def method_function(*args, **kwargs): # Make sure to mutate the list argument value if "x" in kwargs: x = kwargs["x"] if type(x) is list: x.append(1) for x in args: if type(x) is list: x.append(1) return args, kwargs exec( """ def method_uncompiled_function(*args, **kwargs): # Make sure to mutate the list argument value if "x" in kwargs: x = kwargs["x"] if type(x) is list: x.append(1) for x in args: if type(x) is list: x.append(1) return args, kwargs """ ) def method_function_with_defaults(self, a, b, c, d=1, e=2, f=3): return True def simpleFunction88(): x = C() x += C() def simpleFunction89(): x = [1, 2] x += [3, 4] def anyArgs(*args, **kw): return kw.keys(), kw.values() def simpleFunction90(): some_tuple = (simpleFunction89, simpleFunction89, simpleFunction89) anyArgs(*some_tuple) def simpleFunction91(): some_dict = {"a": simpleFunction90} anyArgs(**some_dict) def simpleFunction92(): some_tuple = (simpleFunction89,) some_dict = {"a": simpleFunction90} anyArgs(*some_tuple, **some_dict) def simpleFunction93(): some_tuple = (simpleFunction89,) some_dict = {"a": simpleFunction90} anyArgs(some_tuple, *some_tuple, **some_dict) def simpleFunction94(): some_tuple = (simpleFunction89,) some_dict = {"a": simpleFunction90} anyArgs(*some_tuple, b=some_dict, **some_dict) def simpleFunction95(): some_tuple = (simpleFunction89,) some_dict = {"a": simpleFunction90} anyArgs(some_tuple, *some_tuple, b=some_dict, **some_dict) def simpleFunction96(): some_tuple = (simpleFunction89,) anyArgs(some_tuple, *some_tuple) # Complex call with dictionary and key arguments only. def simpleFunction97(): some_dict = {"a": simpleFunction90, "d": simpleFunction91} anyArgs(b=some_dict, c=1, **some_dict) def simpleFunction98(): some_tuple = (simpleFunction89,) anyArgs(*some_tuple, b=some_tuple) def simpleFunction99(): some_dict = {"a": simpleFunction90} anyArgs(some_dict, **some_dict) def simpleFunction100(): def h(f): def g(): return f return g def f(): pass h(f) def simpleFunction101(): def orMaking(a, b): x = "axa" x += a or b orMaking("x", "") #################################### class SomeClassWithAttributeAccess(object): READING = 1 def use(self): return self.READING def simpleFunction102(): SomeClassWithAttributeAccess().use() SomeClassWithAttributeAccess().use() #################################### def getInt(): return 3 def simpleFunction103(): try: raise getInt() except TypeError: pass #################################### class ClassWithGeneratorMethod: def generator_method(self): yield self def simpleFunction104(): return list(ClassWithGeneratorMethod().generator_method()) def simpleFunction105(): """Delete a started generator, not properly closing it before releasing.""" def generator(): yield 1 yield 2 g = generator() next(g) del g def simpleFunction106(): # Call a PyCFunction with a single argument. return sys.getsizeof(type) def simpleFunction107(): # Call a PyCFunction with a single argument. return sum(i for i in range(x)) def simpleFunction108(): # Call a PyCFunction with a single argument. return sum((i for i in range(x)), 17) def simpleFunction109(): # Call a PyCFunction that looks like a method call. sys.exc_info() def simpleFunction110(): def my_open(*args, **kwargs): return (args, kwargs) orig_open = __builtins__.open __builtins__.open = my_open open("me", buffering=True) __builtins__.open = orig_open #################################### u = u"__name__" def simpleFunction111(): return getattr(simpleFunction111, u) #################################### def simpleFunction112(): TESTFN = "tmp.txt" import codecs try: with open(TESTFN, "wb") as out_file: out_file.write(b"\xa1") f = codecs.open(TESTFN, encoding="cp949") f.read(2) except UnicodeDecodeError: pass finally: try: f.close() except Exception: pass try: os.unlink(TESTFN) except Exception: pass #################################### def simpleFunction113(): class A(object): pass a = A() a.a = a return a l = [] def simpleFunction114(): global l l += ["something"] # Erase it to avoid reference change. del l[:] i = 2 ** 16 + 1 def simpleFunction115(): global i i += 1 t = tuple(range(259)) def simpleFunction116(): global t t += (2, 3) t = tuple(range(259)) def simpleFunction117(): # Operation tuple+object, error case. try: return tuple(t) + i except TypeError: pass def simpleFunction118(): # Operation tuple+object, error case. try: return i + tuple(t) except TypeError: pass t2 = tuple(range(9)) def simpleFunction119(): # Operation tuple+object no error case. return tuple(t) + t2 def simpleFunction120(): # Operation object+tuple no error case. return t2 + tuple(t) def simpleFunction121(): # Operation tuple+tuple return tuple(t2) + tuple(t) def simpleFunction122(): # Operation list+object, error case. try: return list(t) + i except TypeError: pass def simpleFunction123(): # Operation list+object, error case. try: return i + list(t) except TypeError: pass l2 = list(range(9)) def simpleFunction124(): # Operation list+object no error case. return list(t) + l2 def simpleFunction125(): # Operation object+list no error case. return l2 + list(t) def simpleFunction126(): # Operation tuple+tuple return list(l2) + list(t) class TupleWithSlots(tuple): def __add__(self, other): return 42 def __radd__(self, other): return 42 def simpleFunction127(): # Operation tuple+object with add slot. return tuple(t) + TupleWithSlots() def simpleFunction128(): # Operation object+tuple with add slot. return TupleWithSlots() + tuple(t) class ListWithSlots(list): def __add__(self, other): return 42 def __radd__(self, other): return 42 def simpleFunction129(): # Operation list+object with add slot. return list(t) + ListWithSlots() def simpleFunction130(): # Operation list+object with add slot. return ListWithSlots() + list(t) def simpleFunction131(): try: C().f.__reduce__() except Exception as e: assert sys.version_info < (3, 4) def simpleFunction132(): C().f.__reduce_ex__(5) x = 5 def local_function(*args, **kwargs): # Make sure to mutate the list argument value if "x" in kwargs: x = kwargs["x"] if type(x) is list: x.append(1) for x in args: if type(x) is list: x.append(1) return args, kwargs exec( """ def local_uncompiled_function(*args, **kwargs): # Make sure to mutate the list argument value if "x" in kwargs: x = kwargs["x"] if type(x) is list: x.append(1) for x in args: if type(x) is list: x.append(1) return args, kwargs """ ) def simpleFunction133(): local_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) local_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) local_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) local_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=[]) local_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) local_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) local_function(1, 2, 3, 4, 5, 6, 7, [], 9, 10, 11, x=[]) local_function(x=1) local_function(x=x) local_function(x=[]) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=[]) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) local_uncompiled_function(1, 2, 3, 4, 5, 6, 7, [], 9, 10, 11, x=[]) local_uncompiled_function(x=1) local_uncompiled_function(x=x) local_uncompiled_function(x=[]) c = C() C().method_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) C.method_function(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) C().method_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) C().method_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=[1]) C.method_function(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) C().method_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) C.method_function(c, 1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) C().method_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) C.method_function(c, 1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) C().method_function(1, 2, 3, 4, 5, 6, 7, [1], 9, 10, 11, x=[1]) C.method_function(c, 1, 2, 3, 4, 5, 6, 7, [1], 9, 10, 11, x=[1]) C().method_function(x=1) C().method_function(x=x) C().method_function(x=[1]) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) C.method_uncompiled_function(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=1) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=[1]) C.method_uncompiled_function(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, x=x) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) C.method_uncompiled_function(c, 1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=1) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) C.method_uncompiled_function(c, 1, 2, 3, 4, 5, 6, 7, x, 9, 10, 11, x=x) C().method_uncompiled_function(1, 2, 3, 4, 5, 6, 7, [1], 9, 10, 11, x=[1]) C.method_uncompiled_function(c, 1, 2, 3, 4, 5, 6, 7, [1], 9, 10, 11, x=[1]) C().method_uncompiled_function(x=1) C().method_uncompiled_function(x=x) C().method_uncompiled_function(x=[1]) C().method_function_with_defaults(1, 2, 3, d=1) C().method_function_with_defaults(1, x, 3, d=x) C().method_function_with_defaults(1, x, 3, d=[1]) #################################### # These need stderr to be wrapped. tests_stderr = (63,) # Disabled tests tests_skipped = {} result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/Constants27.py0000600000372100037210000000174314166627112025401 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("Clash in constants reveals order:") x = {True, 1} print(x) print("Complex constant using sets with clashes at run time:") y = True x = ({1}, {1, True}, {1, 1.0}, {1, y}) print(x) Nuitka-0.6.19.1/tests/basics/run_all.py0000700000372100037210000000733714166627112024716 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runner for basic tests of Nuitka. Basic tests are those that cover our back quickly, but need not necessarily, be complete. """ import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import ( compareWithCPython, createSearchMode, decideNeeds2to3, hasDebugPython, scanDirectoryForTestCases, setup, ) def main(): setup(suite="basics", needs_io_encoding=True) search_mode = createSearchMode() # Now run all the tests in this directory. for filename in scanDirectoryForTestCases("."): extra_flags = [ # No error exits normally, unless we break tests, and that we would # like to know. "expect_success", # Keep no temporary files. "remove_output", # Do not follow imports. "--nofollow-imports", # Use the original __file__ value, at least one case warns about things # with filename included. "--file-reference-choice=original", # Cache the CPython results for re-use, they will normally not change. "cpython_cache", # To understand what is slow. "timing", # We annotate some tests, use that to lower warnings. "plugin_enable:pylint-warnings", ] # This test should be run with the debug Python, and makes outputs to # standard error that might be ignored. if filename.startswith("Referencing"): if hasDebugPython(): extra_flags.append("python_debug") # This tests warns about __import__() used. if filename == "OrderChecks.py": extra_flags.append("ignore_warnings") # This tests warns about an package relative import despite # being in no package. if filename == "Importing.py": extra_flags.append("ignore_warnings") # TODO: Nuitka does not give output for ignored exception in dtor, this is # not fully compatible and potentially an error. if filename == "YieldFrom33.py": extra_flags.append("ignore_stderr") # For Python2 there is a "builtins" package that gives warnings. TODO: We # ought to NOT import that package and detect statically that __builtins__ # import won't raise ImportError. if filename == "BuiltinOverload.py": extra_flags.append("ignore_warnings") active = search_mode.consider(dirname=None, filename=filename) if active: compareWithCPython( dirname=None, filename=filename, extra_flags=extra_flags, search_mode=search_mode, needs_2to3=decideNeeds2to3(filename), ) search_mode.finish() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/basics/ExecEval.py0000600000372100037210000001513114166627112024744 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import os import sys import tempfile print "eval 3+3=", eval("3+3") print "eval 4+4=", eval(" 4+4") def functionEval1(): return eval(" 5+5") print "eval in a function with nothing provided", functionEval1() def functionEval2(): a = [2] g = {} r = eval("1+3", g) return r, g.keys(), a print "eval in a function with globals provided", functionEval2() def functionEval3(): result = [] for x in eval("(1,2)"): result.append(x) return result print "eval in a for loop as iterator giver", functionEval3() print "exec on a global level", exec ("d=2+2") print "2+2=", d def functionExec1(): a = 1 code = "a=2" exec (code) return a def functionExec2(): a = 1 code = "a=2" exec code in globals(), locals() return a print "exec in function without and with locals() provided:", functionExec1(), functionExec2() tmp_filename = tempfile.gettempdir() + "/execfile.py" f = open(tmp_filename, "w") f.write("e=7\nf=8\n") f.close() execfile(tmp_filename) print "execfile with defaults f,g=", e, f global_vars = {"e": "0", "f": 0} local_vars = dict(global_vars) execfile(tmp_filename, global_vars) print "execfile with globals dict:", global_vars.keys() execfile(tmp_filename, global_vars, local_vars) print "execfile with globals and locals dict:", local_vars def functionExecfile(): e = 0 f = 0 global_vars = {"e": "0", "f": 0} local_vars = dict(global_vars) print "execfile with globals and locals dict in a function:", x = execfile(tmp_filename, global_vars, local_vars) print x, print global_vars.keys(), local_vars, e, f functionExecfile() class classExecfile: e = 0 f = 0 print "execfile in a class:", # TODO: Won't work yet, Issue#5 # print execfile( tmp_filename ), execfile(tmp_filename) print "execfile changed local values:", e, f f = 7 def functionExecNonesTuple(): f = 0 exec ("f=1", None, None) print "Exec with None as optimizable tuple args did update locals:", f def functionExecNonesSyntax(): f = 0 exec "f=2" in None, None print "Exec with None as optimizable normal args did update locals:", f functionExecNonesTuple() functionExecNonesSyntax() print "Global value is untouched", f def functionEvalNones2(): f = 11 code = "f" g = None l = None f1 = eval(code, l, g) print "Eval with None arguments from variables did access locals:", f1 functionEvalNones2() def functionExecNonesTuple2(): f = 0 code = "f=1" g = None l = None exec (code, l, g) print "Exec with None as tuple args from variable did update locals:", f def functionExecNonesSyntax2(): f = 0 code = "f=2" g = None l = None exec code in l, g print "Exec with None as normal args did update locals:", f functionExecNonesTuple2() functionExecNonesSyntax2() print "Exec with a future division definition and one without:" exec """ from __future__ import division from __future__ import print_function print( "3/2 is with future division", 3/2 ) """ exec """ from __future__ import print_function print( "3/2 is without future division", 3/2 ) """ x = 1 y = 1 def functionGlobalsExecShadow(): global x print "Global x outside is", x y = 0 print "Local y is initially", y print "Locals initially", locals() exec """ from __future__ import print_function x = 2 print( "Exec local x is", x ) """ print "Function global x referenced as local x in exec is", x exec """ from __future__ import print_function print( "Re-exec local x", x ) """ print "Locals after exec assigning to local x", locals() exec """ from __future__ import print_function global x x = 3 print( "Exec global x is inside exec", x ) """ print "Global x referenced as global x in exec is", x exec """ from __future__ import print_function def change_y(): global y y = 4 print( "Exec function global y is", y ) y = 7 change_y() # TODO: The below will not work print( "Exec local y is", y ) """ # print "Local y is afterwards", y def print_global_y(): global y # TODO: The below will not work print "Global y outside", y print_global_y() print "Outside y", y functionGlobalsExecShadow() def functionWithClosureProvidedByExec(): code = "ValueError = TypeError" exec code in None, None def func(): print "Closure from exec not used", ValueError func() functionWithClosureProvidedByExec() x = 2 def functionWithExecAffectingClosure(): x = 4 code = "d=3;x=5" space = locals() exec code in space def closureMaker(): return x return d, closureMaker() print "Closure in a function with exec to not none", functionWithExecAffectingClosure() def generatorFunctionWithExec(): yield 1 code = "y = 2" exec code yield y print "Exec in a generator function", tuple(generatorFunctionWithExec()) def evalInContractions(): r1 = list(eval(str(s)) for s in range(3)) r2 = [eval(str(s)) for s in range(4)] return r1, r2 print "Eval in a list contraction or generator expression", evalInContractions() def execDefinesFunctionToLocalsExplicity(): exec """\ def makeAddPair(a, b): def addPair(c, d): return (a + c, b + d) return addPair """ in locals() if sys.version_info < (3,): assert makeAddPair return "yes" print "Exec adds functions declares in explicit locals() given.", execDefinesFunctionToLocalsExplicity() os.unlink(tmp_filename) def execWithShortTuple(): try: exec ("print hey",) except Exception as e: return "gives exception: " + repr(e) print "Exec with too short tuple argument:", execWithShortTuple() if str is not bytes: def evalMemoryView(value): return eval(memoryview(value)) print "Eval with memory view:", evalMemoryView(b"27") Nuitka-0.6.19.1/tests/basics/Functions.py0000600000372100037210000003006514166627112025223 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Various kinds of functions with small specialties. """ from __future__ import print_function import inspect import sys # pylint: disable=redefined-outer-name var_on_module_level = 1 def closureTest1(some_arg): # pylint: disable=unused-argument x = 3 def enclosed(_f="default_value"): return x return enclosed print("Call closured function returning function:", closureTest1(some_arg="ignored")()) def closureTest2(some_arg): # pylint: disable=unused-argument def enclosed(_f="default_value"): return x x = 4 return enclosed print("Call closured function returning function:", closureTest2(some_arg="ignored")()) def defaultValueTest1(_no_default, some_default_constant=1): return some_default_constant print( "Call function with 2 parameters, one defaulted, and check that the default value is used:", defaultValueTest1("ignored"), ) def defaultValueTest1a( _no_default, some_default_constant_1=1, some_default_constant_2=2 ): return some_default_constant_2 - some_default_constant_1 print( "Call function with 3 parameters, 2 defaulted, check they are used correctly:", defaultValueTest1a("ignored"), ) def defaultValueTest2(_no_default, some_default_variable=var_on_module_level * 2): return some_default_variable print( "Call function with 2 parameters, 1 defaulted with an expression, check its result", defaultValueTest2("ignored"), ) var_on_module_level = 2 print( "Call function with 2 parameters, 1 defaulted with an expression, values have changed since, check its result", defaultValueTest2("ignored"), ) def contractionTest(): j = 2 return [j + i for i in range(8)] print("Call function that returns a list contraction:", contractionTest()) def defaultValueTest3a( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): return [i + funced_defaulted for i in range(8)] print( "Call function that has a default value coming from a function call:", defaultValueTest3a("ignored"), ) def defaultValueTest3b( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): local_var = [funced_defaulted + i for i in range(8)] return local_var print( "Call function that returns a list contraction result via a local variable:", defaultValueTest3b("ignored"), ) def defaultValueTest3c( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): local_var = [[j + funced_defaulted + 1 for j in range(i)] for i in range(8)] return local_var print( "Call function that returns a nested list contraction with input from default parameter", defaultValueTest3c("ignored"), ) def defaultValueTest4(_no_default, funced_defaulted=lambda x: x ** 2): return funced_defaulted(4) print( "Call function that returns value calculated by a lambda function as default parameter", defaultValueTest4("ignored"), ) def defaultValueTest4a(_no_default, funced_defaulted=lambda x: x ** 2): c = 1 d = funced_defaulted(1) r = (i + j + c + d for i, j in zip(range(8), range(9))) l = [] for x in r: l.append(x) return l print( "Call function that has a lambda calculated default parameter and a generator expression", defaultValueTest4a("ignored"), ) def defaultValueTest4b(_no_default, funced_defaulted=lambda x: x ** 3): d = funced_defaulted(1) # Nested generators l = [] for x in ((d + j for j in range(4)) for i in range(8)): for y in x: l.append(y) return l print( "Call function that has a lambda calculated default parameter and a nested generator expression", defaultValueTest4b("ignored"), ) def defaultValueTest5(_no_default, tuple_defaulted=(1, 2, 3)): return tuple_defaulted print("Call function with default value that is a tuple", defaultValueTest5("ignored")) def defaultValueTest6( _no_default, list_defaulted=[1, 2, 3] ): # pylint: disable=dangerous-default-value return list_defaulted print("Call function with default value that is a list", defaultValueTest6("ignored")) x = len("hey") # TODO: Doesn't belong here. def in_test(a): # if 7 in a: # print "hey" # pylint: disable=pointless-statement 8 in a # @NoEffect 9 not in a # @NoEffect in_test([8]) try: in_test(9) except TypeError: pass def my_deco(function): def new_function(c, d): return function(d, c) return new_function @my_deco def decoriert(a, b): # pylint: disable=unused-argument def subby(a): return 2 + a return 1 + subby(b) print("Function with decoration", decoriert(3, 9)) def functionWithGlobalReturnValue(): global a # pylint: disable=global-statement return a a = "oh common" some_constant_tuple = (2, 5, 7) some_semiconstant_tuple = (2, 5, a) f = a * 2 print(defaultValueTest1("ignored")) # The change of the default variable doesn't influence the default # parameter of defaultValueTest2, that means it's also calculated # at the time the function is defined. module_level = 7 print(defaultValueTest2("also ignored")) def starArgTest(a, b, c): return a, b, c print("Function called with star arg from tuple:") star_list_arg = (11, 44, 77) print(starArgTest(*star_list_arg)) print("Function called with star arg from list:") star_list_arg = [7, 8, 9] print(starArgTest(*star_list_arg)) star_dict_arg = {"a": 9, "b": 3, "c": 8} print("Function called with star arg from dict") print(starArgTest(**star_dict_arg)) lambda_func = lambda a, b: a < b lambda_args = (8, 9) print("Lambda function called with star args from tuple:") print(lambda_func(*lambda_args)) print("Lambda function called with star args from list:") lambda_args = [8, 7] print(lambda_func(*lambda_args)) print("Generator function without context:") def generator_without_context_function(): gen = (x for x in range(9)) return tuple(gen) print(generator_without_context_function()) print("Generator function with 2 iterateds:") def generator_with_2_fors(): return tuple((x, y) for x in range(2) for y in range(3)) print(generator_with_2_fors()) def someYielder(): yield 1 yield 2 def someYieldFunctionUser(): print("someYielder", someYielder()) result = [] for a in someYielder(): result.append(a) return result print("Function that uses some yielding function coroutine:") print(someYieldFunctionUser()) def someLoopYielder(): for i in (0, 1, 2): yield i def someLoopYieldFunctionUser(): result = [] for a in someLoopYielder(): result.append(a) return result print("Function that uses some yielding function coroutine that loops:") print(someLoopYieldFunctionUser()) def someGeneratorClosureUser(): def someGenerator(): def userOfGeneratorLocalVar(): return x + 1 x = 2 yield userOfGeneratorLocalVar() yield 6 gen = someGenerator() return [next(gen), next(gen)] print( "Function generator that uses a local function accessing its local variables to yield:" ) print(someGeneratorClosureUser()) def someClosureUsingGeneratorUser(): offered = 7 def someGenerator(): yield offered return next(someGenerator()) print("Function generator that yield from its closure:") print(someClosureUsingGeneratorUser()) print("Function call with both star args and named args:") def someFunction(a, b, c, d): print(a, b, c, d) someFunction(a=1, b=2, **{"c": 3, "d": 4}) print("Order of evaluation of function and args:") def getFunction(): print("getFunction", end="") def x(y, u, a, k): return y, u, k, a return x def getPlainArg1(): print("getPlainArg1", end="") return 9 def getPlainArg2(): print("getPlainArg2", end="") return 13 def getKeywordArg1(): print("getKeywordArg1", end="") return "a" def getKeywordArg2(): print("getKeywordArg2", end="") return "b" getFunction()(getPlainArg1(), getPlainArg2(), k=getKeywordArg1(), a=getKeywordArg2()) print() def getListStarArg(): print("getListStarArg", end="") return [1] def getDictStarArg(): print("getDictStarArg", end="") return {"k": 9} print("Same with star args:") getFunction()(getPlainArg1(), a=getKeywordArg1(), *getListStarArg(), **getDictStarArg()) print() print("Dictionary creation order:") d = {getKeywordArg1(): getPlainArg1(), getKeywordArg2(): getPlainArg2()} print() print("Throwing an exception to a generator function:") def someGeneratorFunction(): try: yield 1 yield 2 except Exception: # pylint: disable=broad-except yield 3 yield 4 gen1 = someGeneratorFunction() print("Fresh Generator Function throwing gives", end="") try: print(gen1.throw(ValueError)), except ValueError: print("exception indeed") gen2 = someGeneratorFunction() print("Used Generator Function throwing gives", end="") next(gen2) print(gen2.throw(ValueError), "indeed") gen3 = someGeneratorFunction() print("Fresh Generator Function close gives", end="") print(gen3.close()) gen4 = someGeneratorFunction() print("Used Generator Function that mis-catches close gives", end="") next(gen4) try: print(gen4.close(), end="") except RuntimeError: print("runtime exception indeed") gen5 = someGeneratorFunction() print("Used Generator Function close gives", end="") next(gen5) next(gen5) next(gen5) print(gen5.close(), end="") def receivingGenerator(): while True: a = yield 4 yield a print("Generator function that receives", end="") gen6 = receivingGenerator() print(next(gen6), end="") print(gen6.send(5), end="") print(gen6.send(6), end="") print(gen6.send(7), end="") print(gen6.send(8)) print("Generator function whose generator is copied", end="") def generatorFunction(): yield 1 yield 2 gen7 = generatorFunction() next(gen7) gen8 = iter(gen7) print(next(gen8)) def doubleStarArgs(*a, **d): return a, d try: from UserDict import UserDict except ImportError: print("Using Python3, making own non-dict dict:") class UserDict(dict): pass print("Function that has keyword argument matching the list star arg name", end="") print(doubleStarArgs(1, **UserDict(a=2))) def generatorFunctionUnusedArg(_a): yield 1 generatorFunctionUnusedArg(3) def closureHavingGenerator(arg): def gen(_x=1): yield arg return gen() print("Function generator that has a closure and default argument", end="") print(list(closureHavingGenerator(3))) def functionWithDualStarArgsAndKeywordsOnly(a1, a2, a3, a4, b): return a1, a2, a3, a4, b l = [1, 2, 3] d = {"b": 8} print( "Dual star args, but not positional call", functionWithDualStarArgsAndKeywordsOnly(a4=1, *l, **d), ) def posDoubleStarArgsFunction(a, b, c, *l, **d): return a, b, c, l, d l = [2] d = {"other": 7, "c": 3} print("Dual star args consuming function", posDoubleStarArgsFunction(1, *l, **d)) for value in sorted(dir()): main_value = getattr(sys.modules["__main__"], value) if inspect.isfunction(main_value): print( main_value, main_value.__code__.co_varnames[: main_value.__code__.co_argcount], inspect.getargs(main_value.__code__), ) # # TODO: Make this work as well, currently disabled, because of nested arguments not # being compatible yet. # print inspect.getargspec( main_value ) Nuitka-0.6.19.1/tests/basics/Printing_2.py0000600000372100037210000000260514166627112025265 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- coding: utf-8 -*- # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # All of these should be identical with correct software behavior. print "Output with newline." print "Output", "with", "newline." print "Output trailing spaces ", "with ", "newline." print "Output ", print "with ", print "newline." print "Output\twith tab" print "Output\t", print "with tab" # These ones gave errors with previous literal bugs: print "changed 2" print "foo%sbar%sfred%sbob?????" a = "partial print" # b doesn't exist try: print a, undefined_global except Exception, e: print "then occurred", repr(e) print "No newline at the end", x = 1 print """ New line is no soft space, is it """, x Nuitka-0.6.19.1/tests/basics/Referencing27.py0000600000372100037210000000403414166627112025650 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests for Python2 specific features. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. """ # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import executeReferenceChecked x = 17 # Python2.7 or higher syntax things are here. def simpleFunction1(): return {i: x for i in range(x)} def simpleFunction2(): try: return {y: i for i in range(x)} except NameError: pass def simpleFunction3(): return {i for i in range(x)} def simpleFunction4(): try: return {y for i in range(x)} except NameError: pass # These need stderr to be wrapped. tests_stderr = () # Disabled tests tests_skipped = {} result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/BuiltinSuper.py0000600000372100037210000000721014166627112025674 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys # Python2 will fallback to this variable, which Python3 will ignore. __class__ = "Using module level __class__ variable, would be wrong for Python3" class ClassWithUnderClassClosure: def g(self): def h(): print("Variable __class__ in ClassWithUnderClassClosure is", __class__) h() try: print( "ClassWithUnderClassClosure: Super in ClassWithUnderClassClosure is", super(), ) except Exception as e: print("ClassWithUnderClassClosure: Occurred during super call", repr(e)) print("Class with a method that has a local function accessing __class__:") ClassWithUnderClassClosure().g() class ClassWithoutUnderClassClosure: def g(self): __class__ = "Providing __class__ ourselves, then it must be used" print(__class__) try: print("ClassWithoutUnderClassClosure: Super", super()) except Exception as e: print("ClassWithoutUnderClassClosure: Occurred during super call", repr(e)) ClassWithoutUnderClassClosure().g() # For Python2 only. __class__ = "Global __class__" def deco(C): print("Decorating", repr(C)) class D(C): pass return D @deco class X: __class__ = "some string" def f1(self): print("f1", locals()) try: print("f1", __class__) except Exception as e: print("Accessing __class__ in f1 gave", repr(e)) def f2(self): print("f2", locals()) def f4(self): print("f4", self) self = X() print("f4", self) try: print("f4", super()) print("f4", super().__self__) except TypeError: import sys assert sys.version_info < (3,) f5 = lambda x: __class__ def f6(self_by_another_name): # @NoSelf try: print("f6", super()) except TypeError: import sys assert sys.version_info < (3,) def f7(self): try: yield super() except TypeError: import sys assert sys.version_info < (3,) print("Early pre-class calls begin") print("Set in class __class__", __class__) # f1(1) f2(2) print("Early pre-class calls end") del __class__ x = X() x.f1() x.f2() x.f4() print("f5", x.f5()) x.f6() print("f7", list(x.f7())) def makeSuperCall(arg1, arg2): print("Calling super with args", arg1, arg2, end=": ") try: super(arg1, arg2) except Exception as e: print("Exception", e) else: print("Ok.") # Due to inconsistent backporting to Python2.6 and Python2.7, 3.5 on various OSes, # this one gives varying results, ignore that if sys.version_info >= (3, 6): makeSuperCall(None, None) makeSuperCall(1, None) makeSuperCall(type, None) makeSuperCall(type, 1) Nuitka-0.6.19.1/tests/basics/Unicode.py0000600000372100037210000000211014166627112024627 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # print(u"gfcrk") print(repr(u"g\xfcrk")) print(r"""\x00""") print("\ttest\n") print( """ something with new lines""" ) print(u"favicon.ico (32\xd732)") # TODO: Python3 has a problem here, hard to find, disabled for now. if False: encoding = "utf-16-be" print("[\uDC80]".encode(encoding)) print("[\\udc80]") Nuitka-0.6.19.1/tests/basics/ParameterErrors.py0000600000372100037210000001333514166627112026371 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def functionNoParameters(): pass print("Call a function with no parameters with a plain argument:") try: functionNoParameters(1) except TypeError as e: print(repr(e)) print("Call a function with no parameters with a keyword argument:") try: functionNoParameters(z=1) except TypeError as e: print(repr(e)) def functionOneParameter(a): print(a) print("Call a function with one parameter with two plain arguments:") try: functionOneParameter(1, 1) except TypeError as e: print(repr(e)) print("Call a function with one parameter too many, and duplicate arguments:") try: functionOneParameter(6, a=4, *(1, 2, 3)) except TypeError as e: print(repr(e)) print("Call a function with two parameters with three plain arguments:") def functionTwoParameters(a, b): print(a, b) try: functionTwoParameters(1, 2, 3) except TypeError as e: print(repr(e)) print("Call a function with two parameters with one plain argument:") try: functionTwoParameters(1) except TypeError as e: print(repr(e)) print("Call a function with two parameters with three plain arguments:") try: functionTwoParameters(1, 2, 3) except TypeError as e: print(repr(e)) print("Call a function with two parameters with one keyword argument:") try: functionTwoParameters(a=1) except TypeError as e: print(repr(e)) print("Call a function with two parameters with three keyword arguments:") try: functionTwoParameters(a=1, b=2, c=3) except TypeError as e: print(repr(e)) class MethodContainer: def methodNoParameters(self): pass def methodOneParameter(self, a): print(a) def methodTwoParameters(self, a, b): print(a, b) obj = MethodContainer() print("Call a method with no parameters with a plain argument:") try: obj.methodNoParameters(1) except TypeError as e: print(repr(e)) print("Call a method with no parameters with a keyword argument:") try: obj.methodNoParameters(z=1) except TypeError as e: print(repr(e)) print("Call a method with one parameter with two plain arguments:") try: obj.methodOneParameter(1, 1) except TypeError as e: print(repr(e)) print("Call a method with two parameters with three plain arguments:") try: obj.methodTwoParameters(1, 2, 3) except TypeError as e: print(repr(e)) print("Call a method with two parameters with one plain argument:") try: obj.methodTwoParameters(1) except TypeError as e: print(repr(e)) print("Call a method with two parameters with one keyword argument:") try: obj.methodTwoParameters(a=1) except TypeError as e: print(repr(e)) print("Call a method with two parameters with three keyword arguments:") try: obj.methodTwoParameters(a=1, b=2, c=3) except TypeError as e: print(repr(e)) def functionPosBothStarArgs(a, b, c, *l, **d): print(a, b, c, l, d) l = [2] d = {"other": 7} print("Call a function with both star arguments and too little arguments:") try: functionPosBothStarArgs(1, *l, **d) except TypeError as e: print(repr(e)) print("Call a function with defaults with too little arguments:") def functionWithDefaults(a, b, c, d=3): print(a, b, c, d) try: functionWithDefaults(1) except TypeError as e: print(repr(e)) print("Call a function with defaults with too many arguments:") try: functionWithDefaults(1) except TypeError as e: print(repr(e)) print("Complex calls with both invalid star list and star arguments:") try: a = 1 b = 2.0 functionWithDefaults(1, c=3, *a, **b) except TypeError as e: # Workaround Python 3.9 shortcoming print(repr(e).replace("Value", "__main__.functionWithDefaults() argument")) try: a = 1 b = 2.0 functionWithDefaults(1, *a, **b) except TypeError as e: # Workaround Python 3.9 shortcoming print(repr(e).replace("Value", "__main__.functionWithDefaults() argument")) try: a = 1 b = 2.0 functionWithDefaults(c=1, *a, **b) except TypeError as e: print(repr(e)) try: a = 1 b = 2.0 functionWithDefaults(*a, **b) except TypeError as e: print(repr(e)) print("Complex call with both invalid star list argument:") try: a = 1 functionWithDefaults(*a) except TypeError as e: print(repr(e)) try: a = 1 MethodContainer(*a) except TypeError as e: print(repr(e)) try: a = 1 MethodContainer()(*a) except TypeError as e: print(repr(e)) try: a = 1 MethodContainer.methodTwoParameters(*a) except TypeError as e: print(repr(e)) try: a = 1 None(*a) except TypeError as e: print(repr(e)) try: a = 1 None(**a) except TypeError as e: print(repr(e)) print("Call object with name as both keyword and in star dict argument:") try: a = {"a": 3} None(a=2, **a) except TypeError as e: print(repr(e)) print("Call function with only defaulted value given as keyword argument:") def functionwithTwoArgsOneDefaulted(a, b=5): pass try: functionwithTwoArgsOneDefaulted(b=12) except TypeError as e: print(repr(e)) Nuitka-0.6.19.1/tests/basics/DefaultParameters.py0000600000372100037210000000435114166627112026662 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tests to cover default parameter behaviours. """ from __future__ import print_function # pylint: disable=dangerous-default-value,unused-argument module_level = 1 def defaultValueTest1(no_default, some_default_constant=1): return some_default_constant def defaultValueTest2(no_default, some_default_computed=module_level * 2): local_var = no_default return local_var, some_default_computed def defaultValueTest3(no_default, func_defaulted=defaultValueTest1(module_level)): return [func_defaulted for _i in range(8)] def defaultValueTest4(no_default, funced_defaulted=lambda x: x ** 2): c = 1 d = 1 return (i + c + d for i in range(8)) def defaultValueTest5(no_default, tuple_defaulted=(1, 2, 3)): return tuple_defaulted def defaultValueTest6(no_default, list_defaulted=[1, 2, 3]): list_defaulted.append(5) return list_defaulted print(defaultValueTest1("ignored")) # The change of the default variable doesn't influence the default # parameter of defaultValueTest2, that means it's also calculated # at the time the function is defined. module_level = 7 print(defaultValueTest2("also ignored")) print(defaultValueTest3("nono not again")) print(list(defaultValueTest4("unused"))) print(defaultValueTest5("unused")) print(defaultValueTest6("unused"), end="") print(defaultValueTest6("unused")) print(defaultValueTest6.__defaults__) defaultValueTest6.func_defaults = ([1, 2, 3],) print(defaultValueTest6.__defaults__) print(defaultValueTest6(1)) Nuitka-0.6.19.1/tests/basics/Referencing36.py0000600000372100037210000001174414166627112025656 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests for Python3.6 or higher. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. These are Python3.6 specific constructs, that will give a SyntaxError or not be relevant on older versions. """ import os import sys # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start import asyncio import types from nuitka.tools.testing.Common import ( async_iterate, executeReferenceChecked, run_async, ) class AwaitException(Exception): pass def run_until_complete(coro): exc = False while True: try: if exc: exc = False fut = coro.throw(AwaitException) else: fut = coro.send(None) except StopIteration as ex: return ex.args[0] if fut == ("throw",): exc = True def simpleFunction1(): async def gen1(): try: yield except: # pylint: disable=bare-except pass async def run(): g = gen1() await g.asend(None) await g.asend(None) try: run_async(run()) except StopAsyncIteration: pass def simpleFunction2(): async def async_gen(): try: yield 1 yield 1.1 1 / 0 # pylint: disable=pointless-statement finally: yield 2 yield 3 yield 100 async_iterate(async_gen()) @types.coroutine def awaitable(*, throw=False): if throw: yield ("throw",) else: yield ("result",) async def gen2(): await awaitable() a = yield 123 assert a is None await awaitable() yield 456 await awaitable() yield 789 def simpleFunction3(): def to_list(gen): async def iterate(): res = [] async for i in gen: res.append(i) return res return run_until_complete(iterate()) async def run2(): return to_list(gen2()) run_async(run2()) def simpleFunction4(): g = gen2() ai = g.__aiter__() an = ai.__anext__() an.__next__() try: ai.__anext__().__next__() except StopIteration as _ex: pass except RuntimeError: # Python 3.8 doesn't like this anymore assert sys.version_info >= (3, 8) try: ai.__anext__().__next__() except RuntimeError: # Python 3.8 doesn't like this anymore assert sys.version_info >= (3, 8) def simpleFunction5(): t = 2 class C: # pylint: disable=invalid-name exec("u=2") # pylint: disable=exec-used x: int = 2 y: float = 2.0 z = x + y + t * u # pylint: disable=undefined-variable rawdata = b"The quick brown fox jumps over the lazy dog.\r\n" # Be slow so we don't depend on other modules rawdata += bytes(range(256)) return C() # This refleaks big time, but the construct is rare enough to not bother # as this proves hard to find. def disabled_simpleFunction6(): loop = asyncio.new_event_loop() asyncio.set_event_loop(None) async def waiter(timeout): await asyncio.sleep(timeout) yield 1 async def wait(): async for _ in waiter(1): pass t1 = loop.create_task(wait()) t2 = loop.create_task(wait()) loop.run_until_complete(asyncio.sleep(0.01)) t1.cancel() t2.cancel() try: loop.run_until_complete(t1) except asyncio.CancelledError: pass try: loop.run_until_complete(t2) except asyncio.CancelledError: pass loop.run_until_complete(loop.shutdown_asyncgens()) loop.close() # These need stderr to be wrapped. tests_stderr = () # Disabled tests tests_skipped = {} result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/OverflowFunctions_2.py0000600000372100037210000000265414166627112027173 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def starImporterFunction(): from sys import * print "Version", version.split()[0].split(".")[:-1] starImporterFunction() def deepExec(): for_closure = 3 def deeper(): for_closure_as_well = 4 def execFunction(): code = "f=2" # Can fool it to nest exec code in None, None print "Locals now", locals() print "Closure one level up was taken", for_closure_as_well print "Closure two levels up was taken", for_closure print "Globals still work", starImporterFunction print "Added local from code", f execFunction() deeper() deepExec() Nuitka-0.6.19.1/tests/basics/Importing.py0000600000372100037210000000464114166627112025224 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def localImporter1(): import os return os def localImporter1a(): import os as my_os_name return my_os_name def localImporter2(): from os import path return path def localImporter2a(): from os import path as renamed return renamed print("Direct module import", localImporter1()) print("Direct module import using rename", localImporter1a()) print("From module import", localImporter2()) print("From module import using rename", localImporter2a()) from os import * # isort:skip print("Star import gave us", path) import os.path as myname # isort:skip print("As import gave", myname) def localImportFailure(): try: from os import path, lala, listdir except Exception as e: print("gives", type(e), repr(e)) try: print(listdir) except UnboundLocalError: print("and listdir was not imported", end=" ") print("but path was", path) print("From import that fails in the middle", end=" ") localImportFailure() def nonPackageImportFailure(): try: # Not allowed without being a package, should raise ValueError from . import whatever except Exception as e: print(type(e), repr(e)) print("Package import fails in non-package:", end=" ") nonPackageImportFailure() def importBuiltinTupleFailure(): try: value = ("something",) # Not allowed to not be constant string, optimization might be fooled # though. __import__(value) except Exception as e: print(type(e), repr(e)) print("The __import__ built-in optimization can handle tuples:", end=" ") importBuiltinTupleFailure() Nuitka-0.6.19.1/tests/basics/TrickAssignments32.py0000600000372100037210000005466714166627112026726 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def someFunctionThatReturnsDeletedValueViaAttributeLookup(): class C: def __getattr__(self, attr_name): nonlocal a del a c = C() a = 1 c.something return a try: someFunctionThatReturnsDeletedValueViaAttributeLookup() except UnboundLocalError: print("OK, object attribute look-up correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaAttributeSetting(): class C: def __setattr__(self, attr_name, value): nonlocal a del a c = C() a = 1 c.something = 1 return a try: someFunctionThatReturnsDeletedValueViaAttributeSetting() except UnboundLocalError: print("OK, object attribute setting correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaAttributeDel(): class C: def __delattr__(self, attr_name): nonlocal a del a return True c = C() a = 1 del c.something return a try: someFunctionThatReturnsDeletedValueViaAttributeDel() except UnboundLocalError: print("OK, object attribute del correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaItemLookup(): class C: def __getitem__(self, attr_name): nonlocal a del a c = C() a = 1 c[2] return a try: someFunctionThatReturnsDeletedValueViaItemLookup() except UnboundLocalError: print("OK, object subscript look-up correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaItemSetting(): class C: def __setitem__(self, attr_name, value): nonlocal a del a c = C() a = 1 c[2] = 3 return a try: someFunctionThatReturnsDeletedValueViaItemSetting() except UnboundLocalError: print("OK, object subscript setting correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaItemDel(): class C: def __delitem__(self, attr_name): nonlocal a del a c = C() a = 1 del c[2] return a try: someFunctionThatReturnsDeletedValueViaItemDel() except UnboundLocalError: print("OK, object subscript del correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaCall(): class C: def __call__(self): nonlocal a del a c = C() a = 1 c() return a try: someFunctionThatReturnsDeletedValueViaCall() except UnboundLocalError: print("OK, object call correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaAdd(): class C: def __add__(self, other): nonlocal a del a c = C() a = 1 c + 1 return a try: someFunctionThatReturnsDeletedValueViaAdd() except UnboundLocalError: print("OK, object add correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaSub(): class C: def __sub__(self, other): nonlocal a del a c = C() a = 1 c - 1 return a try: someFunctionThatReturnsDeletedValueViaSub() except UnboundLocalError: print("OK, object sub correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaMul(): class C: def __mul__(self, other): nonlocal a del a return 7 c = C() a = 1 c * 1 return a try: someFunctionThatReturnsDeletedValueViaMul() except UnboundLocalError: print("OK, object mul correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaRemainder(): class C: def __mod__(self, other): nonlocal a del a return 7 c = C() a = 1 c % 1 return a try: someFunctionThatReturnsDeletedValueViaRemainder() except UnboundLocalError: print("OK, object remainder correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaDivmod(): class C: def __divmod__(self, other): nonlocal a del a return 7 c = C() a = 1 divmod(c, 1) return a try: someFunctionThatReturnsDeletedValueViaDivmod() except UnboundLocalError: print("OK, object divmod correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaPower(): class C: def __pow__(self, other): nonlocal a del a return 7 c = C() a = 1 c ** 1 return a try: someFunctionThatReturnsDeletedValueViaPower() except UnboundLocalError: print("OK, object power correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaUnaryMinus(): class C: def __neg__(self): nonlocal a del a return 7 c = C() a = 1 -c return a try: someFunctionThatReturnsDeletedValueViaUnaryMinus() except UnboundLocalError: print("OK, object unary minus correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaUnaryPlus(): class C: def __pos__(self): nonlocal a del a return 7 c = C() a = 1 +c return a try: someFunctionThatReturnsDeletedValueViaUnaryPlus() except UnboundLocalError: print("OK, object unary plus correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaNot(): class C: def __bool__(self): nonlocal a del a return False c = C() a = 1 not c return a try: someFunctionThatReturnsDeletedValueViaNot() except UnboundLocalError: print("OK, object bool correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInvert(): class C: def __invert__(self): nonlocal a del a return False c = C() a = 1 ~c return a try: someFunctionThatReturnsDeletedValueViaInvert() except UnboundLocalError: print("OK, object invert correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaLshift(): class C: def __lshift__(self, other): nonlocal a del a return False c = C() a = 1 c << 1 return a try: someFunctionThatReturnsDeletedValueViaLshift() except UnboundLocalError: print("OK, object lshift correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaRshift(): class C: def __rshift__(self, other): nonlocal a del a return False c = C() a = 1 c >> 1 return a try: someFunctionThatReturnsDeletedValueViaRshift() except UnboundLocalError: print("OK, object rshift correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaBitwiseAnd(): class C: def __and__(self, other): nonlocal a del a return False c = C() a = 1 c & 1 return a try: someFunctionThatReturnsDeletedValueViaBitwiseAnd() except UnboundLocalError: print("OK, object bitwise and correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaBitwiseOr(): class C: def __or__(self, other): nonlocal a del a return False c = C() a = 1 c | 1 return a try: someFunctionThatReturnsDeletedValueViaBitwiseOr() except UnboundLocalError: print("OK, object bitwise or correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaBitwiseXor(): class C: def __xor__(self, other): nonlocal a del a return False c = C() a = 1 c ^ 1 return a try: someFunctionThatReturnsDeletedValueViaBitwiseXor() except UnboundLocalError: print("OK, object bitwise xor correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInt(): class C: def __int__(self): nonlocal a del a return False c = C() a = 1 int(c) return a try: someFunctionThatReturnsDeletedValueViaInt() except UnboundLocalError: print("OK, object int correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaFloat(): class C: def __float__(self): nonlocal a del a return 0.0 c = C() a = 1 float(c) return a try: someFunctionThatReturnsDeletedValueViaFloat() except UnboundLocalError: print("OK, object float correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaComplex(): class C: def __complex__(self): nonlocal a del a return 0j c = C() a = 1 complex(c) return a try: someFunctionThatReturnsDeletedValueViaComplex() except UnboundLocalError: print("OK, object complex correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceAdd(): class C: def __iadd__(self, other): nonlocal a del a c = C() a = 1 c += 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceAdd() except UnboundLocalError: print("OK, object inplace add correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceSub(): class C: def __isub__(self, other): nonlocal a del a c = C() a = 1 c -= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceSub() except UnboundLocalError: print("OK, object inplace sub correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceMul(): class C: def __imul__(self, other): nonlocal a del a c = C() a = 1 c *= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceMul() except UnboundLocalError: print("OK, object inplace mul correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceRemainder(): class C: def __imod__(self, other): nonlocal a del a c = C() a = 1 c %= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceRemainder() except UnboundLocalError: print("OK, object inplace remainder correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplacePower(): class C: def __ipow__(self, other): nonlocal a del a return 7 c = C() a = 1 c **= 1 return a try: someFunctionThatReturnsDeletedValueViaInplacePower() except UnboundLocalError: print("OK, object inplace power correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceAnd(): class C: def __iand__(self, other): nonlocal a del a return False c = C() a = 1 c &= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceAnd() except UnboundLocalError: print("OK, object inplace and correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceFloordiv(): class C: def __ifloordiv__(self, other): nonlocal a del a return 7 c = C() a = 1 c //= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceFloordiv() except UnboundLocalError: print("OK, object inplace floordiv correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceLshift(): class C: def __ilshift__(self, other): nonlocal a del a return False c = C() a = 1 c <<= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceLshift() except UnboundLocalError: print("OK, object inplace lshift correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceRshift(): class C: def __irshift__(self, other): nonlocal a del a return False c = C() a = 1 c >>= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceRshift() except UnboundLocalError: print("OK, object inplace rshift correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceOr(): class C: def __ior__(self, other): nonlocal a del a return False c = C() a = 1 c |= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceOr() except UnboundLocalError: print("OK, object inplace or correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceTrueDiv(): class C: def __itruediv__(self, other): nonlocal a del a return 7 c = C() a = 1 c /= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceTrueDiv() except UnboundLocalError: print("OK, object inplace truediv correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceXor(): class C: def __ixor__(self, other): nonlocal a del a return False c = C() a = 1 c ^= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceXor() except UnboundLocalError: print("OK, object inplace xor correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaIndex(): class C: def __index__(self): nonlocal a del a return 0 c = C() a = 1 [1][c] return a try: someFunctionThatReturnsDeletedValueViaIndex() except UnboundLocalError: print("OK, object index correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaLen(): class C: def __len__(self): nonlocal a del a return 0 c = C() a = 1 len(c) return a try: someFunctionThatReturnsDeletedValueViaLen() except UnboundLocalError: print("OK, object len correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaRepr(): class C: def __repr__(self): nonlocal a del a return "" c = C() a = 1 repr(c) return a try: someFunctionThatReturnsDeletedValueViaRepr() except UnboundLocalError: print("OK, object repr correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaStr(): class C: def __str__(self): nonlocal a del a return "" c = C() a = 1 str(c) return a try: someFunctionThatReturnsDeletedValueViaStr() except UnboundLocalError: print("OK, object str correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaCompare(): class C: def __lt__(self, other): nonlocal a del a return "" c = C() a = 1 c < None return a try: someFunctionThatReturnsDeletedValueViaCompare() except UnboundLocalError: print("OK, object compare correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaDel(): class C: def __del__(self): nonlocal a del a return "" c = C() a = 1 del c return a try: someFunctionThatReturnsDeletedValueViaDel() except UnboundLocalError: print("OK, object del correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaHash(): class C: def __hash__(self): nonlocal a del a return 42 c = C() a = 1 {}[c] = 1 return a try: someFunctionThatReturnsDeletedValueViaHash() except UnboundLocalError: print("OK, object hash correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaIter(): class C: def __iter__(self): nonlocal a del a return iter(range(2)) c = C() a = 1 x, y = c return a, x, y try: someFunctionThatReturnsDeletedValueViaIter() except UnboundLocalError: print("OK, object iter correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaBytes(): class C: def __bytes__(self): nonlocal a del a return bytes(range(2)) c = C() a = 1 bytes(c) return a, x, y try: someFunctionThatReturnsDeletedValueViaBytes() except UnboundLocalError: print("OK, object bytes correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaEq(): class C: def __eq__(self, other): nonlocal a del a return False c = C() a = 1 c == 1 return a try: someFunctionThatReturnsDeletedValueViaEq() except UnboundLocalError: print("OK, object eq correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaLe(): class C: def __le__(self, other): nonlocal a del a return False c = C() a = 1 c <= 1 return a try: someFunctionThatReturnsDeletedValueViaEq() except UnboundLocalError: print("OK, object le correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaGt(): class C: def __gt__(self, other): nonlocal a del a return False c = C() a = 1 c > 1 return a try: someFunctionThatReturnsDeletedValueViaEq() except UnboundLocalError: print("OK, object gt correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaGe(): class C: def __ge__(self, other): nonlocal a del a return False c = C() a = 1 c >= 1 return a try: someFunctionThatReturnsDeletedValueViaEq() except UnboundLocalError: print("OK, object ge correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaNe(): class C: def __ne__(self, other): nonlocal a del a return False c = C() a = 1 c != 1 return a try: someFunctionThatReturnsDeletedValueViaEq() except UnboundLocalError: print("OK, object ne correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaContains(): class C: def __contains__(self, item): nonlocal a del a return False c = C() a = 1 1 in c return a try: someFunctionThatReturnsDeletedValueViaContains() except UnboundLocalError: print("OK, object contains correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInit(): class C: def __init__(self): nonlocal a del a a = 1 c = C() return a try: someFunctionThatReturnsDeletedValueViaInit() except UnboundLocalError: print("OK, object init correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaNew(): class C: def __new__(self): nonlocal a del a a = 1 c = C() return a try: someFunctionThatReturnsDeletedValueViaNew() except UnboundLocalError: print("OK, object new correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaDir(): class C: def __dir__(self): nonlocal a del a return [] c = C() a = 1 dir(c) return a try: someFunctionThatReturnsDeletedValueViaDir() except UnboundLocalError: print("OK, object dir correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaReversed(): class C: def __reversed__(self): nonlocal a del a return None a = 1 c = C() reversed(c) return a try: someFunctionThatReturnsDeletedValueViaReversed() except UnboundLocalError: print("OK, object reversed correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaFormat(): class C: def __format__(self, string): nonlocal a del a return "formated string" c = C() a = 1 format(c, "some string") return a try: someFunctionThatReturnsDeletedValueViaFormat() except UnboundLocalError: print("OK, object format correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaAbs(): class C: def __abs__(self): nonlocal a del a return abs(10) a = 1 c = C() abs(c) return a try: someFunctionThatReturnsDeletedValueViaAbs() except UnboundLocalError: print("OK, object abs correctly deleted an item.") else: print("Ouch.!") # TODO: There must be way more than these. Nuitka-0.6.19.1/tests/basics/MainPrograms.py0000600000372100037210000000276614166627112025661 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function print("Module name is", __name__) class SomeClass: pass print("Class inside main module names its module as", repr(SomeClass.__module__)) if __name__ == "__main__": print("Executed as __main__:") import sys, os # The sys.argv[0] might contain ".exe", ".py" or no suffix at all. # Remove it, so the "diff" output is more acceptable. args = sys.argv[:] args[0] = ( os.path.basename(args[0]) .replace(".exe", ".py") .replace(".bin", ".py") .replace(".py", "") ) print("Arguments were (stripped argv[0] suffix):", repr(args)) # Output the flags, so we can test if we are compatible with these too. print("The sys.flags are:", sys.flags) Nuitka-0.6.19.1/tests/basics/YieldFrom33.py0000600000372100037210000000600014166627112025303 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def g(): for a in range(3): yield a return 7 def h(): yield 4 yield 5 def f(): print("Yielded from returner", (yield g())) print("Yielded from non-return value", (yield h())) print("Result", list(f())) print("Yielder with return value", list(g())) # This will raise when looking up any attribute. class Broken: def __iter__(self): return self def __next__(self): return 1 def __getattr__(self, attr): 1 / 0 def test_broken_getattr_handling(): def g(): yield from Broken() print("Next with send: ", end="") try: gi = g() next(gi) gi.send(1) except Exception as e: print("Caught", repr(e)) print("Next with throw: ", end="") try: gi = g() next(gi) gi.throw(AttributeError) except Exception as e: print("Caught", repr(e)) print("Next with close: ", end="") try: gi = g() next(gi) gi.close() print("All good") except Exception as e: print("Caught", repr(e)) test_broken_getattr_handling() def test_throw_catched_subgenerator_handling(): def g1(): try: print("Starting g1") yield "g1 ham" yield from g2() yield "g1 eggs" finally: print("Finishing g1") def g2(): try: print("Starting g2") yield "g2 spam" yield "g2 more spam" except LunchError: print("Caught LunchError in g2") yield "g2 lunch saved" yield "g2 yet more spam" class LunchError(Exception): pass g = g1() for i in range(2): x = next(g) print("Yielded %s" % (x,)) e = LunchError("tomato ejected") print("Throw returned", g.throw(e)) print("Sub thrown") for x in g: print("Yielded %s" % (x,)) test_throw_catched_subgenerator_handling() def give_cpython_generator(): # TODO: This relies on eval not being inlined, which will become untrue. return eval("(x for x in range(3))") def gen_compiled(): yield from give_cpython_generator() yield ... yield from range(7) print("Mixing uncompiled and compiled yield from:") print(list(gen_compiled())) Nuitka-0.6.19.1/tests/basics/Constants.py0000600000372100037210000001041414166627112025223 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Playing around with constants only. """ # pylint: disable=invalid-name,redefined-outer-name from __future__ import print_function try: long except NameError: long = int def displayDict(d): result = "{" for key, value in sorted(d.items()): result += "%s: %s" % (key, value) result += "}" print("A bunch of constants and their representation:") for value in (0, 3, -4, 17, "hey", (0,), 0.0, -0.0): print(value, ":", repr(value)) print("Comparing constants, optimizable:") print(1 == 0) print("Representation of long constants:") a = long(0) print(repr(long(0)), repr(a) == "0L") print("Identity of empty dictionary constants:") print({} is {}) a = ({}, []) a[0][1] = 2 a[1].append(3) print("Mutable list and dict inside an immutable tuple:") print(a) print("Empty list and dict are hopefully unchanged:") print(({}, [])) def argChanger(a): a[0][1] = 2 a[1].append(3) return a print("Mutable list and dict inside an immutable tuple as arguments:") print(argChanger(({}, []))) print("Empty list and dict are hopefully still unchanged:") print(({}, [])) print("Set constants:") print(set(["foo"])) def mutableConstantChanger(): a = ([1, 2], [3]) print("Start out with value:") print(a) a[1].append(5) print("Changed to value:") print(a) d = {"l": [], "m": []} print("Start out with value:") print(d) d["l"].append(7) print("Changed to value:") print(d) spec = dict(qual=[], storage=set(), type=[], function=set(), q=1) spec["type"].insert(0, 2) spec["storage"].add(3) print("Dictionary created from dict built-in.") print(sorted(spec)) mutableConstantChanger() print("Redo constant changes, to catch corruptions:") mutableConstantChanger() def defaultKeepsIdentity(arg="str_value"): print("Default constant values are still shared if immutable:", arg is "str_value") defaultKeepsIdentity() # Dictionary creation from call arguments. def dd(**d): return d def f(): def one(): print("one") def two(): print("two") a = dd(qual=one(), storage=two(), type=[], function=[]) print("f mutable", displayDict(a)) a = dd(qual=1, storage=2, type=3, function=4) print("f immutable", displayDict(a)) x = {"p": 7} a = dd(qual=[], storage=[], type=[], function=[], **x) print("f ext mutable", displayDict(a)) x = {"p": 8} a = dd(qual=1, storage=2, type=3, function=4, **x) print("f ext immutable", displayDict(a)) f() # Dictionary creation one after another x = {} x["function"] = [] x["type"] = [] x["storage"] = [] x["qual"] = [] print("Manual built dictionary:", x) x = {} x["function"] = 1 x["type"] = 2 x["storage"] = 3 x["qual"] = 4 print("Manual built dictionary:", x) # Constants in the code must be created differently. d = {"qual": [], "storage": [], "type2": [], "function": []} print("Mutable values dictionary constant:", displayDict(d)) d = {"qual": 1, "storage": 2, "type2": 3, "function": 4} print("Immutable values dictionary constant:", displayDict(d)) # Constants that might be difficult min_signed_int = int(-(2 ** (8 * 8 - 1) - 1) - 1) print("Small int:", min_signed_int, type(min_signed_int)) min_signed_int = int(-(2 ** (8 * 4 - 1) - 1) - 1) print("Small int", min_signed_int, type(min_signed_int)) # Constants that might be difficult min_signed_long = long(-(2 ** (8 * 8 - 1) - 1) - 1) print("Small long", min_signed_long, type(min_signed_long)) min_signed_long = long(-(2 ** (8 * 4 - 1) - 1) - 1) print("Small long", min_signed_long, type(min_signed_long)) Nuitka-0.6.19.1/tests/basics/Inspection_35.py0000600000372100037210000000274014166627112025674 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Tests uncompiled functions and compiled functions responses to inspect and isistance. """ import inspect import types # nuitka-project: --python-flag=no_warnings async def compiledCoroutine(): async with _x: pass print(type(compiledCoroutine())) assert inspect.isfunction(compiledCoroutine) is True assert inspect.isgeneratorfunction(compiledCoroutine) is False assert inspect.iscoroutinefunction(compiledCoroutine) is True assert isinstance(compiledCoroutine(), types.GeneratorType) is False assert isinstance(compiledCoroutine(), types.CoroutineType) is True assert type(compiledCoroutine()) == types.CoroutineType, type(compiledCoroutine()) assert isinstance(compiledCoroutine, types.CoroutineType) is False Nuitka-0.6.19.1/tests/basics/ClassMinimal.py0000600000372100037210000000154214166627112025625 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Very minimal class example, to be used for debugging. a = 1 class B: b = a print(B.b) Nuitka-0.6.19.1/tests/basics/ModuleAttributes.py0000600000372100037210000000345614166627112026553 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Some module documentation. With newline and stuff.""" from __future__ import print_function import os import sys print("doc:", __doc__) print("filename:", os.path.basename(__file__)) print("builtins:", __builtins__) print("debug", __debug__) print("debug in builtins", __builtins__.__debug__) print("__initializing__", end=" ") try: print(__initializing__) except NameError: print("not found") def checkFromFunction(): frame = sys._getframe(1) # pylint: disable=protected-access def displayDict(d): if "__loader__" in d: d = dict(d) d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d = dict(d) d["__file__"] = "<__file__ removed>" if "__compiled__" in d: d = dict(d) del d["__compiled__"] import pprint return pprint.pformat(d) print("Globals", displayDict(frame.f_globals)) print("Locals", displayDict(frame.f_locals)) print("Is identical", frame.f_locals is frame.f_globals) checkFromFunction() Nuitka-0.6.19.1/tests/basics/TryExceptContinue.py0000600000372100037210000000424414166627112026707 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def tryWhileExceptContinueTest(): print("Check if continue is executed in a except handler using for loop:") global undefined x = 0 while x < 10: x += 1 try: if x % 2 == 1: undefined except: print(x, end=" ") continue print("-", end=" ") print() def tryForExceptContinueTest(): print("Check if continue is executed in a except handler using for loop:") for x in range(10): try: if x % 2 == 1: undefined except: print(x, end=" ") continue print("-", end=" ") print() def tryWhileExceptBreakTest(): print("Check if break is executed in a except handler using while loop:") x = 0 while x < 10: x += 1 try: if x == 5: undefined except: print(x, end=" ") break print("-", end=" ") print() def tryForExceptBreakTest(): print("Check if break is executed in a except handler using for loop:") for x in range(10): try: if x == 5: undefined except: print(x, end=" ") break print("-", end=" ") print() tryWhileExceptContinueTest() tryWhileExceptBreakTest() tryForExceptContinueTest() tryForExceptBreakTest() Nuitka-0.6.19.1/tests/basics/InplaceOperations.py0000600000372100037210000000242014166627112026664 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function x = 1 x += 2 print("Plain in-place:", x) z = [1, 2, 3] z[1] += 5 print("List in-place:", z[1]) h = {"a": 3} h["a"] += 2 print("Dictionary in-place:", h["a"]) class B: a = 1 B.a += 2 print("Class attribute in-place:", B.a) h = [1, 2, 3, 4] h[1:2] += (2, 3) print("List 'sclice' in-place [x:y]", h) h[:1] += (9, 9) print("List 'sclice' in-place [:y]", h) h[2:] += (6, 6) print("List 'sclice' in-place [y:]", h) h[:] += (5, 5, 5) print("List 'sclice' in-place [:]", h) Nuitka-0.6.19.1/tests/basics/Varargs.py0000600000372100037210000000405714166627112024662 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- coding: utf-8 -*- # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def plain_list_dict_args_function(plain, *arg_list, **arg_dict): print("plain", plain, "arg_list", arg_list, "arg_dict", arg_dict) def plain_list_args_function(plain, *arg_list): print(plain, arg_list) def plain_dict_args_function(plain, **arg_dict): print(plain, arg_dict) print("Function with plain arg and varargs dict:") plain_dict_args_function(1, a=2, b=3, c=4) plain_dict_args_function(1) print("Function with plain arg and varargs list:") plain_list_args_function(1, 2, 3, 4) plain_list_args_function(1) print("Function with plain arg, varargs list and varargs dict:") plain_list_dict_args_function(1, 2, z=3) plain_list_dict_args_function(1, 2, 3) plain_list_dict_args_function(1, a=2, b=3, c=4) def list_dict_args_function(*arg_list, **arg_dict): print(arg_list, arg_dict) def list_args_function(*arg_list): print(arg_list) def dict_args_function(**arg_dict): print(arg_dict) print("Function with plain arg and varargs dict:") dict_args_function(a=2, b=3, c=4) dict_args_function() print("Function with plain arg and varargs list:") list_args_function(2, 3, 4) list_args_function() print("Function with plain arg, varargs list and varargs dict:") list_dict_args_function(2, z=3) list_dict_args_function(2, 3) list_dict_args_function(a=2, b=3, c=4) Nuitka-0.6.19.1/tests/basics/TrickAssignments35.py0000600000372100037210000000300514166627112026705 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def someFunctionThatReturnsDeletedValueViaMaxtrixMult(): class C: def __matmul__(self, other): nonlocal a del a c = C() a = 1 c @ 1 return a try: someFunctionThatReturnsDeletedValueViaMaxtrixMult() except UnboundLocalError: print("OK, object matrix mult correctly deleted an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaInplaceMaxtrixMult(): class C: def __imatmul__(self, other): nonlocal a del a c = C() a = 1 c @= 1 return a try: someFunctionThatReturnsDeletedValueViaInplaceMaxtrixMult() except UnboundLocalError: print("OK, object inplace matrix mult correctly deleted an item.") else: print("Ouch.!") Nuitka-0.6.19.1/tests/basics/Referencing35.py0000600000372100037210000001145214166627112025651 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests for features of Python3.5 or higher. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. These are Python3.5 specific constructs, that will give a SyntaxError or not be relevant on older versions. """ # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start # Tests do all bad things: # pylint: disable=not-an-iterable import asyncio import types from nuitka.PythonVersions import python_version from nuitka.tools.testing.Common import executeReferenceChecked, run_async # Tests do bad stuff, pylint: disable=redefined-outer-name def raisy(): raise TypeError def simpleFunction1(): async def someCoroutine(): return run_async(someCoroutine()) #################################### def simpleFunction2(): async def someCoroutine(): return 7 run_async(someCoroutine()) #################################### class AsyncIteratorWrapper: def __init__(self, obj): self._it = iter(obj) def __aiter__(self): return self async def __anext__(self): try: value = next(self._it) except StopIteration: raise StopAsyncIteration return value def simpleFunction3(): async def f(): result = [] # Python 3.5 before 3.2 won't allow this. try: async for letter in AsyncIteratorWrapper("abcdefg"): result.append(letter) except TypeError: assert sys.version_info < (3, 5, 2) return result run_async(f()) #################################### def simpleFunction4(): async def someCoroutine(): raise StopIteration try: run_async(someCoroutine()) except RuntimeError: pass #################################### class ClassWithAsyncMethod: async def async_method(self): return self def simpleFunction5(): run_async(ClassWithAsyncMethod().async_method()) #################################### class BadAsyncIter: def __init__(self): self.weight = 1 async def __aiter__(self): return self def __anext__(self): return () def simpleFunction7(): async def someCoroutine(): async for _i in BadAsyncIter(): print("never going to happen") try: run_async(someCoroutine()) except TypeError: pass def simpleFunction8(): async def someCoroutine(): return ("some", "thing") @types.coroutine def someDecoratorCoroutine(): yield from someCoroutine() run_async(someDecoratorCoroutine()) def simpleFunction9(): a = {"a": 1, "b": 2} b = {"c": 3, **a} return b async def rmtree(path): return await asyncio.get_event_loop().run_in_executor(None, sync_rmtree, path) def sync_rmtree(path): raise FileNotFoundError async def execute(): try: await rmtree("/tmp/test1234.txt") except FileNotFoundError: pass return 10 ** 10 async def run(): await execute() def simpleFunction10(): asyncio.get_event_loop().run_until_complete(run()) def nosimpleFunction11(): async def someCoroutine(): return 10 coro = someCoroutine() def someGenerator(): yield from coro try: list(someGenerator()) except TypeError: pass coro.close() # These need stderr to be wrapped. tests_stderr = () # Disabled tests tests_skipped = {} if python_version < 0x380: tests_skipped[10] = "Incompatible refcount bugs of asyncio with python prior 3.8" result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/Functions_2.py0000600000372100037210000000510514166627112025441 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Various kinds of functions definitions with Python2 only features. Esp. nested arguments are no longer allowed in Python3 and covered here to make sure they are not forgotten. """ from __future__ import print_function # pylint: disable=redefined-outer-name def local_function(a, z=9): b = ` a * a + 1 ` c = (a, b, a ** 32, a + a) d = long("0") e = int("77") d = long(b) e = long(1 + 1) return a, b, c, d, e, z print( "Call function with many variables calculated and returned", local_function(1, z=5) ) print("Function with nested args:") def nested_args_function((a, b), c): return a, b, c print(nested_args_function((1, 2), 3)) try: nested_args_function((1, 2, 3), 3) except ValueError, e: print("Calling nested with too long tuple gave:", e) try: nested_args_function((1,), 3) except ValueError, e: print("Calling nested with too short tuple gave:", e) def deeply_nested_function(((a,), b, c, (d, (e, f)))): return a, b, c, d, e, f print("Deeply nested function", deeply_nested_function(((1,), 2, 3, (4, (5, 6))))) print("Function with nested args that have defaults:") def default_giver(): class SomeClass: # pylint: disable=old-style-class def __iter__(self): print("Giving iter") return iter(range(2)) return SomeClass() def nested_args_function_with_defaults((a, b)=default_giver(), c=5): return a, b, c print("Calling it.") print(nested_args_function_with_defaults()) def comp_args1((a, b)): return a, b def comp_args2((a, b)=(3, 4)): return a, b def comp_args3(a, (b, c)): return a, b, c def comp_args4(a=2, (b, c)=(3, 4)): return a, b, c print( "Complex args functions", comp_args1((2, 1)), comp_args2(), comp_args2((7, 9)), comp_args3(7, (8, 9)), comp_args4(), ) Nuitka-0.6.19.1/tests/basics/TryContinueFinally.py0000600000372100037210000000404614166627112027055 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def tryWhileContinueFinallyTest(): print("Check if finally is executed in a continue using for loop:") x = 0 while x < 10: x += 1 try: if x % 2 == 1: continue finally: print(x, end=" ") print("-", end=" ") print() def tryForContinueFinallyTest(): print("Check if finally is executed in a continue using for loop:") for x in range(10): try: if x % 2 == 1: continue finally: print(x, end=" ") print("-", end=" ") print() def tryWhileBreakFinallyTest(): print("Check if finally is executed in a break using while loop:") x = 0 while x < 10: x += 1 try: if x == 5: break finally: print(x, end=" ") print("-", end=" ") print() def tryForBreakFinallyTest(): print("Check if finally is executed in a break using for loop:") for x in range(10): try: if x == 5: break finally: print(x, end=" ") print("-", end=" ") print() tryWhileContinueFinallyTest() tryWhileBreakFinallyTest() tryForContinueFinallyTest() tryForBreakFinallyTest() Nuitka-0.6.19.1/tests/basics/ThreadedGenerators.py0000600000372100037210000000220714166627112027022 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # From Issue#146, this has crashed in the past. import threading def some_generator(): yield 1 def run(): for i in range(10000): for j in some_generator(): pass def main(): workers = [threading.Thread(target=run) for i in range(5)] for t in workers: t.start() for t in workers: t.join() if __name__ == "__main__": main() Nuitka-0.6.19.1/tests/basics/Lamdas.py0000600000372100037210000000320714166627112024452 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def lamdaContainer(x): f = lambda c: c g = lambda c: c if x else c * c # h = lambda c: 'a' <= c <= 'z' y = f(x) z = g(4) print("Lambda with conditional expression gives", z) if "a" <= x <= y <= "z": print("Four") if "a" <= x <= "z": print("Yes") if "a" <= x > "z": print("Yes1") if "a" <= ("1" if x else "2") > "z": print("Yes2") if "a" <= ("1" if x else "2") > "z" > undefined_global: print("Yes3") z = lambda huhu=y: huhu print("Lambda defaulted gives", z()) lamdaContainer("b") def lambdaGenerator(): x = lambda: (yield 3) gen = x() print("Lambda generator gives", next(gen)) lambdaGenerator() def lambdaDirectCall(): args = range(7) x = (lambda *args: args)(*args) print("Lambda direct call gave", x) lambdaDirectCall() Nuitka-0.6.19.1/tests/basics/Unpacking35.py0000600000372100037210000000352514166627112025343 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def tupleUnpacking(): return (*a, b, *c) def listUnpacking(): return [*a, b, *c] def setUnpacking(): return {*a, b, *c} def dictUnpacking(): return {"a": 1, **d} a = range(3) b = 5 c = range(8, 10) d = {"a": 2} print("Tuple unpacked", tupleUnpacking()) print("List unpacked", listUnpacking()) print("Set unpacked", setUnpacking()) print("Dict unpacked", dictUnpacking()) non_iterable = 2.0 def tupleUnpackingError(): try: return (*a, *non_iterable, *c) except Exception as e: return e def listUnpackingError(): try: return [*a, *non_iterable, *c] except Exception as e: return e def setUnpackingError(): try: return {*a, *non_iterable, *c} except Exception as e: return e def dictUnpackingError(): try: return {"a": 1, **non_iterable} except Exception as e: return e print("Tuple unpacked error:", tupleUnpackingError()) print("List unpacked error:", listUnpackingError()) print("Set unpacked error:", setUnpackingError()) print("Dict unpacked error:", dictUnpackingError()) Nuitka-0.6.19.1/tests/basics/BuiltinOverload.py0000600000372100037210000000212014166627112026344 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function try: from __builtin__ import len as _len except ImportError: from builtins import len as _len # This kind of built-in overload will have to work. def len(x): print("Private built-in called with argument", repr(x)) return _len(x) print("Calling built-in len", len(range(9))) Nuitka-0.6.19.1/tests/basics/DoubleDeletions.py0000600000372100037210000000210114166627112026322 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function a = 3 del a try: del a except NameError as e: print("Raised expected exception:", repr(e)) def someFunction(b, c): b = 1 del b try: del b except UnboundLocalError as e: print("Raised expected exception:", repr(e)) someFunction(3, 4) Nuitka-0.6.19.1/tests/basics/Looping.py0000600000372100037210000000640114166627112024657 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Looping in various forms. """ from __future__ import print_function # pylint: disable=superfluous-parens,useless-else-on-loop,using-constant-test def cond(): return False def loopingFunction(a=1 * 2): c = [] f = [c, a] for a in range(6 or 8): for b in range(8): if a == b: c.append((a, b, True)) elif a < b: c.append((b, a, False)) else: c.append((a, b, False)) if a != b: z = 1 else: z = 0 if z == 0: continue if z == 1 and b == 6: break if a == b: z = 0 print(c) print(f) f = 1 while f < (10 or 8): m = 1 f += 1 print("m=", m) x = [u for u in range(8)] print(x) x = [(u, v) for (u, v) in zip(range(8), reversed(range(8)))] print(x) x = [(u if u % 2 == 0 else 0) for u in range(10)] print(x) x = [(u if u % 2 == 0 else 0) for u in (a if cond() else range(9))] print(x) y = [[3 + (l if l else -1) for l in [m, m + 1]] for m in [f for f in range(2)]] print("f=", f) print("y=", y) if x: l = "YES" else: l = "NO" if x: l = "yes" else: if True: l = "no" print("Triple and chain") if m and l and f: print("OK") print("Triple or chain") if m or l or f: print("Okey") print("Nested if not chain") if not m: if not l: print("ok") print("Braced if not chain with 'or'") if not (m or l): print("oki") print("Braced if not chain with 'and'") if not (m and l): print("oki") d = 1 print("Nested if chain with outer else") if a: if b or c: if d: print("inside nest") else: print("outer else") print(x) while False: pass else: print("Executed else branch for False condition while loop") while True: break else: print("Executed else branch for True condition while loop") for x in range(7): pass else: print("Executed else branch for no break for loop") for x in range(7): break else: print("Executed else branch despite break in for loop") x = iter(range(5)) while next(x): pass else: print("Executed else branch of while loop without break") loopingFunction() Nuitka-0.6.19.1/tests/basics/Future32.py0000600000372100037210000000157214166627112024673 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import barry_as_FLUFL print(eval("1 <> 2")) print(eval('"a"<>"b"')) print(eval("range(7) <> range(7)")) Nuitka-0.6.19.1/tests/basics/ExceptionRaising.py0000600000372100037210000003406714166627112026534 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys print("Raising an exception type in a function:") def raiseExceptionClass(): raise ValueError try: raiseExceptionClass() except Exception as e: print("Caught exception type", e, repr(e), type(e)) print("Inside handler, sys.exc_info is this", sys.exc_info()) print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Raising an exception instance in a function:") def raiseExceptionInstance(): raise ValueError("hallo") try: raiseExceptionInstance() except Exception as f: print("Caught exception instance", f, repr(f), type(f)) print("Inside handler, sys.exc_info is this", sys.exc_info()) print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Raising an exception, then catch it to re-raise it:") def raiseExceptionAndReraise(arg): try: return arg / arg except: raise try: raiseExceptionAndReraise(0) except: print("Catched reraised", sys.exc_info()) print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Access an undefined global variable in a function:") def raiseNonGlobalError(): return undefined_value try: raiseNonGlobalError() except: print("NameError caught", sys.exc_info()) print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Raise a new style class as an exception, should be rejected:") def raiseIllegalError(): class X(object): pass raise X() try: raiseIllegalError() except TypeError as E: print("New style class exception correctly rejected:", E) except: print(sys.exc_info()) assert False, "Error, new style class exception was not rejected" print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Raise an old-style class, version dependent outcome:") class ClassicClassException: pass def raiseCustomError(): raise ClassicClassException() try: try: raiseCustomError() except ClassicClassException: print("Caught classic class exception") except: print("Default catch", sys.exc_info()) assert False, "Error, old style class exception was not caught" except TypeError as e: print("Python3 hates to even try and catch classic classes", e) else: print("Classic exception catching was considered fine.") print("After catching, sys.exc_info is this", sys.exc_info()) print("*" * 20) print("Check lazy exception creation:") def checkExceptionConversion(): try: raise Exception("some string") except Exception as err: print("Catched raised object", err, type(err)) try: raise Exception, "some string" except Exception as err: print("Catched raised type, value pair", err, type(err)) checkExceptionConversion() print("*" * 20) print("Check exc_info scope:") def checkExcInfoScope(): try: raise ValueError except: assert sys.exc_info()[0] is not None assert sys.exc_info()[1] is not None assert sys.exc_info()[2] is not None if sys.version_info[0] < 3: print("Exc_info remains visible after exception handler for Python2") assert sys.exc_info()[0] is not None assert sys.exc_info()[1] is not None assert sys.exc_info()[2] is not None else: print("Exc_info is clear after exception handler for Python3") assert sys.exc_info()[0] is None assert sys.exc_info()[1] is None assert sys.exc_info()[2] is None def subFunction(): print("Entering with exception info", sys.exc_info()) assert sys.exc_info()[0] is not None assert sys.exc_info()[1] is not None assert sys.exc_info()[2] is not None try: print("Trying") except: pass print( "After trying something and didn't have an exception, info is", sys.exc_info(), ) print("Call a function inside the exception handler and check there too.") try: raise KeyError except: assert sys.exc_info()[0] is not None assert sys.exc_info()[1] is not None assert sys.exc_info()[2] is not None subFunction() print("Call it twice and see.") try: raise "me" except: assert sys.exc_info()[0] is not None assert sys.exc_info()[1] is not None assert sys.exc_info()[2] is not None subFunction() subFunction() if sys.version_info[0] < 3: sys.exc_clear() checkExcInfoScope() print("*" * 20) # Check that the sys.exc_info is cleared again, after being set inside the # function checkExcInfoScope, it should now be clear again. assert sys.exc_info()[0] is None, sys.exc_info()[0] assert sys.exc_info()[1] is None assert sys.exc_info()[2] is None print("Check catching subclasses") def checkDerivedCatch(): class A(BaseException): pass class B(A): def __init__(self): pass a = A() b = B() try: raise A, b except B, v: print("Caught B", v) except A, v: print("Didn't catch as B, but as A, Python3 does that", v) else: print("Not caught A class, not allowed to happen.") try: raise B, a except TypeError, e: print("TypeError with pair form for class not taking args:", e) checkDerivedCatch() print("*" * 20) def checkNonCatch1(): print("Testing if the else branch is executed in the optimizable case:") try: 0 except TypeError: print("Should not catch") else: print("Executed else branch correctly") checkNonCatch1() print("*" * 20) def checkNonCatch2(): try: print("Testing if the else branch is executed in the non-optimizable case:") except TypeError: print("Should not catch") else: print("Executed else branch correctly") checkNonCatch2() print("*" * 20) print("Checking raise that with exception arguments that raise error themselves.") def checkRaisingRaise(): def geterror(): return 1 / 0 try: geterror() except Exception as e: print("Had exception", e) try: raise TypeError, geterror() except Exception as e: print("Had exception", e) try: raise TypeError, 7, geterror() except Exception as e: print("Had exception", e) checkRaisingRaise() print("*" * 20) print("Checking a re-raise that isn't one:") def checkMisRaise(): raise try: checkMisRaise() except Exception as e: print("Without existing exception, re-raise gives:", e) print("*" * 20) print("Raising an exception in an exception handler gives:") def nestedExceptions(a, b): try: a / b except ZeroDivisionError: a / b try: nestedExceptions(1, 0) except Exception as e: print("Nested exception gives", e) print("*" * 20) print("Checking unpacking from an exception as a sequence:") def unpackingCatcher(): try: raise ValueError(1, 2) except ValueError as (a, b): print("Unpacking caught exception and unpacked", a, b) unpackingCatcher() print("Afterwards, exception info is", sys.exc_info()) print("*" * 20) print("Testing exception that escapes __del__ and therefore cannot be raised") def devide(a, b): return a / b def unraisableExceptionInDel(): class C: def __del__(self): c = devide(1, 0) print(c) def f(): C() f() unraisableExceptionInDel() print("*" * 20) print("Testing exception changes between generator switches:") def yieldExceptionInteraction(): def yield_raise(): print("Yield finds at generator entry", sys.exc_info()[0]) try: raise KeyError("caught") except KeyError: yield sys.exc_info()[0] yield sys.exc_info()[0] yield sys.exc_info()[0] g = yield_raise() print("Initial yield from catch in generator", next(g)) print("Checking from outside of generator", sys.exc_info()[0]) print("Second yield from the catch reentered", next(g)) print("Checking from outside of generator", sys.exc_info()[0]) print("After leaving the catch generator yielded", next(g)) yieldExceptionInteraction() print("*" * 20) print( "Testing exception change between generator switches while handling an own exception" ) def yieldExceptionInteraction2(): def yield_raise(): print("Yield finds at generator entry", sys.exc_info()[0]) try: raise ValueError("caught") except ValueError: yield sys.exc_info()[0] yield sys.exc_info()[0] yield sys.exc_info()[0] try: undefined_global except Exception: print("Checking from outside of generator with", sys.exc_info()[0]) g = yield_raise() v = next(g) print("Initial yield from catch in generator:", v) print("Checking from outside the generator:", sys.exc_info()[0]) print("Second yield from the catch reentered:", next(g)) print("Checking from outside the generation again:", sys.exc_info()[0]) print("After leaving the catch generator yielded:", next(g)) print("After exiting the trying branch:", sys.exc_info()[0]) yieldExceptionInteraction2() print("After function exit, no exception", sys.exc_info()) print("*" * 20) print("Check what happens if a function attempts to clear the exception in a handler") def clearingException(): def clearit(): try: if sys.version_info[0] < 3: sys.exc_clear() except KeyError: pass try: raise KeyError except: print("Before clearing, it's", sys.exc_info()) clearit() print("After clearing, it's", sys.exc_info()) clearingException() print("*" * 20) print("Check that multiple exceptions can be caught in a handler through a variable:") def multiCatchViaTupleVariable(): some_exceptions = (KeyError, ValueError) try: raise KeyError except some_exceptions: print("Yes, indeed.") multiCatchViaTupleVariable() def raiseValueWithValue(): try: raise ValueError(1, 2, 3), (ValueError(1, 2, 3)) except Exception as e: print("Gives", e) print("Check exception given when value is raised with value", raiseValueWithValue()) # Make sure the "repr" of exceptions is fine a = IOError print("IOError is represented correctly:", repr(a)) def raising(): raise ValueError def not_raising(): pass def raiseWithFinallyNotCorruptingLineNumber(): try: try: raising() finally: not_raising() except ValueError: print("Traceback is in tried block line", sys.exc_info()[2].tb_lineno) raiseWithFinallyNotCorruptingLineNumber() def wideCatchMustPublishException(): print("At entry, no exception", sys.exc_info()) try: undefined_global except: print("Inside handler:", sys.exc_info()) pass print("Outside handler:", sys.exc_info()) print("Check that a unqualified catch properly preserves exception") wideCatchMustPublishException() print("Check if a nested exception handler does overwrite re-raised") def checkReraiseAfterNestedTryExcept(): def reraise(): try: raise TypeError("outer") except Exception: try: raise KeyError("nested") except KeyError: print("Current exception inside nested handler", sys.exc_info()) pass print("Current exception after nested handler exited", sys.exc_info()) # Which one does this pick raise try: reraise() except Exception as e: print("Catched", repr(e)) checkReraiseAfterNestedTryExcept() def checkReraiseByFunction(): def reraise(): raise try: try: raise TypeError("outer") except Exception: reraise() except Exception as e: import traceback print("Exception traceback of re-raise:") print("-" * 40) traceback.print_exc() print("-" * 40) print("OK.") # TODO: Enable this, once the actual traceback of a function # re-raise isn't wrong (contains itself) anymore. if False: checkReraiseByFunction() def checkNoRaiseExceptionDictBuilding(arg): a = {(): arg} b = {None: arg} c = {Ellipsis: arg} d = {1.0j: arg} e = {1.0: arg} f = {long(0): arg} g = {0: arg} h = {type: arg} return a, b, c, d, e, f, g, h checkNoRaiseExceptionDictBuilding(1) def checkRaiseExceptionDictBuildingRange(arg): try: i = {range(10): arg} except Exception as e: print("Raised", repr(e)) else: print("No exception, OK for Python2") return i print("Check if range as dict key raises:") checkRaiseExceptionDictBuildingRange(2) def checkRaiseExceptionDictBuildingTuple(arg): try: i = {(2, []): arg} except Exception as e: print("Raised", repr(e)) else: return i print("Check if mutable tuple as dict key raises:") checkRaiseExceptionDictBuildingTuple(3) def checkRaiseExceptionDictBuildingList(arg): try: i = {[2, ()]: arg} except Exception as e: print("Raised", repr(e)) else: return i print("Check if list as dict key raises:") checkRaiseExceptionDictBuildingList(4) Nuitka-0.6.19.1/tests/basics/Inspection_36.py0000600000372100037210000000312214166627112025670 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Tests uncompiled functions and compiled functions responses to inspect and isistance. """ import inspect import types # nuitka-project: --python-flag=no_warnings async def compiledAsyncgen(): yield 1 print(type(compiledAsyncgen())) assert inspect.isfunction(compiledAsyncgen) is True assert inspect.isgeneratorfunction(compiledAsyncgen) is False assert inspect.iscoroutinefunction(compiledAsyncgen) is False assert inspect.isasyncgenfunction(compiledAsyncgen) is True assert isinstance(compiledAsyncgen(), types.GeneratorType) is False assert isinstance(compiledAsyncgen(), types.CoroutineType) is False assert isinstance(compiledAsyncgen(), types.AsyncGeneratorType) is True assert type(compiledAsyncgen()) == types.AsyncGeneratorType, type(compiledAsyncgen()) assert isinstance(compiledAsyncgen, types.AsyncGeneratorType) is False Nuitka-0.6.19.1/tests/basics/Classes34.py0000600000372100037210000000242214166627112025013 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from enum import Enum print("Enum class with duplicate enumeration values:") try: class Color(Enum): red = 1 green = 2 blue = 3 red = 4 print("not allowed to get here") except Exception as e: print("Occurred", e) print("Class variable that conflicts with closure variable:") def testClassNamespaceOverridesClosure(): # See #17853. x = 42 class X: locals()["x"] = 43 y = x print("should be 43:", X.y) testClassNamespaceOverridesClosure() Nuitka-0.6.19.1/tests/basics/Asserts.py0000600000372100037210000000322214166627112024672 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function def testAssert1(): assert False return 1 def testAssert2(): assert True return 1 def testAssert3(): assert False, "argument" return 1 try: print("Function that will assert.") testAssert1() print("No exception.") except Exception as e: print("Raised", type(e), e) try: print("Function that will not assert.") testAssert2() print("No exception.") except Exception as e: print("Raised", type(e), e) try: print("Function that will assert with argument.") testAssert3() print("No exception.") except Exception as e: print("Raised", type(e), e) try: print("Assertion with tuple argument.", end="") assert False, (3,) except AssertionError as e: print(str(e)) try: print("Assertion with plain argument.", end="") assert False, 3 except AssertionError as e: print(str(e)) Nuitka-0.6.19.1/tests/basics/GeneratorExpressions_37.py0000600000372100037210000000202114166627112027744 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Test case with generator expression form only allow until Python 3.7 """ def strangeLambdaGeneratorExpression(): x = ((yield) for i in (1, 2) if (yield)) print("Strange lambda generator expression:") print(list(x)) strangeLambdaGeneratorExpression() Nuitka-0.6.19.1/tests/basics/ExtremeClosure.py0000600000372100037210000000261314166627112026217 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ These tests contain all forms of closure absuse. """ from __future__ import print_function a = 1 b = 1 def someFunction(): a = a # pylint: disable=redefined-outer-name,unused-variable class SomeClass: b = b SomeClass() try: someFunction() except UnboundLocalError as e: print("Expected unbound local error occurred:", repr(e)) try: class AnotherClass: b = undefined_global except NameError as e: print("Expected name error occurred:", repr(e)) try: class YetAnotherClass: b = 1 del b print(b) except NameError as e: print("Expected name error occurred:", repr(e)) Nuitka-0.6.19.1/tests/basics/Empty.py0000600000372100037210000000140114166627112024341 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Nuitka-0.6.19.1/tests/basics/WithStatements.py0000600000372100037210000001141714166627112026236 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import sys x = 0 # This is used to trace the exact interaction with the context manager to # uncover and decide ordering and correctness of calls. class MyContextManager(object): def __getattribute__(self, attribute_name): print("Asking context manager attribute", attribute_name) return object.__getattribute__(self, attribute_name) def __enter__(self): global x x += 1 print("Entered context manager with counter value", x) return x def __exit__(self, exc_type, exc_value, traceback): print("Context manager exit sees", exc_type, exc_value, traceback) print("Published to context manager exit is", sys.exc_info()) return False print("Use context manager and raise no exception in the body:") with MyContextManager() as x: print("x has become", x) print("Use context manager and raise an exception in the body:") try: with MyContextManager() as x: print("x has become", x) raise Exception("Lalala") print(x) except Exception as e: print("Caught raised exception", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) # Python3 ranges are not lists l = list(range(3)) print("Use context manager and assign to subscription target:") with MyContextManager() as l[0]: print("Complex assignment target works", l[0]) try: with MyContextManager(): sys.exit(9) except BaseException as e: print("Caught base exception", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) print("Use context manager and fail to assign to attribute:") try: with MyContextManager() as l.wontwork: sys.exit(9) except BaseException as e: print("Caught base exception", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) print("Use context manager to do nothing inside:") with MyContextManager() as x: pass if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) # Use context manager and fail to assign. def returnFromContextBlock(): # Use context manager to do nothing. with MyContextManager() as x: return 7 if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) print("Use context manager to return value:") r = returnFromContextBlock() print("Return value", r) class NonContextManager1: def __enter__(self): return self class NonContextManager2: def __exit__(self): return self print("Use incomplete context managers:") try: with NonContextManager1() as x: print(x) except Exception as e: print("Caught for context manager without __exit__", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) try: with NonContextManager2() as x: print(x) except Exception as e: print("Caught for context manager without __enter__", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) class NotAtAllContextManager: pass try: with NotAtAllContextManager() as x: print(x) except Exception as e: print("Caught for context manager without any special methods", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) class MeanContextManager: def __enter__(self): raise ValueError("Nah, I won't play") def __exit__(self): print("Called exit, yes") print("Use mean context manager:") try: with MeanContextManager() as x: print(x) except Exception as e: print("Caught from mean manager", repr(e)) if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) class CatchingContextManager(object): def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): return True print("Suppressing exception from context manager body:") with CatchingContextManager(): raise ZeroDivisionError if sys.version_info >= (3,): assert sys.exc_info() == (None, None, None) print("OK") Nuitka-0.6.19.1/tests/basics/Functions32.py0000600000372100037210000000663414166627112025375 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def displayDict(d): result = "{" for key, value in sorted(d.items()): result += "%s: %s" % (key, value) result += "}" def kwonlysimple(*, a): return a print("Keyword only function case: ", kwonlysimple(a=3)) def kwonlysimpledefaulted(*, a=5): return a print("Keyword only function, using default value: ", kwonlysimpledefaulted()) def default1(): print("Called", default1) return 1 def default2(): print("Called", default2) return 2 def default3(): print("Called", default3) return 3 def default4(): print("Called", default4) return 4 def annotation1(): print("Called", annotation1) return "a1" def annotation2(): print("Called", annotation2) return "a2" def annotation3(): print("Called", annotation3) return "a3" def annotation4(): print("Called", annotation4) return "a4" def annotation5(): print("Called", annotation5) return "a5" def annotation6(): print("Called", annotation6) return "a6" def annotation7(): print("Called", annotation7) return "a7" def annotation8(): print("Called", annotation8) return "a8" def annotation9(): print("Called", annotation9) return "a9" print("Defining function with annotations, and defaults as functions for everything:") def kwonlyfunc( x: annotation1(), y: annotation2() = default1(), z: annotation3() = default2(), *, a: annotation4(), b: annotation5() = default3(), c: annotation6() = default4(), d: annotation7(), **kw: annotation8() ) -> annotation9(): print(x, y, z, a, b, c, d) print("__kwdefaults__", displayDict(kwonlyfunc.__kwdefaults__)) print("Keyword only function called:") kwonlyfunc(7, a=8, d=12) print("OK.") print("Annotations come out as", sorted(kwonlyfunc.__annotations__)) kwonlyfunc.__annotations__ = {} print("After updating to None it is", kwonlyfunc.__annotations__) kwonlyfunc.__annotations__ = {"k": 9} print("After updating to None it is", kwonlyfunc.__annotations__) def kwonlystarfunc(*, a, b, **d): return a, b, d print("kwonlystarfunc", kwonlystarfunc(a=8, b=12, k=9, j=7)) def deeplyNestedNonLocalWrite(): x = 0 y = 0 def f(): def g(): nonlocal x x = 3 return x return g() return f(), x print("Deeply nested non local writing function", deeplyNestedNonLocalWrite()) def deletingClosureVariable(): try: x = 1 def g(): nonlocal x del x g() g() except Exception as e: return repr(e) print("Using deleted non-local variable:", deletingClosureVariable()) Nuitka-0.6.19.1/tests/basics/Referencing_2.py0000600000372100037210000000552314166627112025724 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. These are for Python2 only constructs, which will give SyntaxError on other versions. """ # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start from nuitka.tools.testing.Common import executeReferenceChecked x = 17 # Python2 only syntax things are here. def simpleFunction1(): try: raise TypeError, (3, x, x, x) except TypeError: pass def simpleFunction2(): try: raise ValueError(1, 2, 3), ValueError(1, 2, 3) except Exception: pass def simpleFunction3(): try: raise ValueError, 2, None except Exception: pass def simpleFunction4(): try: raise ValueError, 2, 3 except Exception: pass def simpleFunction5(): def nested_args_function((a, b), c): return a, b, c nested_args_function((1, 2), 3) def simpleFunction6(): def nested_args_function((a, b), c): return a, b, c try: nested_args_function((1,), 3) except ValueError: pass def simpleFunction7(): def nested_args_function((a, b), c): return a, b, c try: nested_args_function((1, 2, 3), 3) except ValueError: pass def simpleFunction8(): from decimal import * d1 = Decimal("5") d2 = Decimal("2") (p, q) = divmod(d1, d2) (p, q) = divmod(d1, 4) (p, q) = divmod(7, d1) return q, p # These need stderr to be wrapped. tests_stderr = () # Disabled tests tests_skipped = {} result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/run_xml.py0000700000372100037210000000433114166627112024735 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import print_function import os, sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start import shutil import subprocess from nuitka.tools.testing.Common import check_output # Go its own directory, to have it easy with path knowledge. nuitka1 = sys.argv[1] nuitka2 = sys.argv[2] search_mode = len(sys.argv) > 3 and sys.argv[3] == "search" start_at = sys.argv[4] if len(sys.argv) > 4 else None if start_at: active = False else: active = True my_dir = os.path.dirname(os.path.abspath(__file__)) for filename in sorted(os.listdir(my_dir)): if not filename.endswith(".py") or filename.startswith("run_"): continue path = os.path.relpath(os.path.join(my_dir, filename)) if not active and start_at in (filename, path): active = True if active: command = "%s %s '%s' '%s' %s" % ( sys.executable, os.path.join(my_dir, "..", "..", "bin", "compare_with_xml"), nuitka1, nuitka2, path, ) result = subprocess.call(command, shell=True) if result == 2: sys.stderr.write("Interrupted, with CTRL-C\n") sys.exit(2) if result != 0 and search_mode: print("Error exit!", result) sys.exit(result) else: print("Skipping", filename) Nuitka-0.6.19.1/tests/basics/Classes.py0000600000372100037210000001124714166627112024651 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def displayDict(d): if "__loader__" in d: d = dict(d) d["__loader__"] = "<__loader__ removed>" if "__file__" in d: d = dict(d) d["__file__"] = "<__file__ removed>" # Avoid recursion that we don't offer for classes. if "__locals__" in d: d = dict(d) del d["__locals__"] import pprint return pprint.pformat(d) class SimpleClass: " The class documentation." # Leading space on purpose. # TODO: Doesn't work with Python3, because we don't yet make our own dict # visible. print locals() print "Class locals, while building", displayDict(locals()) class_var = 1 def __init__(self, init_parameter): self.x = init_parameter def normal_method(self, arg1, arg2): self.arg1 = arg1 self.arg2 = arg2 return self.arg1, self.arg2, self.x, self @staticmethod def static_method(): return "something" print "Simple class:", SimpleClass print "Lives in", SimpleClass.__module__ print "Documentation", SimpleClass.__doc__ print "Instantiate simple class:", SimpleClass(14) print "Call simple class normal method:", SimpleClass(11).normal_method(1, 2) print "Call simple class static method:", SimpleClass(11).static_method() class MetaClass(type): def __init__(cls, name, bases, dictionary): print "MetaClass is called." cls.addedin = 5 print MetaClass class ComplexClass: __metaclass__ = MetaClass print ComplexClass, dir(ComplexClass) print ComplexClass, hasattr(ComplexClass, "addedin") and ComplexClass.addedin def function(): x = 1 class DynamicClass: y = x x = 2 return DynamicClass print function(), function().y def strangeClassBehaviour(): class StrangeClass(object): count = 0 def __new__(cls): print "__new__" cls.count += 1 return object.__new__(cls) def __del__(self): print "__del__" cls = self.__class__ cls.count -= 1 assert cls.count >= 0 x = StrangeClass() return x.count print "Strange class with __new__ and __del__ overloads", strangeClassBehaviour() class ClosureLocalizer: function = function # Using what looks like a method as a decorator. def deco(f): # @NoSelf f.decorated = True return f @deco def x(self): pass print "Class with a name from module level renamed to local", ClosureLocalizer.function print "Class method decorated", ClosureLocalizer().x.decorated print "Class with decorator and meta class:" def classdecorator(cls): print "cls decorator", cls.addedin return cls @classdecorator class MyClass: __metaclass__ = MetaClass print "Class that updates its locals:", class DictUpdating: a = 1 locals().update({"b": 2}) for f in range(6): locals()["test_%s" % f] = f print "Changed values", DictUpdating.b, DictUpdating.test_4 def functionThatOffersClosureToPassThroughClass(x): class Foo: global x x = 1 def __call__(self, y): return x + y return Foo() print functionThatOffersClosureToPassThroughClass(6)(2), print x class NameCollisionClosure: def x(self): return x print NameCollisionClosure, NameCollisionClosure().x() class ClassesWithNestedClass: class NestedClass(object): def getDict(self): return {"a": 2} print "Classes:" print ClassesWithNestedClass, print ClassesWithNestedClass().NestedClass, print ClassesWithNestedClass().NestedClass().getDict() secondary = "global closure wins" class ClassWithModuleVariableCollisionMain: secondary = None def __init__(self): self.secondary = self.Child() self.value = self.secondary.attr class Child: def __init__(self): self.attr = secondary print ClassWithModuleVariableCollisionMain, ClassWithModuleVariableCollisionMain().value Nuitka-0.6.19.1/tests/basics/Referencing33.py0000600000372100037210000001675414166627112025661 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reference counting tests for features of Python3.3 or higher. These contain functions that do specific things, where we have a suspect that references may be lost or corrupted. Executing them repeatedly and checking the reference count is how they are used. These are Python3 specific constructs, that will give a SyntaxError or not be relevant on Python2. """ # While we use that for comparison code, no need to compile that. # nuitka-project: --nofollow-import-to=nuitka import os import sys # Find nuitka package relative to us. sys.path.insert( 0, os.path.normpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ), ) # isort:start import types from nuitka.tools.testing.Common import ( executeReferenceChecked, someGenerator, someGeneratorRaising, ) def simpleFunction1(): def abc(*, _exc=IOError): pass for _ in range(100): abc() def simpleFunction2(): def abc(*, exc=IOError): raise ValueError from None try: abc() except (ValueError, TypeError): pass def simpleFunction3(): try: class ClassA(Exception): pass class ClassB(Exception): pass try: raise ClassA("foo") except ClassA as e1: raise ClassB(str(e1)) from e1 except Exception: # different to Nuitka, pylint: disable=broad-except pass def simpleFunction4(): a = 1 def nonlocal_writer(): nonlocal a for a in range(10): # false alarm, pylint: disable=unused-variable pass nonlocal_writer() assert a == 9, a def simpleFunction5(): x = 2 def local_func(_a: int, _b: x * x): pass local_func(x, x) def simpleFunction6(): # Make sure exception state is cleaned up as soon as the except # block is left. class MyException(Exception): def __init__(self, obj): # This is on purpose not called, pylint: disable=super-init-not-called self.obj = obj class MyObj: pass def inner_raising_func(): local_ref = obj raise MyException(obj) # "except" block raising another exception obj = MyObj() try: try: inner_raising_func() except: raise KeyError except KeyError as e: # on purpose, pylint: disable=unused-variable pass range_low = 0 range_high = 256 range_step = 13 def simpleFunction7(): # Make sure xranges work nicely return range(range_low, range_high, range_step) def simpleFunction8(): # Make sure xranges work nicely return range(range_low, range_high) def simpleFunction9(): # Make sure xranges work nicely return range(range_high) def simpleFunction10(): def f(_x: int) -> int: pass return f def simpleFunction11(): try: raise ImportError(path="lala", name="lele") except ImportError as e: assert e.name == "lele" assert e.path == "lala" def simpleFunction12(): def g(): for a in range(20): yield a def h(): yield 4 yield 5 yield 6 def f(): yield from g() yield from h() _x = list(f()) def simpleFunction13(): def g(): for a in range(20): yield a def h(): yield 4 yield 5 yield 6 raise TypeError def f(): yield from g() yield from h() try: _x = list(f()) except TypeError: pass # Broken iterator class. class Broken: def __iter__(self): return self def __next__(self): return 1 def __getattr__(self, attr): 1 / 0 # pylint: disable=pointless-statement def simpleFunction14(): def g(): yield from Broken() try: gi = g() next(gi) except Exception: # pylint: disable=broad-except pass def simpleFunction15(): def g(): yield from Broken() try: gi = g() next(gi) gi.throw(AttributeError) except Exception: # pylint: disable=broad-except pass def simpleFunction16(): def g(): yield from (2, 3) return list(g()) def simpleFunction17(): def g(): yield from (2, 3) return 9 return list(g()) def simpleFunction18(): def g(): yield from (2, 3) return 9, 8 return list(g()) def simpleFunction19(): def g(): x = someGenerator() assert type(x) is types.GeneratorType yield from x gen = g() next(gen) try: gen.throw(ValueError) except ValueError: pass def simpleFunction20(): def g(): x = someGeneratorRaising() assert type(x) is types.GeneratorType yield from x gen = g() next(gen) try: next(gen) except TypeError: pass class ClassIteratorBrokenClose: def __init__(self): self.my_iter = iter(range(2)) def __iter__(self): return self def next(self): return next(self.my_iter) def close(self): raise TypeError(3) __next__ = next def simpleFunction21(): def g(): x = ClassIteratorBrokenClose() yield from x gen = g() next(gen) try: gen.throw(GeneratorExit) except TypeError: pass class ClassIteratorBrokenThrow: def __init__(self): self.my_iter = iter(range(2)) def __iter__(self): return self def next(self): return next(self.my_iter) def throw(self, *args): raise TypeError(3) __next__ = next def simpleFunction22(): def g(): x = ClassIteratorBrokenThrow() yield from x gen = g() next(gen) try: gen.throw(ValueError) except GeneratorExit: pass except TypeError: pass class ClassIteratorRejectingThrow: def __init__(self): self.my_iter = iter(range(2)) def __iter__(self): return self def next(self): return next(self.my_iter) def throw(self, *args): # This should not be subject normalize exceptions. assert len(args) == 1, args __next__ = next # Lets have an exception that must not be instantiated. class MyError(Exception): def __init__(self): # pylint: disable=super-init-not-called assert False def simpleFunction23(): def g(): x = ClassIteratorRejectingThrow() yield from x gen = g() next(gen) gen.throw(MyError) # These need stderr to be wrapped. tests_stderr = (14, 15) # Disabled tests tests_skipped = {} result = executeReferenceChecked( prefix="simpleFunction", names=globals(), tests_skipped=tests_skipped, tests_stderr=tests_stderr, ) sys.exit(0 if result else 1) Nuitka-0.6.19.1/tests/basics/TrickAssignments_2.py0000600000372100037210000000337414166627112026767 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # def someFunctionThatReturnsDeletedValueViaLong(): class C: def __int__(self): a.append(2) return False c = C() a = [1] long(c) return a if someFunctionThatReturnsDeletedValueViaLong()[-1] == 2: print("OK, object long correctly modified an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaNot(): class C: def __nonzero__(self): a.append(2) return False c = C() a = [1] not c return a if someFunctionThatReturnsDeletedValueViaNot()[-1] == 2: print("OK, object bool correctly modified an item.") else: print("Ouch.!") def someFunctionThatReturnsDeletedValueViaCompare(): class C: def __cmp__(self, other): a.append(2) return 0 c = C() a = [1] c < None return a if someFunctionThatReturnsDeletedValueViaCompare()[-1] == 2: print("OK, object compare correctly modified an item.") else: print("Ouch.!") Nuitka-0.6.19.1/tests/basics/RecursionTest.py0000600000372100037210000000155614166627112026067 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # count = 0 def recurse(): global count count += 1 if count < 50: recurse() recurse() Nuitka-0.6.19.1/doc/0000700000372100037210000000000014167275622021040 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/doc/nuitka2.10000600000372100037210000005231214167275621022503 0ustar nuitka-buildslavenuitka-buildslave00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. .TH NUITKA "1" "January 2022" "nuitka 0.6.19.1" "User Commands" .SH NAME nuitka \- the Python compiler .SH SYNOPSIS .B nuitka [\fI\,--module\/\fR] [\fI\,--run\/\fR] [\fI\,options\/\fR] \fI\,main_module.py\/\fR .SH OPTIONS .TP \fB\-\-version\fR show program's version number and exit .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-\-module\fR Create an extension module executable instead of a program. Defaults to off. .TP \fB\-\-standalone\fR Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "\-\-follow\-imports". You may also want to use "\-\-python\-flag=no_site" to avoid the "site.py" module, which can save a lot of code dependencies. Defaults to off. .TP \fB\-\-onefile\fR On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to off. .TP \fB\-\-python\-debug\fR Use debug version or not. Default uses what you are using to run Nuitka, most likely a non\-debug version. .TP \fB\-\-python\-flag\fR=\fI\,FLAG\/\fR Python flags to use. Default is what you are using to run Nuitka, this enforces a specific mode. These are options that also exist to standard Python executable. Currently supported: "\-S" (alias "no_site"), "static_hashes" (do not use hash randomization), "no_warnings" (do not give Python runtime warnings), "\-O" (alias "no_asserts"), "no_docstrings" (do not use docstrings), and "\-m". Default empty. .TP \fB\-\-python\-for\-scons\fR=\fI\,PATH\/\fR If using Python3.3 or Python3.4, provide the path of a Python binary to use for Scons. Otherwise Nuitka can use what you run Nuitka with or a "scons" binary that is found in PATH, or a Python installation from Windows registry. .TP \fB\-\-warn\-implicit\-exceptions\fR Enable warnings for implicit exceptions detected at compile time. .TP \fB\-\-warn\-unusual\-code\fR Enable warnings for unusual code detected at compile time. .TP \fB\-\-assume\-yes\-for\-downloads\fR Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "" is used. For compatibility reasons, the "__file__" value will always have ".py" suffix independent of what it really is. .IP Output choices: .TP \fB\-o\fR FILENAME Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '' on this platform. \&.bin .TP \fB\-\-output\-dir\fR=\fI\,DIRECTORY\/\fR Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. .TP \fB\-\-remove\-output\fR Removes the build directory after producing the module or exe file. Defaults to off. .TP \fB\-\-no\-pyi\-file\fR Do not create a ".pyi" file for extension modules created by Nuitka. This is used to detect implicit imports. Defaults to off. .IP Debug features: .TP \fB\-\-debug\fR Executing all self checks possible to find errors in Nuitka, do not use for production. Defaults to off. .TP \fB\-\-unstripped\fR Keep debug info in the resulting object file for better debugger interaction. Defaults to off. .TP \fB\-\-profile\fR Enable vmprof based profiling of time spent. Not working currently. Defaults to off. .TP \fB\-\-internal\-graph\fR Create graph of optimization process internals, do not use for whole programs, but only for small test cases. Defaults to off. .TP \fB\-\-trace\-execution\fR Traced execution output, output the line of code before executing it. Defaults to off. .TP \fB\-\-recompile\-c\-only\fR This is not incremental compilation, but for Nuitka development only. Takes existing files and simply compile them as C again. Allows compiling edited C files for quick debugging changes to the generated source, e.g. to see if code is passed by, values output, etc, Defaults to off. Depends on compiling Python source to determine which files it should look at. .TP \fB\-\-generate\-c\-only\fR Generate only C source code, and do not compile it to binary or module. This is for debugging and code coverage analysis that doesn't waste CPU. Defaults to off. Do not think you can use this directly. .TP \fB\-\-experimental\fR=\fI\,FLAG\/\fR Use features declared as 'experimental'. May have no effect if no experimental features are present in the code. Uses secret tags (check source) per experimented feature. .TP \fB\-\-low\-memory\fR Attempt to use less memory, by forking less C compilation jobs and using options that use less memory. For use on embedded machines. Use this in case of out of memory problems. Defaults to off. .IP Backend C compiler choice: .TP \fB\-\-clang\fR Enforce the use of clang. On Windows this requires a working Visual Studio version to piggy back on. Defaults to off. .TP \fB\-\-mingw64\fR Enforce the use of MinGW64 on Windows. Defaults to off. .TP \fB\-\-msvc\fR=\fI\,MSVC_VERSION\/\fR Enforce the use of specific MSVC version on Windows. Allowed values are e.g. "14.2" (MSVC 2019), specify an illegal value for a list of installed compilers, or use "latest". Notice that only latest MSVC is really supported, and you can use "latest" to enforce that. Defaults to MSVC on Windows being used if installed, otherwise MinGW64. .TP \fB\-j\fR N, \fB\-\-jobs\fR=\fI\,N\/\fR Specify the allowed number of parallel C compiler jobs. Defaults to the system CPU count. .TP \fB\-\-lto\fR=\fI\,choice\/\fR Use link time optimizations (MSVC, gcc, clang). Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-static\-libpython\fR=\fI\,choice\/\fR Use static link library of Python. Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-disable\-ccache\fR Do not attempt to use ccache (gcc, clang, etc.) or clcache (MSVC, clangcl). .IP PGO compilation choices: .TP \fB\-\-pgo\fR Enables C level profile guided optimization (PGO), by executing a dedicated build first for a profiling run, and then using the result to feedback into the C compilation. Note: This is experimental and not working with standalone modes of Nuitka yet. Defaults to off. .TP \fB\-\-pgo\-args\fR=\fI\,PGO_ARGS\/\fR Arguments to be passed in case of profile guided optimization. These are passed to the special built executable during the PGO profiling run. Default empty. .TP \fB\-\-pgo\-executable\fR=\fI\,PGO_EXECUTABLE\/\fR Command to execute when collecting profile information. Use this only, if you need to launch it through a script that prepares it to run. Default use created program. .IP Tracing features: .TP \fB\-\-quiet\fR Disable all information outputs, but show warnings. Defaults to off. .TP \fB\-\-show\-scons\fR Operate Scons in non\-quiet mode, showing the executed commands. Defaults to off. .TP \fB\-\-show\-progress\fR Provide progress information and statistics. Defaults to off. .TP \fB\-\-no\-progressbar\fR Disable progress bar outputs (if tqdm is installed). Defaults to off. .TP \fB\-\-show\-memory\fR Provide memory information and statistics. Defaults to off. .TP \fB\-\-show\-modules\fR Provide information for included modules and DLLs Defaults to off. .TP \fB\-\-show\-modules\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-show\-modules\fR, should be a filename. Default is standard output. .TP \fB\-\-report\fR=\fI\,COMPILATION_REPORT_FILENAME\/\fR Report module inclusion in an XML output file. Default is off. .TP \fB\-\-verbose\fR Output details of actions taken, esp. in optimizations. Can become a lot. Defaults to off. .TP \fB\-\-verbose\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-verbose\fR, should be a filename. Default is standard output. .IP Windows specific controls: .TP \fB\-\-windows\-disable\-console\fR When compiling for Windows, disable the console window. Defaults to off. .TP \fB\-\-windows\-icon\-from\-ico\fR=\fI\,ICON_PATH\/\fR Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with # where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. .TP \fB\-\-windows\-icon\-from\-exe\fR=\fI\,ICON_EXE_PATH\/\fR Copy executable icons from this existing executable (Windows only). .TP \fB\-\-onefile\-windows\-splash\-screen\-image\fR=\fI\,SPLASH_SCREEN_IMAGE\/\fR When compiling for Windows and onefile, show this while loading the application. Defaults to off. .TP \fB\-\-windows\-uac\-admin\fR Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. .TP \fB\-\-windows\-uac\-uiaccess\fR Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. .TP \fB\-\-windows\-company\-name\fR=\fI\,WINDOWS_COMPANY_NAME\/\fR Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-name\fR=\fI\,WINDOWS_PRODUCT_NAME\/\fR Name of the product to use in Windows Version information. Defaults to base filename of the binary. .TP \fB\-\-windows\-file\-version\fR=\fI\,WINDOWS_FILE_VERSION\/\fR File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-version\fR=\fI\,WINDOWS_PRODUCT_VERSION\/\fR Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-file\-description\fR=\fI\,WINDOWS_FILE_DESCRIPTION\/\fR Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. .TP \fB\-\-windows\-onefile\-tempdir\-spec\fR=\fI\,ONEFILE_TEMPDIR_SPEC\/\fR Use this as a temporary folder. Defaults to \&'%TEMP%\eonefile_%PID%_%TIME%', i.e. system temporary directory. .TP \fB\-\-windows\-force\-stdout\-spec\fR=\fI\,WINDOWS_FORCE_STDOUT_SPEC\/\fR Force standard output of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.out.txt', i.e. file near your program. .TP \fB\-\-windows\-force\-stderr\-spec\fR=\fI\,WINDOWS_FORCE_STDERR_SPEC\/\fR Force standard error of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.err.txt', i.e. file near your program. .IP macOS specific controls: .TP \fB\-\-macos\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for binary to use. Can be given only one time. Defaults to Python icon if available. .TP \fB\-\-macos\-disable\-console\fR When compiling for macOS, disable the console window and create a GUI application. Defaults to off. .TP \fB\-\-macos\-create\-app\-bundle\fR When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console.Defaults to off. .TP \fB\-\-macos\-signed\-app\-name\fR=\fI\,MACOS_SIGNED_APP_NAME\/\fR Name of the application to use for macOS signing. Follow com.yourcompany.appname naming results for best results, as these have to be globally unique, and will grant protected API accesses. .TP \fB\-\-macos\-app\-name\fR=\fI\,MACOS_APP_NAME\/\fR Name of the product to use in macOS bundle information. Defaults to base filename of the binary. .TP \fB\-\-macos\-app\-version\fR=\fI\,MACOS_APP_VERSION\/\fR Product version to use in macOS bundle information. Defaults to 1.0 if not given. .IP Linux specific controls: .TP \fB\-\-linux\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for onefile binary to use. Can be given only one time. Defaults to Python icon if available. .IP Plugin control: .TP \fB\-\-enable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-enable\fR=\fI\,PLUGIN_NAME\/\fR Enabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-disable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-disable\fR=\fI\,PLUGIN_NAME\/\fR Disabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-plugin\-no\-detection\fR Plugins can detect if they might be used, and the you can disable the warning via "\-\-disable\-plugin=pluginthat\-warned", or you can use this option to disable the mechanism entirely, which also speeds up compilation slightly of course as this detection code is run in vain once you are certain of which plugins to use. Defaults to off. .TP \fB\-\-plugin\-list\fR Show list of all available plugins and exit. Defaults to off. .TP \fB\-\-user\-plugin\fR=\fI\,PATH\/\fR The file name of user plugin. Can be given multiple times. Default empty. .TP \fB\-\-persist\-source\-changes\fR Write source changes to original Python files. Use with care. May need permissions, best for use in a virtualenv to debug if plugin code changes work with standard Python or to benefit from bloat removal even with pure Python. Default False. .PP Commercial: None Python: 2.7.16 (default, Oct 10 2019, 22:02:15) Flavor: Debian Python Executable: \fI\,/usr/bin/python2\/\fP OS: Linux Arch: x86_64 Distribution: Debian 10.9 .SH EXAMPLES Compile a Python file "some_module.py" to a module "some_module.so": .IP \f(CW$ nuitka \-\-module some_module.py\fR .PP Compile a Python program "some_program.py" to an executable "some_program.exe": .IP \f(CW$ nuitka some_program.py\fR .PP Compile a Python program "some_program.py" and the package "some_package" it uses to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-to=some_package some_program.py\fR .PP Compile a Python program "some_program.py" and all the modules it uses to an executable "some_program.exe". Then execute it immediately when ready: .IP \f(CW$ nuitka \-\-run \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses (even standard library) to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-stdlib some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Keep the debug information, so valgrind, gdb, etc. work nicely. Note: This will *not* degrade performance: .IP \f(CW$ nuitka \-\-unstriped \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Also use the debug Python library, which does its own checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-python-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the plugins modules it loads at run time to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-directory=plugins_dir some_program.py\fR .PP Nuitka-0.6.19.1/doc/nuitka3.10000600000372100037210000005231014167275622022503 0ustar nuitka-buildslavenuitka-buildslave00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. .TH NUITKA "1" "January 2022" "nuitka 0.6.19.1" "User Commands" .SH NAME nuitka \- the Python compiler .SH SYNOPSIS .B nuitka [\fI\,--module\/\fR] [\fI\,--run\/\fR] [\fI\,options\/\fR] \fI\,main_module.py\/\fR .SH OPTIONS .TP \fB\-\-version\fR show program's version number and exit .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-\-module\fR Create an extension module executable instead of a program. Defaults to off. .TP \fB\-\-standalone\fR Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "\-\- follow\-imports". You may also want to use "\-\-pythonflag=no_site" to avoid the "site.py" module, which can save a lot of code dependencies. Defaults to off. .TP \fB\-\-onefile\fR On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to off. .TP \fB\-\-python\-debug\fR Use debug version or not. Default uses what you are using to run Nuitka, most likely a non\-debug version. .TP \fB\-\-python\-flag\fR=\fI\,FLAG\/\fR Python flags to use. Default is what you are using to run Nuitka, this enforces a specific mode. These are options that also exist to standard Python executable. Currently supported: "\-S" (alias "no_site"), "static_hashes" (do not use hash randomization), "no_warnings" (do not give Python runtime warnings), "\-O" (alias "no_asserts"), "no_docstrings" (do not use docstrings), and "\-m". Default empty. .TP \fB\-\-python\-for\-scons\fR=\fI\,PATH\/\fR If using Python3.3 or Python3.4, provide the path of a Python binary to use for Scons. Otherwise Nuitka can use what you run Nuitka with or a "scons" binary that is found in PATH, or a Python installation from Windows registry. .TP \fB\-\-warn\-implicit\-exceptions\fR Enable warnings for implicit exceptions detected at compile time. .TP \fB\-\-warn\-unusual\-code\fR Enable warnings for unusual code detected at compile time. .TP \fB\-\-assume\-yes\-for\-downloads\fR Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "" is used. For compatibility reasons, the "__file__" value will always have ".py" suffix independent of what it really is. .IP Output choices: .TP \fB\-o\fR FILENAME Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '' on this platform. \&.bin .TP \fB\-\-output\-dir\fR=\fI\,DIRECTORY\/\fR Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. .TP \fB\-\-remove\-output\fR Removes the build directory after producing the module or exe file. Defaults to off. .TP \fB\-\-no\-pyi\-file\fR Do not create a ".pyi" file for extension modules created by Nuitka. This is used to detect implicit imports. Defaults to off. .IP Debug features: .TP \fB\-\-debug\fR Executing all self checks possible to find errors in Nuitka, do not use for production. Defaults to off. .TP \fB\-\-unstripped\fR Keep debug info in the resulting object file for better debugger interaction. Defaults to off. .TP \fB\-\-profile\fR Enable vmprof based profiling of time spent. Not working currently. Defaults to off. .TP \fB\-\-internal\-graph\fR Create graph of optimization process internals, do not use for whole programs, but only for small test cases. Defaults to off. .TP \fB\-\-trace\-execution\fR Traced execution output, output the line of code before executing it. Defaults to off. .TP \fB\-\-recompile\-c\-only\fR This is not incremental compilation, but for Nuitka development only. Takes existing files and simply compile them as C again. Allows compiling edited C files for quick debugging changes to the generated source, e.g. to see if code is passed by, values output, etc, Defaults to off. Depends on compiling Python source to determine which files it should look at. .TP \fB\-\-generate\-c\-only\fR Generate only C source code, and do not compile it to binary or module. This is for debugging and code coverage analysis that doesn't waste CPU. Defaults to off. Do not think you can use this directly. .TP \fB\-\-experimental\fR=\fI\,FLAG\/\fR Use features declared as 'experimental'. May have no effect if no experimental features are present in the code. Uses secret tags (check source) per experimented feature. .TP \fB\-\-low\-memory\fR Attempt to use less memory, by forking less C compilation jobs and using options that use less memory. For use on embedded machines. Use this in case of out of memory problems. Defaults to off. .IP Backend C compiler choice: .TP \fB\-\-clang\fR Enforce the use of clang. On Windows this requires a working Visual Studio version to piggy back on. Defaults to off. .TP \fB\-\-mingw64\fR Enforce the use of MinGW64 on Windows. Defaults to off. .TP \fB\-\-msvc\fR=\fI\,MSVC_VERSION\/\fR Enforce the use of specific MSVC version on Windows. Allowed values are e.g. "14.2" (MSVC 2019), specify an illegal value for a list of installed compilers, or use "latest". Notice that only latest MSVC is really supported, and you can use "latest" to enforce that. Defaults to MSVC on Windows being used if installed, otherwise MinGW64. .TP \fB\-j\fR N, \fB\-\-jobs\fR=\fI\,N\/\fR Specify the allowed number of parallel C compiler jobs. Defaults to the system CPU count. .TP \fB\-\-lto\fR=\fI\,choice\/\fR Use link time optimizations (MSVC, gcc, clang). Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-static\-libpython\fR=\fI\,choice\/\fR Use static link library of Python. Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-disable\-ccache\fR Do not attempt to use ccache (gcc, clang, etc.) or clcache (MSVC, clangcl). .IP PGO compilation choices: .TP \fB\-\-pgo\fR Enables C level profile guided optimization (PGO), by executing a dedicated build first for a profiling run, and then using the result to feedback into the C compilation. Note: This is experimental and not working with standalone modes of Nuitka yet. Defaults to off. .TP \fB\-\-pgo\-args\fR=\fI\,PGO_ARGS\/\fR Arguments to be passed in case of profile guided optimization. These are passed to the special built executable during the PGO profiling run. Default empty. .TP \fB\-\-pgo\-executable\fR=\fI\,PGO_EXECUTABLE\/\fR Command to execute when collecting profile information. Use this only, if you need to launch it through a script that prepares it to run. Default use created program. .IP Tracing features: .TP \fB\-\-quiet\fR Disable all information outputs, but show warnings. Defaults to off. .TP \fB\-\-show\-scons\fR Operate Scons in non\-quiet mode, showing the executed commands. Defaults to off. .TP \fB\-\-show\-progress\fR Provide progress information and statistics. Defaults to off. .TP \fB\-\-no\-progressbar\fR Disable progress bar outputs (if tqdm is installed). Defaults to off. .TP \fB\-\-show\-memory\fR Provide memory information and statistics. Defaults to off. .TP \fB\-\-show\-modules\fR Provide information for included modules and DLLs Defaults to off. .TP \fB\-\-show\-modules\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-show\-modules\fR, should be a filename. Default is standard output. .TP \fB\-\-report\fR=\fI\,COMPILATION_REPORT_FILENAME\/\fR Report module inclusion in an XML output file. Default is off. .TP \fB\-\-verbose\fR Output details of actions taken, esp. in optimizations. Can become a lot. Defaults to off. .TP \fB\-\-verbose\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-verbose\fR, should be a filename. Default is standard output. .IP Windows specific controls: .TP \fB\-\-windows\-disable\-console\fR When compiling for Windows, disable the console window. Defaults to off. .TP \fB\-\-windows\-icon\-from\-ico\fR=\fI\,ICON_PATH\/\fR Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with # where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. .TP \fB\-\-windows\-icon\-from\-exe\fR=\fI\,ICON_EXE_PATH\/\fR Copy executable icons from this existing executable (Windows only). .TP \fB\-\-onefile\-windows\-splash\-screen\-image\fR=\fI\,SPLASH_SCREEN_IMAGE\/\fR When compiling for Windows and onefile, show this while loading the application. Defaults to off. .TP \fB\-\-windows\-uac\-admin\fR Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. .TP \fB\-\-windows\-uac\-uiaccess\fR Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. .TP \fB\-\-windows\-company\-name\fR=\fI\,WINDOWS_COMPANY_NAME\/\fR Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-name\fR=\fI\,WINDOWS_PRODUCT_NAME\/\fR Name of the product to use in Windows Version information. Defaults to base filename of the binary. .TP \fB\-\-windows\-file\-version\fR=\fI\,WINDOWS_FILE_VERSION\/\fR File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-version\fR=\fI\,WINDOWS_PRODUCT_VERSION\/\fR Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-file\-description\fR=\fI\,WINDOWS_FILE_DESCRIPTION\/\fR Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. .TP \fB\-\-windows\-onefile\-tempdir\-spec\fR=\fI\,ONEFILE_TEMPDIR_SPEC\/\fR Use this as a temporary folder. Defaults to \&'%TEMP%\eonefile_%PID%_%TIME%', i.e. system temporary directory. .TP \fB\-\-windows\-force\-stdout\-spec\fR=\fI\,WINDOWS_FORCE_STDOUT_SPEC\/\fR Force standard output of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.out.txt', i.e. file near your program. .TP \fB\-\-windows\-force\-stderr\-spec\fR=\fI\,WINDOWS_FORCE_STDERR_SPEC\/\fR Force standard error of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.err.txt', i.e. file near your program. .IP macOS specific controls: .TP \fB\-\-macos\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for binary to use. Can be given only one time. Defaults to Python icon if available. .TP \fB\-\-macos\-disable\-console\fR When compiling for macOS, disable the console window and create a GUI application. Defaults to off. .TP \fB\-\-macos\-create\-app\-bundle\fR When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console.Defaults to off. .TP \fB\-\-macos\-signed\-app\-name\fR=\fI\,MACOS_SIGNED_APP_NAME\/\fR Name of the application to use for macOS signing. Follow com.yourcompany.appname naming results for best results, as these have to be globally unique, and will grant protected API accesses. .TP \fB\-\-macos\-app\-name\fR=\fI\,MACOS_APP_NAME\/\fR Name of the product to use in macOS bundle information. Defaults to base filename of the binary. .TP \fB\-\-macos\-app\-version\fR=\fI\,MACOS_APP_VERSION\/\fR Product version to use in macOS bundle information. Defaults to 1.0 if not given. .IP Linux specific controls: .TP \fB\-\-linux\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for onefile binary to use. Can be given only one time. Defaults to Python icon if available. .IP Plugin control: .TP \fB\-\-enable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-enable\fR=\fI\,PLUGIN_NAME\/\fR Enabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-disable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-disable\fR=\fI\,PLUGIN_NAME\/\fR Disabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-plugin\-no\-detection\fR Plugins can detect if they might be used, and the you can disable the warning via "\-\-disable\-plugin=pluginthat\-warned", or you can use this option to disable the mechanism entirely, which also speeds up compilation slightly of course as this detection code is run in vain once you are certain of which plugins to use. Defaults to off. .TP \fB\-\-plugin\-list\fR Show list of all available plugins and exit. Defaults to off. .TP \fB\-\-user\-plugin\fR=\fI\,PATH\/\fR The file name of user plugin. Can be given multiple times. Default empty. .TP \fB\-\-persist\-source\-changes\fR Write source changes to original Python files. Use with care. May need permissions, best for use in a virtualenv to debug if plugin code changes work with standard Python or to benefit from bloat removal even with pure Python. Default False. .PP Commercial: None Python: 3.7.3 (default, Jan 22 2021, 20:04:44) Flavor: Debian Python Executable: \fI\,/usr/bin/python3\/\fP OS: Linux Arch: x86_64 Distribution: Debian 10.9 .SH EXAMPLES Compile a Python file "some_module.py" to a module "some_module.so": .IP \f(CW$ nuitka \-\-module some_module.py\fR .PP Compile a Python program "some_program.py" to an executable "some_program.exe": .IP \f(CW$ nuitka some_program.py\fR .PP Compile a Python program "some_program.py" and the package "some_package" it uses to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-to=some_package some_program.py\fR .PP Compile a Python program "some_program.py" and all the modules it uses to an executable "some_program.exe". Then execute it immediately when ready: .IP \f(CW$ nuitka \-\-run \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses (even standard library) to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-stdlib some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Keep the debug information, so valgrind, gdb, etc. work nicely. Note: This will *not* degrade performance: .IP \f(CW$ nuitka \-\-unstriped \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Also use the debug Python library, which does its own checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-python-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the plugins modules it loads at run time to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-directory=plugins_dir some_program.py\fR .PP Nuitka-0.6.19.1/doc/Logo/0000700000372100037210000000000014167275622021740 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/doc/Logo/Nuitka-Logo-Symbol.svg0000600000372100037210000001635114166627112026057 0ustar nuitka-buildslavenuitka-buildslave00000000000000 image/svg+xml Nuitka-0.6.19.1/doc/Logo/Nuitka-Logo-Horizontal.svg0000600000372100037210000001623114166627112026740 0ustar nuitka-buildslavenuitka-buildslave00000000000000 image/svg+xml Nuitka Nuitka-0.6.19.1/doc/Logo/Nuitka-Logo-Vertical.svg0000600000372100037210000004277514166627112026374 0ustar nuitka-buildslavenuitka-buildslave00000000000000 image/svg+xml Nuitka Nuitka-0.6.19.1/doc/images/0000700000372100037210000000000014167275622022305 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/doc/images/Nuitka-Logo-Vertical.png0000600000372100037210000002314414166627112026713 0ustar nuitka-buildslavenuitka-buildslave00000000000000PNG  IHDRU?cPgAMA asRGB cHRMz&u0`:pQ< pHYsHHFk>bKGDC%YIDATx}ygݻ^{](J)i@MI|xS @JSEhIq*%(B)iU B X'@ԪH4k@ ,sNkw>9sg>Ν;3Aj<Zv1CڝƘI=zR~Ŀo{ѷԥޒNjMױ7oڊ^}_ByIcIoc̏/aA?~|7JcID$oXәB+$g=z׺ʒ>sz])Mkkoz8*o]tEo02[J3>>s>IiA*[~kvJB}nj*k}q||[l1f Dˍ1G%]O$BMOHG@Yksbb6ǎZFޅS.j c?+ڛDRڀ?+ok]7oOF++$Z ն=C1Z;:66nF!Ru!K$=(Pۓ]V3jjLLLtKvI Zn6ʈDi$m!]&ܬ5= WO=b u}~&B-tP.c&*W; 6j|6nNF.RMZ\@M[2v r@}mPVkH5iC6sBm`PL4E6ZZձPf*9[ =AS+_kۓaL6:(m9*b%S%O\J~ZʽPi!U6nJ~*2Tg"W {8Bũm F3bU KO7.28oB4JB-2T)! '%PLʜ_ȕLM٪;jOy_aODeP R$n3KT.T2U 5W*@NuST] RdP* <>Nj^j(ԅj?'N7Sv T@mpj|- 5U H PHȵzsRd_Bm<]2 *@2T/_t!T@m RP-BL8NRZOk dP5 5) *@ U"U 5ZkS*@FB2)p[B6xBO ІtաP *@*"V8j*Ce? t5mg.je4Ml;1_۠ s?PLIǽL 5djJDBH_jtJ'S¤c.UJ~T"TQ'*?sOf.u.3io^dgf"԰$"U(iJ VTEj+BGH5sEl] ՏP6#Tsj"%?*RP-BEHJ6eB3VGBf B`BlDR6`Bצ7/q@:{GT2T*# d1Kcm㗳GuF/RR][y|ZN*kulr6]!BmP][KpCpd[ x8`J6<2x7zVt][k{<'B l DBGM?ʀ55^;Ps/TnFI髽[N6&k5m|Nϭm@Ѿ=Ȕ^jNZ"Մc3pI=vOv+OvxVr^:?PlwLiPs)T(試 B =.9mY_`{=ѣB"Tu\eݏ.1v{V B͛P*RE{fN>_tӾZ]3"UPGb57ܫ.Ps"TY*B͟Pf?X{_*BEFmY]O P(TT[-BWCF{w Զ r*R%CͳPg[#2woG BmPIT*B-PgfuBźӾU2]BeEPsonAχ>uy"UP.kMUuVP3eALPwoN[~յWOAdHBBmW4mC b^ފAԮ5㯘gp44c={uE R*P*BEQ_f:c=wME3" f~UoFۆFC[;W"P*BEQ_fm`X~uW BEH"ԨzS68`nZ[~*"TPjWim!֝UP*R͍N=>6;@z'Tɷ_?AVo͂Teص) m*dlZdyͮ8I 6EGa!d B%Q2՜3{f~|㖯k5yU B xn Xx3xp-yѮl;,>h},}ϋy\: T H5jHo uKcg TCO1<=VdP 54a$C Y6 '*B-Pk RE"EM 5BD\2U2R 5)FND7 Sa Bj)T HvcƟSBB7*=U**4KR+ 5.`B=B#Th3TC(*5>UByA w"T@U 5* HCcm ysD!zQT] aOշ[|(&K|_#Uu"Tc^$ H5)e-*4S}Nu*$#Ԣw~H D9rqIeKH! pPIT2̄ڸ^\r:~! d-%<3 5*dEهRm%{9F"ԂfٳgH ՖT*4P "qxnn[!z1+{)3%62j*jƘϒɓ'`YJ3 1c̗ꇈRMnajvv*+w]uU ={d%.2NNN~cddJkvwEB_7/kÇ?Yz+5|YtA 3Tg$]522rӁfgw}ER1UBeZ{E###? ᖪ{%4, uޒ1sssٳMB:=s1fGR,i O65Wo-U/ foIO#.uӋƾcg7p|K}$}]?aR>k׮i"ɸT}^tZ$i $U_;|׼4ř'%g!1.'D I!3b]qU h}c $L!IcnpRgk۞-iRHoUe`!鄤7§$}(i2ཝBm_Y)E_=ǃYA H:scjL\/TKϞ22FqB.(ɯ)I=>(-!$$DdET[:HI߫%KMvI"({ZGTLr뒺!sC"p-Ջ%9!KU}R[%EjHu@W#@:RBY^B O%PēJm/ H59a|U4EE?}|j !X6)靄j4"b}WJ}B H5[Z*͘fO^@"9KtTOJ%bb^@ge -hh~AH՗tc0C !UIElswh|x l^#VX/ˀI/>ş燕l١IIPq=cfZ»2sf3[B5%6SL<T}յ4>#0ߌ t2q %cP+*'IUR`E<`7(J&v0-" ;.CrKQm&;tվ(p0Av"0/bq v ^^`E4DF OLt +ў1wۨ76ZdfyxyxpH5 )P;g3splYJPl L4~U:`HϜMpXcgI׉_+xϼ5:pz3 ||QF#XS4 GH p2)>X'"d)DOB|Ѽǹ;I@ {9?H+,2ՈDQAr'X>nSH=QҠئGFzjfi^+:c2"WpI`/0|-kY;"c5MH2kD_j_ J@!53Ҥ9t6Vze$0NxdTL+r tZki _k]-ĬKߒn^EQ$|mN &LFu2;hV99LʷZ,"SQ NMvվ(xax?yf%IuOZTy%iA-~d!IU^98@$B9En1pܹy~oKRFե ϦBtc,9V dTȥ` }v+cGjs}ELBJMžr>?EZ9H\тHnפR`E@Q`$q-w˕O-WRP`E4$( TmIߩ=[ " ڈ T ٴRtF*nq)u]J)[(J{}&q$Y> NޠJQJDKHb朶A/$j?$ CW"Ļ]̊`:ziT_n'8+N$/:6%48,?~:ݐr(CփdۖLXKLnE% #rAIR uH*|:WbReM;= x'Wgt_h&gC4f\JŞ\QYC|A<=Ao@,7>*Qm-мDpO1 I8 H wke}`{t(J\we ̼B2Jz-kd=uԌqGw&HˑW͚(3Ž9HrO<ݐA|W+xƺܼ"ya%+FmFdck!E1R =) uoIdӭ6O!WrZq)2737L~*K0Mq#` p1 :a/RlZ)Q ,m/b*p':_BltvbXdS(b{w^f5\$j GZzeVd rE#r!C/ULGLV%G{ {SNt鍒Zql^8a67Cp`V$n)ɪQ+)}w:{GUQٜ3P-Y }|EG+dLI AK؂xp9.sXA݁ĉ&E'87 ~Y{镣>dy'z(-MUO0VIp55q2uFR ˃Q{!HH߰}cvPi^DRd6;2CcԌ̋Q 9ׯh9]vz:f9КaݧQZsE܌gSlH%b z-ls=r,n&׃>jc$Efu̺g+0+FF%n[fڡI,bV{A䘬=|Q);єt)ނ:Me`T:<%8 3fTAȫ^C#ǞHR5oq''eݨkm+ 4N H>%\k:'o2 k_Z{m,gȘQWL4>V]nYw|4N&8}7VfɎfqoo$sq~A20ge\ x$?Ro"z#w;bTwABA|7Oⵀo1[wͳQ98g?QZ0?^d<y)?§\8wLZ,~Jo⎞mH}QfVᵔ}{H<[`Xy:&wYϕQ]mbq= d罐o"#UH^o5nC~&/"Ǘ8$%}BrD&Yg'LE&܆IK2>MeHbVIjqi[;-* &NRoc.q}͍w+3 R2`UsHk쀜oiuYO 'ǻ{3fT"uw4"{9:.Kʠ{'e#%W,#UIZ1&vF3#lj8ylڎg8^&ˡeD" |}t඘ x9rm%?"uYa||S, `G1/w! }#|1Ck1n)Ioh7#L[ bKGDCIDATxyUǿ3%$@A E@QكK؅dM6 @(N@>A$1d'$S={k|?nuWߪ[:EQz8`* hfk8 XW'Т](rIAɼiO`?"EQŅ,A5O3-}t^JCR@Q ܡǁEHz3g(9}b}g $ iylkD:٧nEKcrnmsm?K7tqc:`Nccs#GlKLb8](y66{쳀E /bbƈ|۰:  ٬L,͛1 nFx6k֬)T⭷z^jJCr6j;w/WGIt"'ZE^ ̙3KM#ue 3fOKc1DHtu0=x=Hq1V,-p.;s]?EQHR#?nm'H4M>=Xp 0i<z"0ȶf:4$6Յ{C`7}뭷4EKk]ef&,7669+[Z95p.;+^ ˴D"qlX&'G :BT|B/\}p'Ic̗`n@[߲݌3&zO:1 8x  \,o](҈غ΢[nNR" $M: 0{)`Htt-oY'S<5GAEJ$7Dt9n-߈)XJ茁H^iE8bqt02[GE7Qb.,Ĝ^nWx7f0f/;n͆~CAQE-,p8̅As/áq|]o|Vk)*[E~G6e<`ezoC"2"V1эYލɧ^KRD\E ">'&~06"2سkz4$0n#  A؀[ؾpw68DZC"U'E?FPy{]g4探{_1}4d!bak>bH;G(Jh:n'psN"ǨbtM75kFIt!n\`1B_;]ڞJi["K2p?wVr(Frvo} 1xP$ݤIOIYqTJ~ |9b1{ sld[XLx1؄)1) ebܗc=NO~xX<]-]Sʐn@^nG8#}$WQ`H4[hnX^"`-w-܈Dl=Y{ж*\.*=|H.B8+JTֳ-#޿p@yYO~xX`uk⽌''"9|yH ѱX "DNE',.(=Z۶Ly_V?A"$xd@C޴aP:nŻjfzPfhBS0r6t$͋ =5$$5)Jdg[K0Ɉ_k=-ˑ,X!5 x, ItDuCg6toI&b2x۽qˌɍ^(fdm׏ !'w<{N,dwoKe8X@kpu;MY<}lPϟT"Np@KR|GwRqNpeEUey.`?~'ۺ;Y.xuMpVI\䊹{zS8S]`~E%c`@M9h\ pUEw`FOtbwЧHLjÄ(gWH*?&#k͈#OYwa'U )K.^Sl,۳kӞn)c0ez6StVK7C|ڜ ܆R|@flDBljH,A>mv)ǁ'股)O%hCkcc6ѯx8-qVӂ>y9]es*K)dTE7Osj; ~TRֻ[D|[L/[ sPQݿv |28 ŀZWx#&m-Kqe,ߌ/54pCH@(r'~,Dkwlc"uͼגZtYCsKF\tM/g-mFVP9z$+<.>rh3<q_KRvl}ܔ`N-4S K]VWQj}H?:WrĞ3\ nQͼ߷agn`hKcvn>[!iqV0)`p2tge{c,n潾ٱQlЖ$G{nY oisMQ0I:bR#tdD7w=aؼ_җTBE7|8\u+JIh>aiw+ԣDTE7s2zü:M<5kM93MErYyvz޾4ՒVnTs>mӡ(V6O1ޘn 3Xv(Q9yD"1?^¿5H7EG[8qF {G À!@d}{Afޒ޿ sLYߏbHq^Tt.>3WR|ס o/47ՀYMeWCqXا40 OWU l*݌(6G*tr>W8Y ŝ=;/| I(1O>qȬ<Ǜ4R&#ShBBR'Fڲ\5+8ge}:#vJeyv9erXd5tMY{5^#KkJ ><ݥ(C†Z{1v]ʐ"޺>Hf? 3 z e9e$71SQ-W}ڴ"Xjw)J#iV{pN+8J">zwd-`U5TeD"kr3v魋cx q)024xC%%][z"oEFn;ldj]uԊ)(]%2@2Q8Z)%~.JsF䘯>:0$/j=O/[u}n[ڌCzð2b2 [Idy Ȭ+ ka$++q]%R<6cBcU:$d&Ay?{*<1eNt2_9IѰn&Fδx#߁-mFa//u>Z$`~Y{7 Dм[DOt@Ջq6Ds(hy?*| i|NHr3NV{?9a_j"ڙwl'ODSWsp?>\0sG[.o9{ )#pSㆬK6c[&dBg<4+he UUS$%dz:j[qZU;Jh^dߧ@>2Xpø 1Q8ɩ=]SUtcbUZCﴴ@QqhjVywo4U`Oݐ4HXCt]p35*t@(J xim: zŚAc5ܸ_qsأD"AHƭLփ,v'tK;dEͬAu { [lw"98#|έ%S"T?'j$Y /f]\CV:W޹ o"p]{'ŦBجjǶθ7-(f)¥0OZC{`oKǖg,^'K7+FPU7LٙO\8mQYc KFڨm~G3y% }o)=)ہ7,z4Eyx]Ekkh.$FxcJ7($+f"z8ֻI `i{nkzr)-%3صb ]q7'>&8X' ^.7HE;z3Lqo;|f)d]$)[:]tbc42,Cd < 0X8lyV0&dmj;)xB-u7A|_n{-fzVnHl=b/O!Y.iS C܏x34^ Wރjd/2-I$v~o܋ŭEk'#eY l]]&q*"ق|-pwc Q+zmos~ ;cpL`/u8}]щs + Ll)wr~tXfc n,,ummmP 1hp&pk,,?qc\KWn2 ogI1vսΛ)x¿a(ߤ1no0эǏD.71LUowS[pZޥHMk/=՜loo{ͫj,]t2 |no.2b|`%|X$- D˜s $hT/k5RTdHx >7.Ǐ_c9frDD7M|𫪭VB^Bgy5+*[{M~^AsFQqxGj;7 ?q8=Ova' ²-ݢQtXdɤ>{CMoFK+xiH% H?m $"LEoc6ֳz1zv=z1 b$$o=E‰Ǚ}]aw|WjC=ʇz}cu0Wwf蚬AD7^:;;/8qbgH߱Y˘@+Kp x{vϢ-ǽ{5{7]- dw]y7H!ZFd격Ͷf{99y'o|>0;"!`@B̲I{|e"q[P8]ޫ?$n;qo>;I2# RM2eEc:0dn5㨝sԾC\-is_ʻ1D"q>EQE$!k%tEXtdate:create2013-08-13T07:50:42+02:00Q6%tEXtdate:modify2013-08-13T07:50:42+02:00 kUEIENDB`Nuitka-0.6.19.1/doc/images/Nuitka-Logo-Symbol.png0000600000372100037210000001054414166627112026407 0ustar nuitka-buildslavenuitka-buildslave00000000000000PNG  IHDRB,gAMA asRGB cHRMz&u0`:pQ< pHYsHHFk>bKGDCYIDATxoovvƎq(%ĀJqm!yi@ڪ{ΙA˜8v[  `5R?^dOk]1׮6==ґgy?Jڅ_mS^nGcrTznӦM$y"7ޛ#Ea9`rKBH ǟ羋q~$O``8.3"r+.//fgg_3e7[9E\ZCqfDIݞ(o<488J7ƙ8EO)h{ c2;;읝}H]QQ$ #"Ç/UJMNNiDWB!b||m䠔 _khhX`{EN2E9 1d%ƁNӼ6(/ _SSS7>iPxhjjj"byv>QSD!w1)iwcWXlEA1=p7cCyoL!sQx1SJ(bd*L!MQw (xbB0(|Ɇ& 8YAљ(6ߙ`)hC! F9 6 h~lA{ m"PH2{ FKyC E2FPHT>8rJEq41$ }3zm8\\ˍF f RVCE!(p [-6 QDq~ͷl„4ZW ad72D+򉫄0B!}K) : IsFyQL(ypE!ۖ Zž=1 -a$5ʧ9jZ_0dJ6{ÞD|9F (Bk|(|סDvާ`)UQfCE z(a7SFPi 6H&j,}(0cw2q"c Ê eI֖"X% {i0& {.P[(b?V|[4Q$\("ʌaPBҭD1(4 E Vmh 1MOD!Q#ceư0P0Sd0 "`Q$+aXA9A8SGcEũ1PNe"v X( ] (î =BY_ۃ0Dl } Va!B!K)Hu8N0_⾫+0Ew(Z;+eUPpq;8(aE&vahPv_/\R}[0k !vRDsp]\s"!"_ hA*q=GpYD (TSP7]Znh R(< Ή̱}(lhj{G1ܿϖ}J6Q1-_^VvYۯ& v-pS8*+eQO-m-q qU;M hOgY 9n{& ) cE[>}(S+.P(B`EW8\m&˧(>8nM]DacEnj?mqnȨ|ZWypp2!߶kQ\>3r~Qt?>u ^AMʾo5Ti(IђM}c-?{8ne8D~cBD񯯬x}nW`Y&T) $.x64 ʜ*߀مmU06tF/T3] z Face vO|ߘ1DmGC-c|ZsPL&Ikz [?Ls b0^<ڇwIgCMWj8Mrgᴆ\}0C﫡kznX%% _?W>M=Qߴ>2 (p{ CY;s켧Ea;ߟߘ0;)bw٣ }EU~-gM"&Jj(x^Fc3iP3SadCEoat `hR(ZR(x3Ft"V/y T6,DATL6 HBEAl'(DKe73FY#L1Qp-at2 ! k󭋢|D($J(c0c"b f |BڅHe(~Q(cD8. .c( fC9S$^tE) Q.f{q `$ckTL(&wc1ƞ/J7cJY`OXn{:nأw;xƘGܒ-(@2<2::/ngs{y4pQE}c̳~;22RL0igϞulPW , 4rK'_uՅ8ϑ6>Yꟛms?<[2Ƽ#"Si`z%tEXtdate:create2013-08-08T10:34:23+02:00q#%tEXtdate:modify2013-08-08T10:34:23+02:00,:IENDB`Nuitka-0.6.19.1/doc/nuitka3-run.10000600000372100037210000005226014167275622023311 0ustar nuitka-buildslavenuitka-buildslave00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. .TH NUITKA-RUN "1" "January 2022" "nuitka-run 0.6.19.1" "User Commands" .SH NAME nuitka-run \- the Python compiler .SH SYNOPSIS .B nuitka-run [\fI\,options\/\fR] \fI\,main_module.py\/\fR .SH OPTIONS .TP \fB\-\-version\fR show program's version number and exit .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-\-module\fR Create an extension module executable instead of a program. Defaults to off. .TP \fB\-\-standalone\fR Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "\-\- follow\-imports". You may also want to use "\-\-pythonflag=no_site" to avoid the "site.py" module, which can save a lot of code dependencies. Defaults to off. .TP \fB\-\-onefile\fR On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to off. .TP \fB\-\-python\-debug\fR Use debug version or not. Default uses what you are using to run Nuitka, most likely a non\-debug version. .TP \fB\-\-python\-flag\fR=\fI\,FLAG\/\fR Python flags to use. Default is what you are using to run Nuitka, this enforces a specific mode. These are options that also exist to standard Python executable. Currently supported: "\-S" (alias "no_site"), "static_hashes" (do not use hash randomization), "no_warnings" (do not give Python runtime warnings), "\-O" (alias "no_asserts"), "no_docstrings" (do not use docstrings), and "\-m". Default empty. .TP \fB\-\-python\-for\-scons\fR=\fI\,PATH\/\fR If using Python3.3 or Python3.4, provide the path of a Python binary to use for Scons. Otherwise Nuitka can use what you run Nuitka with or a "scons" binary that is found in PATH, or a Python installation from Windows registry. .TP \fB\-\-warn\-implicit\-exceptions\fR Enable warnings for implicit exceptions detected at compile time. .TP \fB\-\-warn\-unusual\-code\fR Enable warnings for unusual code detected at compile time. .TP \fB\-\-assume\-yes\-for\-downloads\fR Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "" is used. For compatibility reasons, the "__file__" value will always have ".py" suffix independent of what it really is. .IP Output choices: .TP \fB\-o\fR FILENAME Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '' on this platform. \&.bin .TP \fB\-\-output\-dir\fR=\fI\,DIRECTORY\/\fR Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. .TP \fB\-\-remove\-output\fR Removes the build directory after producing the module or exe file. Defaults to off. .TP \fB\-\-no\-pyi\-file\fR Do not create a ".pyi" file for extension modules created by Nuitka. This is used to detect implicit imports. Defaults to off. .IP Debug features: .TP \fB\-\-debug\fR Executing all self checks possible to find errors in Nuitka, do not use for production. Defaults to off. .TP \fB\-\-unstripped\fR Keep debug info in the resulting object file for better debugger interaction. Defaults to off. .TP \fB\-\-profile\fR Enable vmprof based profiling of time spent. Not working currently. Defaults to off. .TP \fB\-\-internal\-graph\fR Create graph of optimization process internals, do not use for whole programs, but only for small test cases. Defaults to off. .TP \fB\-\-trace\-execution\fR Traced execution output, output the line of code before executing it. Defaults to off. .TP \fB\-\-recompile\-c\-only\fR This is not incremental compilation, but for Nuitka development only. Takes existing files and simply compile them as C again. Allows compiling edited C files for quick debugging changes to the generated source, e.g. to see if code is passed by, values output, etc, Defaults to off. Depends on compiling Python source to determine which files it should look at. .TP \fB\-\-generate\-c\-only\fR Generate only C source code, and do not compile it to binary or module. This is for debugging and code coverage analysis that doesn't waste CPU. Defaults to off. Do not think you can use this directly. .TP \fB\-\-experimental\fR=\fI\,FLAG\/\fR Use features declared as 'experimental'. May have no effect if no experimental features are present in the code. Uses secret tags (check source) per experimented feature. .TP \fB\-\-low\-memory\fR Attempt to use less memory, by forking less C compilation jobs and using options that use less memory. For use on embedded machines. Use this in case of out of memory problems. Defaults to off. .IP Backend C compiler choice: .TP \fB\-\-clang\fR Enforce the use of clang. On Windows this requires a working Visual Studio version to piggy back on. Defaults to off. .TP \fB\-\-mingw64\fR Enforce the use of MinGW64 on Windows. Defaults to off. .TP \fB\-\-msvc\fR=\fI\,MSVC_VERSION\/\fR Enforce the use of specific MSVC version on Windows. Allowed values are e.g. "14.2" (MSVC 2019), specify an illegal value for a list of installed compilers, or use "latest". Notice that only latest MSVC is really supported, and you can use "latest" to enforce that. Defaults to MSVC on Windows being used if installed, otherwise MinGW64. .TP \fB\-j\fR N, \fB\-\-jobs\fR=\fI\,N\/\fR Specify the allowed number of parallel C compiler jobs. Defaults to the system CPU count. .TP \fB\-\-lto\fR=\fI\,choice\/\fR Use link time optimizations (MSVC, gcc, clang). Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-static\-libpython\fR=\fI\,choice\/\fR Use static link library of Python. Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-disable\-ccache\fR Do not attempt to use ccache (gcc, clang, etc.) or clcache (MSVC, clangcl). .IP PGO compilation choices: .TP \fB\-\-pgo\fR Enables C level profile guided optimization (PGO), by executing a dedicated build first for a profiling run, and then using the result to feedback into the C compilation. Note: This is experimental and not working with standalone modes of Nuitka yet. Defaults to off. .TP \fB\-\-pgo\-args\fR=\fI\,PGO_ARGS\/\fR Arguments to be passed in case of profile guided optimization. These are passed to the special built executable during the PGO profiling run. Default empty. .TP \fB\-\-pgo\-executable\fR=\fI\,PGO_EXECUTABLE\/\fR Command to execute when collecting profile information. Use this only, if you need to launch it through a script that prepares it to run. Default use created program. .IP Tracing features: .TP \fB\-\-quiet\fR Disable all information outputs, but show warnings. Defaults to off. .TP \fB\-\-show\-scons\fR Operate Scons in non\-quiet mode, showing the executed commands. Defaults to off. .TP \fB\-\-show\-progress\fR Provide progress information and statistics. Defaults to off. .TP \fB\-\-no\-progressbar\fR Disable progress bar outputs (if tqdm is installed). Defaults to off. .TP \fB\-\-show\-memory\fR Provide memory information and statistics. Defaults to off. .TP \fB\-\-show\-modules\fR Provide information for included modules and DLLs Defaults to off. .TP \fB\-\-show\-modules\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-show\-modules\fR, should be a filename. Default is standard output. .TP \fB\-\-report\fR=\fI\,COMPILATION_REPORT_FILENAME\/\fR Report module inclusion in an XML output file. Default is off. .TP \fB\-\-verbose\fR Output details of actions taken, esp. in optimizations. Can become a lot. Defaults to off. .TP \fB\-\-verbose\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-verbose\fR, should be a filename. Default is standard output. .IP Windows specific controls: .TP \fB\-\-windows\-disable\-console\fR When compiling for Windows, disable the console window. Defaults to off. .TP \fB\-\-windows\-icon\-from\-ico\fR=\fI\,ICON_PATH\/\fR Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with # where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. .TP \fB\-\-windows\-icon\-from\-exe\fR=\fI\,ICON_EXE_PATH\/\fR Copy executable icons from this existing executable (Windows only). .TP \fB\-\-onefile\-windows\-splash\-screen\-image\fR=\fI\,SPLASH_SCREEN_IMAGE\/\fR When compiling for Windows and onefile, show this while loading the application. Defaults to off. .TP \fB\-\-windows\-uac\-admin\fR Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. .TP \fB\-\-windows\-uac\-uiaccess\fR Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. .TP \fB\-\-windows\-company\-name\fR=\fI\,WINDOWS_COMPANY_NAME\/\fR Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-name\fR=\fI\,WINDOWS_PRODUCT_NAME\/\fR Name of the product to use in Windows Version information. Defaults to base filename of the binary. .TP \fB\-\-windows\-file\-version\fR=\fI\,WINDOWS_FILE_VERSION\/\fR File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-version\fR=\fI\,WINDOWS_PRODUCT_VERSION\/\fR Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-file\-description\fR=\fI\,WINDOWS_FILE_DESCRIPTION\/\fR Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. .TP \fB\-\-windows\-onefile\-tempdir\-spec\fR=\fI\,ONEFILE_TEMPDIR_SPEC\/\fR Use this as a temporary folder. Defaults to \&'%TEMP%\eonefile_%PID%_%TIME%', i.e. system temporary directory. .TP \fB\-\-windows\-force\-stdout\-spec\fR=\fI\,WINDOWS_FORCE_STDOUT_SPEC\/\fR Force standard output of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.out.txt', i.e. file near your program. .TP \fB\-\-windows\-force\-stderr\-spec\fR=\fI\,WINDOWS_FORCE_STDERR_SPEC\/\fR Force standard error of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.err.txt', i.e. file near your program. .IP macOS specific controls: .TP \fB\-\-macos\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for binary to use. Can be given only one time. Defaults to Python icon if available. .TP \fB\-\-macos\-disable\-console\fR When compiling for macOS, disable the console window and create a GUI application. Defaults to off. .TP \fB\-\-macos\-create\-app\-bundle\fR When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console.Defaults to off. .TP \fB\-\-macos\-signed\-app\-name\fR=\fI\,MACOS_SIGNED_APP_NAME\/\fR Name of the application to use for macOS signing. Follow com.yourcompany.appname naming results for best results, as these have to be globally unique, and will grant protected API accesses. .TP \fB\-\-macos\-app\-name\fR=\fI\,MACOS_APP_NAME\/\fR Name of the product to use in macOS bundle information. Defaults to base filename of the binary. .TP \fB\-\-macos\-app\-version\fR=\fI\,MACOS_APP_VERSION\/\fR Product version to use in macOS bundle information. Defaults to 1.0 if not given. .IP Linux specific controls: .TP \fB\-\-linux\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for onefile binary to use. Can be given only one time. Defaults to Python icon if available. .IP Plugin control: .TP \fB\-\-enable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-enable\fR=\fI\,PLUGIN_NAME\/\fR Enabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-disable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-disable\fR=\fI\,PLUGIN_NAME\/\fR Disabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-plugin\-no\-detection\fR Plugins can detect if they might be used, and the you can disable the warning via "\-\-disable\-plugin=pluginthat\-warned", or you can use this option to disable the mechanism entirely, which also speeds up compilation slightly of course as this detection code is run in vain once you are certain of which plugins to use. Defaults to off. .TP \fB\-\-plugin\-list\fR Show list of all available plugins and exit. Defaults to off. .TP \fB\-\-user\-plugin\fR=\fI\,PATH\/\fR The file name of user plugin. Can be given multiple times. Default empty. .TP \fB\-\-persist\-source\-changes\fR Write source changes to original Python files. Use with care. May need permissions, best for use in a virtualenv to debug if plugin code changes work with standard Python or to benefit from bloat removal even with pure Python. Default False. .PP Commercial: None Python: 3.7.3 (default, Jan 22 2021, 20:04:44) Flavor: Debian Python Executable: \fI\,/usr/bin/python3\/\fP OS: Linux Arch: x86_64 Distribution: Debian 10.9 .SH EXAMPLES Compile a Python file "some_module.py" to a module "some_module.so": .IP \f(CW$ nuitka \-\-module some_module.py\fR .PP Compile a Python program "some_program.py" to an executable "some_program.exe": .IP \f(CW$ nuitka some_program.py\fR .PP Compile a Python program "some_program.py" and the package "some_package" it uses to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-to=some_package some_program.py\fR .PP Compile a Python program "some_program.py" and all the modules it uses to an executable "some_program.exe". Then execute it immediately when ready: .IP \f(CW$ nuitka \-\-run \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses (even standard library) to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-stdlib some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Keep the debug information, so valgrind, gdb, etc. work nicely. Note: This will *not* degrade performance: .IP \f(CW$ nuitka \-\-unstriped \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Also use the debug Python library, which does its own checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-python-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the plugins modules it loads at run time to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-directory=plugins_dir some_program.py\fR .PP Nuitka-0.6.19.1/doc/nuitka2-run.10000600000372100037210000005226214167275621023311 0ustar nuitka-buildslavenuitka-buildslave00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. .TH NUITKA-RUN "1" "January 2022" "nuitka-run 0.6.19.1" "User Commands" .SH NAME nuitka-run \- the Python compiler .SH SYNOPSIS .B nuitka-run [\fI\,options\/\fR] \fI\,main_module.py\/\fR .SH OPTIONS .TP \fB\-\-version\fR show program's version number and exit .TP \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP \fB\-\-module\fR Create an extension module executable instead of a program. Defaults to off. .TP \fB\-\-standalone\fR Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "\-\-follow\-imports". You may also want to use "\-\-python\-flag=no_site" to avoid the "site.py" module, which can save a lot of code dependencies. Defaults to off. .TP \fB\-\-onefile\fR On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to off. .TP \fB\-\-python\-debug\fR Use debug version or not. Default uses what you are using to run Nuitka, most likely a non\-debug version. .TP \fB\-\-python\-flag\fR=\fI\,FLAG\/\fR Python flags to use. Default is what you are using to run Nuitka, this enforces a specific mode. These are options that also exist to standard Python executable. Currently supported: "\-S" (alias "no_site"), "static_hashes" (do not use hash randomization), "no_warnings" (do not give Python runtime warnings), "\-O" (alias "no_asserts"), "no_docstrings" (do not use docstrings), and "\-m". Default empty. .TP \fB\-\-python\-for\-scons\fR=\fI\,PATH\/\fR If using Python3.3 or Python3.4, provide the path of a Python binary to use for Scons. Otherwise Nuitka can use what you run Nuitka with or a "scons" binary that is found in PATH, or a Python installation from Windows registry. .TP \fB\-\-warn\-implicit\-exceptions\fR Enable warnings for implicit exceptions detected at compile time. .TP \fB\-\-warn\-unusual\-code\fR Enable warnings for unusual code detected at compile time. .TP \fB\-\-assume\-yes\-for\-downloads\fR Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "" is used. For compatibility reasons, the "__file__" value will always have ".py" suffix independent of what it really is. .IP Output choices: .TP \fB\-o\fR FILENAME Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '' on this platform. \&.bin .TP \fB\-\-output\-dir\fR=\fI\,DIRECTORY\/\fR Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. .TP \fB\-\-remove\-output\fR Removes the build directory after producing the module or exe file. Defaults to off. .TP \fB\-\-no\-pyi\-file\fR Do not create a ".pyi" file for extension modules created by Nuitka. This is used to detect implicit imports. Defaults to off. .IP Debug features: .TP \fB\-\-debug\fR Executing all self checks possible to find errors in Nuitka, do not use for production. Defaults to off. .TP \fB\-\-unstripped\fR Keep debug info in the resulting object file for better debugger interaction. Defaults to off. .TP \fB\-\-profile\fR Enable vmprof based profiling of time spent. Not working currently. Defaults to off. .TP \fB\-\-internal\-graph\fR Create graph of optimization process internals, do not use for whole programs, but only for small test cases. Defaults to off. .TP \fB\-\-trace\-execution\fR Traced execution output, output the line of code before executing it. Defaults to off. .TP \fB\-\-recompile\-c\-only\fR This is not incremental compilation, but for Nuitka development only. Takes existing files and simply compile them as C again. Allows compiling edited C files for quick debugging changes to the generated source, e.g. to see if code is passed by, values output, etc, Defaults to off. Depends on compiling Python source to determine which files it should look at. .TP \fB\-\-generate\-c\-only\fR Generate only C source code, and do not compile it to binary or module. This is for debugging and code coverage analysis that doesn't waste CPU. Defaults to off. Do not think you can use this directly. .TP \fB\-\-experimental\fR=\fI\,FLAG\/\fR Use features declared as 'experimental'. May have no effect if no experimental features are present in the code. Uses secret tags (check source) per experimented feature. .TP \fB\-\-low\-memory\fR Attempt to use less memory, by forking less C compilation jobs and using options that use less memory. For use on embedded machines. Use this in case of out of memory problems. Defaults to off. .IP Backend C compiler choice: .TP \fB\-\-clang\fR Enforce the use of clang. On Windows this requires a working Visual Studio version to piggy back on. Defaults to off. .TP \fB\-\-mingw64\fR Enforce the use of MinGW64 on Windows. Defaults to off. .TP \fB\-\-msvc\fR=\fI\,MSVC_VERSION\/\fR Enforce the use of specific MSVC version on Windows. Allowed values are e.g. "14.2" (MSVC 2019), specify an illegal value for a list of installed compilers, or use "latest". Notice that only latest MSVC is really supported, and you can use "latest" to enforce that. Defaults to MSVC on Windows being used if installed, otherwise MinGW64. .TP \fB\-j\fR N, \fB\-\-jobs\fR=\fI\,N\/\fR Specify the allowed number of parallel C compiler jobs. Defaults to the system CPU count. .TP \fB\-\-lto\fR=\fI\,choice\/\fR Use link time optimizations (MSVC, gcc, clang). Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-static\-libpython\fR=\fI\,choice\/\fR Use static link library of Python. Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto". .TP \fB\-\-disable\-ccache\fR Do not attempt to use ccache (gcc, clang, etc.) or clcache (MSVC, clangcl). .IP PGO compilation choices: .TP \fB\-\-pgo\fR Enables C level profile guided optimization (PGO), by executing a dedicated build first for a profiling run, and then using the result to feedback into the C compilation. Note: This is experimental and not working with standalone modes of Nuitka yet. Defaults to off. .TP \fB\-\-pgo\-args\fR=\fI\,PGO_ARGS\/\fR Arguments to be passed in case of profile guided optimization. These are passed to the special built executable during the PGO profiling run. Default empty. .TP \fB\-\-pgo\-executable\fR=\fI\,PGO_EXECUTABLE\/\fR Command to execute when collecting profile information. Use this only, if you need to launch it through a script that prepares it to run. Default use created program. .IP Tracing features: .TP \fB\-\-quiet\fR Disable all information outputs, but show warnings. Defaults to off. .TP \fB\-\-show\-scons\fR Operate Scons in non\-quiet mode, showing the executed commands. Defaults to off. .TP \fB\-\-show\-progress\fR Provide progress information and statistics. Defaults to off. .TP \fB\-\-no\-progressbar\fR Disable progress bar outputs (if tqdm is installed). Defaults to off. .TP \fB\-\-show\-memory\fR Provide memory information and statistics. Defaults to off. .TP \fB\-\-show\-modules\fR Provide information for included modules and DLLs Defaults to off. .TP \fB\-\-show\-modules\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-show\-modules\fR, should be a filename. Default is standard output. .TP \fB\-\-report\fR=\fI\,COMPILATION_REPORT_FILENAME\/\fR Report module inclusion in an XML output file. Default is off. .TP \fB\-\-verbose\fR Output details of actions taken, esp. in optimizations. Can become a lot. Defaults to off. .TP \fB\-\-verbose\-output\fR=\fI\,PATH\/\fR Where to output \fB\-\-verbose\fR, should be a filename. Default is standard output. .IP Windows specific controls: .TP \fB\-\-windows\-disable\-console\fR When compiling for Windows, disable the console window. Defaults to off. .TP \fB\-\-windows\-icon\-from\-ico\fR=\fI\,ICON_PATH\/\fR Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with # where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. .TP \fB\-\-windows\-icon\-from\-exe\fR=\fI\,ICON_EXE_PATH\/\fR Copy executable icons from this existing executable (Windows only). .TP \fB\-\-onefile\-windows\-splash\-screen\-image\fR=\fI\,SPLASH_SCREEN_IMAGE\/\fR When compiling for Windows and onefile, show this while loading the application. Defaults to off. .TP \fB\-\-windows\-uac\-admin\fR Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. .TP \fB\-\-windows\-uac\-uiaccess\fR Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. .TP \fB\-\-windows\-company\-name\fR=\fI\,WINDOWS_COMPANY_NAME\/\fR Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-name\fR=\fI\,WINDOWS_PRODUCT_NAME\/\fR Name of the product to use in Windows Version information. Defaults to base filename of the binary. .TP \fB\-\-windows\-file\-version\fR=\fI\,WINDOWS_FILE_VERSION\/\fR File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-product\-version\fR=\fI\,WINDOWS_PRODUCT_VERSION\/\fR Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. .TP \fB\-\-windows\-file\-description\fR=\fI\,WINDOWS_FILE_DESCRIPTION\/\fR Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. .TP \fB\-\-windows\-onefile\-tempdir\-spec\fR=\fI\,ONEFILE_TEMPDIR_SPEC\/\fR Use this as a temporary folder. Defaults to \&'%TEMP%\eonefile_%PID%_%TIME%', i.e. system temporary directory. .TP \fB\-\-windows\-force\-stdout\-spec\fR=\fI\,WINDOWS_FORCE_STDOUT_SPEC\/\fR Force standard output of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.out.txt', i.e. file near your program. .TP \fB\-\-windows\-force\-stderr\-spec\fR=\fI\,WINDOWS_FORCE_STDERR_SPEC\/\fR Force standard error of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. \&'%PROGRAM%.err.txt', i.e. file near your program. .IP macOS specific controls: .TP \fB\-\-macos\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for binary to use. Can be given only one time. Defaults to Python icon if available. .TP \fB\-\-macos\-disable\-console\fR When compiling for macOS, disable the console window and create a GUI application. Defaults to off. .TP \fB\-\-macos\-create\-app\-bundle\fR When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console.Defaults to off. .TP \fB\-\-macos\-signed\-app\-name\fR=\fI\,MACOS_SIGNED_APP_NAME\/\fR Name of the application to use for macOS signing. Follow com.yourcompany.appname naming results for best results, as these have to be globally unique, and will grant protected API accesses. .TP \fB\-\-macos\-app\-name\fR=\fI\,MACOS_APP_NAME\/\fR Name of the product to use in macOS bundle information. Defaults to base filename of the binary. .TP \fB\-\-macos\-app\-version\fR=\fI\,MACOS_APP_VERSION\/\fR Product version to use in macOS bundle information. Defaults to 1.0 if not given. .IP Linux specific controls: .TP \fB\-\-linux\-onefile\-icon\fR=\fI\,ICON_PATH\/\fR Add executable icon for onefile binary to use. Can be given only one time. Defaults to Python icon if available. .IP Plugin control: .TP \fB\-\-enable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-enable\fR=\fI\,PLUGIN_NAME\/\fR Enabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-disable\-plugin\fR=\fI\,PLUGIN_NAME\/\fR, \fB\-\-plugin\-disable\fR=\fI\,PLUGIN_NAME\/\fR Disabled plugins. Must be plug\-in names. Use \fB\-\-pluginlist\fR to query the full list and exit. Default empty. .TP \fB\-\-plugin\-no\-detection\fR Plugins can detect if they might be used, and the you can disable the warning via "\-\-disable\-plugin=pluginthat\-warned", or you can use this option to disable the mechanism entirely, which also speeds up compilation slightly of course as this detection code is run in vain once you are certain of which plugins to use. Defaults to off. .TP \fB\-\-plugin\-list\fR Show list of all available plugins and exit. Defaults to off. .TP \fB\-\-user\-plugin\fR=\fI\,PATH\/\fR The file name of user plugin. Can be given multiple times. Default empty. .TP \fB\-\-persist\-source\-changes\fR Write source changes to original Python files. Use with care. May need permissions, best for use in a virtualenv to debug if plugin code changes work with standard Python or to benefit from bloat removal even with pure Python. Default False. .PP Commercial: None Python: 2.7.16 (default, Oct 10 2019, 22:02:15) Flavor: Debian Python Executable: \fI\,/usr/bin/python2\/\fP OS: Linux Arch: x86_64 Distribution: Debian 10.9 .SH EXAMPLES Compile a Python file "some_module.py" to a module "some_module.so": .IP \f(CW$ nuitka \-\-module some_module.py\fR .PP Compile a Python program "some_program.py" to an executable "some_program.exe": .IP \f(CW$ nuitka some_program.py\fR .PP Compile a Python program "some_program.py" and the package "some_package" it uses to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-to=some_package some_program.py\fR .PP Compile a Python program "some_program.py" and all the modules it uses to an executable "some_program.exe". Then execute it immediately when ready: .IP \f(CW$ nuitka \-\-run \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses (even standard library) to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-stdlib some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Keep the debug information, so valgrind, gdb, etc. work nicely. Note: This will *not* degrade performance: .IP \f(CW$ nuitka \-\-unstriped \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the modules it uses to an executable "some_program.exe". Perform all kinds of checks about correctness of the generated C and run\-time checks. Also use the debug Python library, which does its own checks. Note: This will degrade performance and should only be used to debug Nuitka: .IP \f(CW$ nuitka \-\-debug \-\-python-debug \-\-recurse\-all some_program.py\fR .PP Compile a Python program "some_program.py" and the plugins modules it loads at run time to an executable "some_program.exe": .IP \f(CW$ nuitka \-\-recurse\-all \-\-recurse\-directory=plugins_dir some_program.py\fR .PP Nuitka-0.6.19.1/nuitka/0000700000372100037210000000000014167275622021566 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/__main__.py0000600000372100037210000001150214166627112023653 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This is the main program of Nuitka, it checks the options and then translates one or more modules to a C source code using Python C/API in a "*.build" directory and then compiles that to either an executable or an extension module or package, that can contain all used modules too. """ # Note: This avoids imports at all costs, such that initial startup doesn't do more # than necessary, until re-execution has been decided. import os import sys def main(): # PyLint for Python3 thinks we import from ourselves if we really # import from package, pylint: disable=I0021,no-name-in-module # Also high complexity. # pylint: disable=too-many-branches,too-many-locals,too-many-statements if "NUITKA_BINARY_NAME" in os.environ: sys.argv[0] = os.environ["NUITKA_BINARY_NAME"] if "NUITKA_PYTHONPATH" in os.environ: # Restore the PYTHONPATH gained from the site module, that we chose not # to have imported. pylint: disable=eval-used sys.path = eval(os.environ["NUITKA_PYTHONPATH"]) del os.environ["NUITKA_PYTHONPATH"] else: # Remove path element added for being called via "__main__.py", this can # only lead to trouble, having e.g. a "distutils" in sys.path that comes # from "nuitka.distutils". sys.path = [ path_element for path_element in sys.path if os.path.dirname(os.path.abspath(__file__)) != path_element ] # We will run with the Python configuration as specified by the user, if it does # not match, we restart ourselves with matching configuration. needs_reexec = False if sys.flags.no_site == 0: needs_reexec = True # The hash randomization totally changes the created source code created, # changing it every single time Nuitka is run. This kills any attempt at # caching it, and comparing generated source code. While the created binary # actually may still use it, during compilation we don't want to. So lets # disable it. if os.environ.get("PYTHONHASHSEED", "-1") != "0": needs_reexec = True # In case we need to re-execute. if needs_reexec: from nuitka.utils.ReExecute import reExecuteNuitka # isort:skip # Does not return reExecuteNuitka(pgo_filename=None) # We don't care about deprecations in any version, and these are triggered # by run time calculations of "range" and others, while on python2.7 they # are disabled by default. import warnings warnings.simplefilter("ignore", DeprecationWarning) from nuitka import Options # isort:skip Options.parseArgs() Options.commentArgs() # Load plugins after we know, we don't execute again. from nuitka.plugins.Plugins import activatePlugins activatePlugins() if Options.isShowMemory(): from nuitka.utils import MemoryUsage MemoryUsage.startMemoryTracing() if "NUITKA_NAMESPACES" in os.environ: # Restore the detected name space packages, that were force loaded in # site.py, and will need a free pass later on. pylint: disable=eval-used from nuitka.importing.PreloadedPackages import setPreloadedPackagePaths setPreloadedPackagePaths(eval(os.environ["NUITKA_NAMESPACES"])) del os.environ["NUITKA_NAMESPACES"] if "NUITKA_PTH_IMPORTED" in os.environ: # Restore the packages that the ".pth" files asked to import. # pylint: disable=eval-used from nuitka.importing.PreloadedPackages import setPthImportedPackages setPthImportedPackages(eval(os.environ["NUITKA_PTH_IMPORTED"])) del os.environ["NUITKA_PTH_IMPORTED"] # Now the real main program of Nuitka can take over. from nuitka import MainControl # isort:skip MainControl.main() if Options.isShowMemory(): MemoryUsage.showMemoryTrace() if __name__ == "__main__": if "NUITKA_PACKAGE_HOME" in os.environ: sys.path.insert(0, os.environ["NUITKA_PACKAGE_HOME"]) import nuitka # just to have it loaded from there, pylint: disable=unused-import del sys.path[0] main() Nuitka-0.6.19.1/nuitka/specs/0000700000372100037210000000000014167275622022703 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/specs/BuiltinStrOperationSpecs.py0000600000372100037210000001051314166627112030227 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Str operation specs. """ from .BuiltinParameterSpecs import ( BuiltinParameterSpec, BuiltinParameterSpecNoKeywords, ) class StrMethodSpecNoKeywords(BuiltinParameterSpecNoKeywords): __slots__ = () def __init__( self, name, arg_names=(), default_count=0, ): BuiltinParameterSpecNoKeywords.__init__( self, name="str." + name, arg_names=arg_names, default_count=default_count, list_star_arg=None, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ) class StrMethodSpec(BuiltinParameterSpec): __slots__ = () def __init__( self, name, arg_names=(), default_count=0, ): BuiltinParameterSpec.__init__( self, name="str." + name, arg_names=arg_names, default_count=default_count, list_star_arg=None, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ) str_join_spec = StrMethodSpecNoKeywords("join", arg_names=("iterable",)) str_partition_spec = StrMethodSpecNoKeywords("partition", arg_names=("sep",)) str_rpartition_spec = StrMethodSpecNoKeywords("rpartition", arg_names=("sep",)) str_strip_spec = StrMethodSpecNoKeywords("strip", arg_names=("chars",), default_count=1) str_lstrip_spec = StrMethodSpecNoKeywords( "lstrip", arg_names=("chars",), default_count=1 ) str_rstrip_spec = StrMethodSpecNoKeywords( "rstrip", arg_names=("chars",), default_count=1 ) str_find_spec = StrMethodSpecNoKeywords( "find", arg_names=("sub", "start", "end"), default_count=2 ) str_rfind_spec = StrMethodSpecNoKeywords( "rfind", arg_names=("sub", "start", "end"), default_count=2 ) str_index_spec = StrMethodSpecNoKeywords( "index", arg_names=("sub", "start", "end"), default_count=2 ) str_rindex_spec = StrMethodSpecNoKeywords( "rindex", arg_names=("sub", "start", "end"), default_count=2 ) str_split_spec = StrMethodSpecNoKeywords( "split", arg_names=("sep", "maxsplit"), default_count=2 ) str_rsplit_spec = StrMethodSpecNoKeywords( "rsplit", arg_names=("sep", "maxsplit"), default_count=2 ) str_startswith_spec = StrMethodSpecNoKeywords( "startswith", arg_names=("prefix", "start", "end"), default_count=2 ) str_endswith_spec = StrMethodSpecNoKeywords( "endswith", arg_names=("suffix", "start", "end"), default_count=2 ) str_replace_spec = StrMethodSpecNoKeywords( "replace", arg_names=("old", "new", "count"), default_count=1 ) str_capitalize_spec = StrMethodSpecNoKeywords("capitalize", arg_names=()) str_upper_spec = StrMethodSpecNoKeywords("upper", arg_names=()) str_lower_spec = StrMethodSpecNoKeywords("lower", arg_names=()) str_swapcase_spec = StrMethodSpecNoKeywords("swapcase", arg_names=()) str_title_spec = StrMethodSpecNoKeywords("title", arg_names=()) str_isalnum_spec = StrMethodSpecNoKeywords("isalnum", arg_names=()) str_isalpha_spec = StrMethodSpecNoKeywords("isalpha", arg_names=()) str_isdigit_spec = StrMethodSpecNoKeywords("isdigit", arg_names=()) str_islower_spec = StrMethodSpecNoKeywords("islower", arg_names=()) str_isupper_spec = StrMethodSpecNoKeywords("isupper", arg_names=()) str_isspace_spec = StrMethodSpecNoKeywords("isspace", arg_names=()) str_istitle_spec = StrMethodSpecNoKeywords("istitle", arg_names=()) str_encode_spec = StrMethodSpec( "encode", arg_names=("encoding", "errors"), default_count=2 ) # Python2 only, Python3 this is in bytes str_decode_spec = StrMethodSpec( "decode", arg_names=("encoding", "errors"), default_count=2 ) Nuitka-0.6.19.1/nuitka/specs/BuiltinUnicodeOperationSpecs.py0000600000372100037210000001070614166627112031051 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Unicode operation specs, Python2 only. """ from .BuiltinParameterSpecs import ( BuiltinParameterSpec, BuiltinParameterSpecNoKeywords, ) class UnicodeMethodSpecNoKeywords(BuiltinParameterSpecNoKeywords): __slots__ = () def __init__( self, name, arg_names=(), default_count=0, ): BuiltinParameterSpecNoKeywords.__init__( self, name="unicode." + name, arg_names=arg_names, default_count=default_count, list_star_arg=None, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ) class UnicodeMethodSpec(BuiltinParameterSpec): __slots__ = () def __init__( self, name, arg_names=(), default_count=0, ): BuiltinParameterSpec.__init__( self, name="unicode." + name, arg_names=arg_names, default_count=default_count, list_star_arg=None, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ) unicode_join_spec = UnicodeMethodSpecNoKeywords("join", arg_names=("iterable",)) unicode_partition_spec = UnicodeMethodSpecNoKeywords("partition", arg_names=("sep",)) unicode_rpartition_spec = UnicodeMethodSpecNoKeywords("rpartition", arg_names=("sep",)) unicode_strip_spec = UnicodeMethodSpecNoKeywords( "strip", arg_names=("chars",), default_count=1 ) unicode_lstrip_spec = UnicodeMethodSpecNoKeywords( "lstrip", arg_names=("chars",), default_count=1 ) unicode_rstrip_spec = UnicodeMethodSpecNoKeywords( "rstrip", arg_names=("chars",), default_count=1 ) unicode_find_spec = UnicodeMethodSpecNoKeywords( "find", arg_names=("sub", "start", "end"), default_count=2 ) unicode_rfind_spec = UnicodeMethodSpecNoKeywords( "rfind", arg_names=("sub", "start", "end"), default_count=2 ) unicode_index_spec = UnicodeMethodSpecNoKeywords( "index", arg_names=("sub", "start", "end"), default_count=2 ) unicode_rindex_spec = UnicodeMethodSpecNoKeywords( "rindex", arg_names=("sub", "start", "end"), default_count=2 ) unicode_split_spec = UnicodeMethodSpecNoKeywords( "split", arg_names=("sep", "maxsplit"), default_count=2 ) unicode_rsplit_spec = UnicodeMethodSpecNoKeywords( "rsplit", arg_names=("sep", "maxsplit"), default_count=2 ) unicode_startswith_spec = UnicodeMethodSpecNoKeywords( "startswith", arg_names=("prefix", "start", "end"), default_count=2 ) unicode_endswith_spec = UnicodeMethodSpecNoKeywords( "endswith", arg_names=("suffix", "start", "end"), default_count=2 ) unicode_replace_spec = UnicodeMethodSpecNoKeywords( "replace", arg_names=("old", "new", "count"), default_count=1 ) unicode_capitalize_spec = UnicodeMethodSpecNoKeywords("capitalize", arg_names=()) unicode_upper_spec = UnicodeMethodSpecNoKeywords("upper", arg_names=()) unicode_lower_spec = UnicodeMethodSpecNoKeywords("lower", arg_names=()) unicode_swapcase_spec = UnicodeMethodSpecNoKeywords("swapcase", arg_names=()) unicode_title_spec = UnicodeMethodSpecNoKeywords("title", arg_names=()) unicode_isalnum_spec = UnicodeMethodSpecNoKeywords("isalnum", arg_names=()) unicode_isalpha_spec = UnicodeMethodSpecNoKeywords("isalpha", arg_names=()) unicode_isdigit_spec = UnicodeMethodSpecNoKeywords("isdigit", arg_names=()) unicode_islower_spec = UnicodeMethodSpecNoKeywords("islower", arg_names=()) unicode_isupper_spec = UnicodeMethodSpecNoKeywords("isupper", arg_names=()) unicode_isspace_spec = UnicodeMethodSpecNoKeywords("isspace", arg_names=()) unicode_istitle_spec = UnicodeMethodSpecNoKeywords("istitle", arg_names=()) unicode_encode_spec = UnicodeMethodSpec( "encode", arg_names=("encoding", "errors"), default_count=2 ) Nuitka-0.6.19.1/nuitka/specs/ParameterSpecs.py0000600000372100037210000004415714166627112026202 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module maintains the parameter specification classes. These are used for function, lambdas, generators. They are also a factory for the respective variable objects. One of the difficulty of Python and its parameter parsing is that they are allowed to be nested like this: (a,b), c Much like in assignments, which are very similar to parameters, except that parameters may also be assigned from a dictionary, they are no less flexible. """ from nuitka import Variables from nuitka.PythonVersions import python_version from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) class TooManyArguments(Exception): def __init__(self, real_exception): Exception.__init__(self) self.real_exception = real_exception def getRealException(self): return self.real_exception class ParameterSpec(object): # These got many attributes, in part duplicating name and instance of # variables, pylint: disable=too-many-instance-attributes __slots__ = ( "name", "owner", "normal_args", "normal_variables", "list_star_arg", "is_list_star_arg_single", "dict_star_arg", "list_star_variable", "dict_star_variable", "default_count", "kw_only_args", "kw_only_variables", "pos_only_args", "pos_only_variables", ) @counted_init def __init__( self, ps_name, ps_normal_args, ps_pos_only_args, ps_kw_only_args, ps_list_star_arg, ps_dict_star_arg, ps_default_count, ps_is_list_star_arg_single=False, ): if type(ps_normal_args) is str: if ps_normal_args == "": ps_normal_args = () else: ps_normal_args = ps_normal_args.split(",") if type(ps_kw_only_args) is str: if ps_kw_only_args == "": ps_kw_only_args = () else: ps_kw_only_args = ps_kw_only_args.split(",") assert None not in ps_normal_args self.owner = None self.name = ps_name self.normal_args = tuple(ps_normal_args) self.normal_variables = None assert ( ps_list_star_arg is None or type(ps_list_star_arg) is str ), ps_list_star_arg assert ( ps_dict_star_arg is None or type(ps_dict_star_arg) is str ), ps_dict_star_arg assert type(ps_is_list_star_arg_single) is bool, ps_is_list_star_arg_single self.list_star_arg = ps_list_star_arg if ps_list_star_arg else None self.is_list_star_arg_single = ps_is_list_star_arg_single self.dict_star_arg = ps_dict_star_arg if ps_dict_star_arg else None self.list_star_variable = None self.dict_star_variable = None self.default_count = ps_default_count self.kw_only_args = tuple(ps_kw_only_args) self.kw_only_variables = None self.pos_only_args = tuple(ps_pos_only_args) self.pos_only_variables = None if isCountingInstances(): __del__ = counted_del() def makeClone(self): return ParameterSpec( ps_name=self.name, ps_normal_args=self.normal_args, ps_pos_only_args=self.pos_only_args, ps_kw_only_args=self.kw_only_args, ps_list_star_arg=self.list_star_arg, ps_dict_star_arg=self.dict_star_arg, ps_default_count=self.default_count, ) def getDetails(self): return { "ps_name": self.name, "ps_normal_args": ",".join(self.normal_args), "ps_pos_only_args": self.pos_only_args, "ps_kw_only_args": ",".join(self.kw_only_args), "ps_list_star_arg": self.list_star_arg if self.list_star_arg is not None else "", "ps_dict_star_arg": self.dict_star_arg if self.dict_star_arg is not None else "", "ps_default_count": self.default_count, } def checkParametersValid(self): arg_names = self.getParameterNames() # Check for duplicate arguments, could happen. for arg_name in arg_names: if arg_names.count(arg_name) != 1: return "duplicate argument '%s' in function definition" % arg_name return None def __repr__(self): parts = [str(normal_arg) for normal_arg in self.pos_only_args] if parts: parts.append("/") parts += [str(normal_arg) for normal_arg in self.normal_args] if self.list_star_arg is not None: parts.append("*%s" % self.list_star_arg) if self.dict_star_variable is not None: parts.append("**%s" % self.dict_star_variable) if parts: return "" % ",".join(parts) else: return "" def setOwner(self, owner): if self.owner is not None: return self.owner = owner self.normal_variables = [] for normal_arg in self.normal_args: if type(normal_arg) is str: normal_variable = Variables.ParameterVariable( owner=self.owner, parameter_name=normal_arg ) else: assert False, normal_arg self.normal_variables.append(normal_variable) if self.list_star_arg: self.list_star_variable = Variables.ParameterVariable( owner=owner, parameter_name=self.list_star_arg ) else: self.list_star_variable = None if self.dict_star_arg: self.dict_star_variable = Variables.ParameterVariable( owner=owner, parameter_name=self.dict_star_arg ) else: self.dict_star_variable = None self.kw_only_variables = [ Variables.ParameterVariable(owner=self.owner, parameter_name=kw_only_arg) for kw_only_arg in self.kw_only_args ] self.pos_only_variables = [ Variables.ParameterVariable(owner=self.owner, parameter_name=pos_only_arg) for pos_only_arg in self.pos_only_args ] def getDefaultCount(self): return self.default_count def hasDefaultParameters(self): return self.getDefaultCount() > 0 def getTopLevelVariables(self): return self.pos_only_variables + self.normal_variables + self.kw_only_variables def getAllVariables(self): result = list(self.pos_only_variables) result += self.normal_variables result += self.kw_only_variables if self.list_star_variable is not None: result.append(self.list_star_variable) if self.dict_star_variable is not None: result.append(self.dict_star_variable) return result def getParameterNames(self): result = list(self.pos_only_args + self.normal_args) result += self.kw_only_args if self.list_star_arg is not None: result.append(self.list_star_arg) if self.dict_star_arg is not None: result.append(self.dict_star_arg) return result def getStarListArgumentName(self): return self.list_star_arg def isStarListSingleArg(self): return self.is_list_star_arg_single def getListStarArgVariable(self): return self.list_star_variable def getStarDictArgumentName(self): return self.dict_star_arg def getDictStarArgVariable(self): return self.dict_star_variable def getKwOnlyVariables(self): return self.kw_only_variables def allowsKeywords(self): # Abstract method, pylint: disable=no-self-use return True def getKeywordRefusalText(self): return "%s() takes no keyword arguments" % self.name def getArgumentNames(self): return self.pos_only_args + self.normal_args def getArgumentCount(self): return len(self.normal_args) + len(self.pos_only_args) def getKwOnlyParameterNames(self): return self.kw_only_args def getKwOnlyParameterCount(self): return len(self.kw_only_args) def getPosOnlyParameterCount(self): return len(self.pos_only_args) def matchCall( func_name, args, kw_only_args, star_list_arg, star_list_single_arg, star_dict_arg, num_defaults, num_posonly, positional, pairs, improved=False, ): """Match a call arguments to a signature. Args: func_name - Name of the function being matched, used to construct exception texts. args - normal argument names kw_only_args - keyword only argument names (Python3) star_list_arg - name of star list argument if any star_dict_arg - name of star dict argument if any num_defaults - amount of arguments that have default values num_posonly - amount of arguments that must be given by position positional - tuple of argument values given for simulated call pairs - tuple of pairs arg argument name and argument values improved - (bool) should we give better errors than CPython or not. Returns: Dictionary of argument name to value mappings Notes: Based loosely on "inspect.getcallargs" with corrections. """ # This is of incredible code complexity, but there really is no other way to # express this with less statements, branches, or variables. # pylint: disable=too-many-branches,too-many-locals,too-many-statements assert type(positional) is tuple, positional assert type(pairs) in (tuple, list), pairs # Make a copy, we are going to modify it. pairs = list(pairs) result = {} assigned_tuple_params = [] def assign(arg, value): if type(arg) is str: # Normal case: result[arg] = value else: # Tuple argument case: assigned_tuple_params.append(arg) value = iter(value.getIterationValues()) for i, subarg in enumerate(arg): try: subvalue = next(value) except StopIteration: raise TooManyArguments( ValueError( "need more than %d %s to unpack" % (i, "values" if i > 1 else "value") ) ) # Recurse into tuple argument values, could be more tuples. assign(subarg, subvalue) # Check that not too many values we provided. try: next(value) except StopIteration: pass else: raise TooManyArguments(ValueError("too many values to unpack")) def isAssigned(arg): if type(arg) is str: return arg in result return arg in assigned_tuple_params num_pos = len(positional) num_total = num_pos + len(pairs) num_args = len(args) for arg, value in zip(args, positional): assign(arg, value) # Python3 does this check earlier. if python_version >= 0x300 and not star_dict_arg: for pair in pairs: try: arg_index = (args + kw_only_args).index(pair[0]) except ValueError: if improved or python_version >= 0x370: message = "'%s' is an invalid keyword argument for %s()" % ( pair[0], func_name, ) else: message = ( "'%s' is an invalid keyword argument for this function" % pair[0] ) raise TooManyArguments(TypeError(message)) else: if arg_index < num_posonly: message = "'%s' is an invalid keyword argument for %s()" % ( pair[0], func_name, ) raise TooManyArguments(TypeError(message)) if star_list_arg: if num_pos > num_args: value = positional[-(num_pos - num_args) :] assign(star_list_arg, value) if star_list_single_arg: if len(value) > 1: raise TooManyArguments( TypeError( "%s expected at most 1 arguments, got %d" % (func_name, len(value)) ) ) else: assign(star_list_arg, ()) elif 0 < num_args < num_total: # Special case for no default values. if num_defaults == 0: # Special cases text for one argument. if num_args == 1: raise TooManyArguments( TypeError( "%s() takes exactly one argument (%d given)" % (func_name, num_total) ) ) raise TooManyArguments( TypeError( "%s expected %d arguments, got %d" % (func_name, num_args, num_total) ) ) raise TooManyArguments( TypeError( "%s() takes at most %d %s (%d given)" % ( func_name, num_args, "argument" if num_args == 1 else "arguments", num_total, ) ) ) elif num_args == 0 and num_total: if star_dict_arg: if num_pos: # Could use num_pos, but Python also uses num_total. raise TooManyArguments( TypeError( "%s() takes exactly 0 arguments (%d given)" % (func_name, num_total) ) ) else: raise TooManyArguments( TypeError("%s() takes no arguments (%d given)" % (func_name, num_total)) ) named_argument_names = [pair[0] for pair in pairs] for arg in args + kw_only_args: if type(arg) is str and arg in named_argument_names: if isAssigned(arg): raise TooManyArguments( TypeError( "%s() got multiple values for keyword argument '%s'" % (func_name, arg) ) ) new_pairs = [] for pair in pairs: if arg == pair[0]: assign(arg, pair[1]) else: new_pairs.append(pair) assert len(new_pairs) == len(pairs) - 1 pairs = new_pairs # Fill in any missing values with the None to indicate "default". if num_defaults > 0: for arg in (kw_only_args + args)[-num_defaults:]: if not isAssigned(arg): assign(arg, None) if star_dict_arg: assign(star_dict_arg, pairs) elif pairs: unexpected = next(iter(dict(pairs))) if improved: message = "%s() got an unexpected keyword argument '%s'" % ( func_name, unexpected, ) else: message = ( "'%s' is an invalid keyword argument for this function" % unexpected ) raise TooManyArguments(TypeError(message)) unassigned = num_args - len([arg for arg in args if isAssigned(arg)]) if unassigned: num_required = num_args - num_defaults # Special case required arguments. if num_required > 0 or improved: if num_defaults == 0 and num_args != 1: raise TooManyArguments( TypeError( "%s expected %d arguments, got %d" % (func_name, num_args, num_total) ) ) if num_required == 1: arg_desc = "1 argument" if python_version < 0x350 else "one argument" else: arg_desc = "%d arguments" % num_required raise TooManyArguments( TypeError( "%s() takes %s %s (%d given)" % ( func_name, "at least" if num_defaults > 0 else "exactly", arg_desc, num_total, ) ) ) raise TooManyArguments( TypeError( "%s expected %s%s, got %d" % ( func_name, ("at least " if python_version < 0x300 else "") if num_defaults > 0 else "exactly ", "%d arguments" % num_required, num_total, ) ) ) unassigned = len(kw_only_args) - len( [arg for arg in kw_only_args if isAssigned(arg)] ) if unassigned: raise TooManyArguments( TypeError( "%s missing %d required keyword-only argument%s: %s" % ( func_name, unassigned, "s" if unassigned > 1 else "", " and ".join( "'%s'" % [arg.getName() for arg in kw_only_args if not isAssigned(arg)] ), ) ) ) return result Nuitka-0.6.19.1/nuitka/specs/BuiltinParameterSpecs.py0000600000372100037210000005454014166627112027526 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Optimizations of built-ins to built-in calls. """ import math from nuitka.__past__ import builtins from nuitka.PythonVersions import python_version from nuitka.Tracing import optimization_logger from .ParameterSpecs import ParameterSpec, TooManyArguments, matchCall class BuiltinParameterSpec(ParameterSpec): __slots__ = ("builtin",) def __init__( self, name, arg_names, default_count, list_star_arg=None, is_list_star_arg_single=False, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ): ParameterSpec.__init__( self, ps_name=name, ps_normal_args=arg_names, ps_list_star_arg=list_star_arg, ps_is_list_star_arg_single=is_list_star_arg_single, ps_dict_star_arg=dict_star_arg, ps_default_count=default_count, ps_pos_only_args=pos_only_args, ps_kw_only_args=kw_only_args, ) self.builtin = getattr(builtins, name, None) assert default_count <= len(arg_names) + len(kw_only_args) + len(pos_only_args) def __repr__(self): return "" % self.name def getName(self): return self.name def isCompileTimeComputable(self, values): # By default, we make this dependent on the ability to compute the # arguments, which is of course a good start for most cases, so this # is for overloads, pylint: disable=no-self-use for value in values: if value is not None and not value.isCompileTimeConstant(): return False return True def simulateCall(self, given_values): # Using star dict call for simulation and catch any exception as really # fatal, pylint: disable=broad-except,too-many-branches try: given_normal_args = given_values[: self.getArgumentCount()] if self.list_star_arg: given_list_star_args = given_values[self.getArgumentCount()] else: given_list_star_args = None if self.dict_star_arg: given_dict_star_args = given_values[-1] else: given_dict_star_args = None arg_dict = {} for arg_name, given_value in zip( self.getArgumentNames(), given_normal_args ): assert type(given_value) not in ( tuple, list, ), "do not like a tuple %s" % (given_value,) if given_value is not None: arg_dict[arg_name] = given_value.getCompileTimeConstant() if given_dict_star_args: for given_dict_star_arg in reversed(given_dict_star_args): arg_name = given_dict_star_arg.subnode_key.getCompileTimeConstant() arg_value = ( given_dict_star_arg.subnode_value.getCompileTimeConstant() ) arg_dict[arg_name] = arg_value arg_list = [] for arg_name in self.getArgumentNames(): if arg_name not in arg_dict: break arg_list.append(arg_dict[arg_name]) del arg_dict[arg_name] except Exception as e: optimization_logger.sysexit_exception("Fatal optimization problem", e) if given_list_star_args: return self.builtin( *( arg_list + list( value.getCompileTimeConstant() for value in given_list_star_args ) ), **arg_dict ) else: return self.builtin(*arg_list, **arg_dict) class BuiltinParameterSpecNoKeywords(BuiltinParameterSpec): __slots__ = () def allowsKeywords(self): return False def simulateCall(self, given_values): # Using star dict call for simulation and catch any exception as really fatal, # pylint: disable=broad-except try: if self.list_star_arg: given_list_star_arg = given_values[self.getArgumentCount()] else: given_list_star_arg = None arg_list = [] refuse_more = False for _arg_name, given_value in zip(self.getArgumentNames(), given_values): assert type(given_value) not in ( tuple, list, ), "do not like tuple %s" % (given_value,) if given_value is not None: if not refuse_more: arg_list.append(given_value.getCompileTimeConstant()) else: assert False else: refuse_more = True if given_list_star_arg is not None: arg_list += [ value.getCompileTimeConstant() for value in given_list_star_arg ] except Exception as e: optimization_logger.sysexit_exception("matching call", e) return self.builtin(*arg_list) class BuiltinParameterSpecExceptionsKwOnly(BuiltinParameterSpec): def __init__(self, exception_name, kw_only_args): BuiltinParameterSpec.__init__( self, name=exception_name, arg_names=(), default_count=len(kw_only_args), # For exceptions, they will be required. list_star_arg="args", kw_only_args=kw_only_args, ) class BuiltinParameterSpecExceptions(BuiltinParameterSpec): def __init__(self, exception_name): BuiltinParameterSpec.__init__( self, name=exception_name, arg_names=(), default_count=0, list_star_arg="args", ) def allowsKeywords(self): return False def getKeywordRefusalText(self): return "exceptions.%s does not take keyword arguments" % self.name def getCallableName(self): return "exceptions." + self.getName() def makeBuiltinExceptionParameterSpec(exception_name): """Factory function to create parameter spec for an exception from its name. Args: exception_name - (str) name of the built-in exception Returns: ParameterSpec that can be used to evaluate calls of these exceptions. """ if exception_name == "ImportError" and python_version >= 0x300: # This is currently the only known built-in exception that does it, but let's # be general, as surely that list is going to expand only. return BuiltinParameterSpecExceptionsKwOnly( exception_name=exception_name, kw_only_args=("name", "path") ) else: return BuiltinParameterSpecExceptions(exception_name=exception_name) class BuiltinParameterSpecPosArgs(BuiltinParameterSpec): def __init__( self, name, pos_only_args, arg_names, default_count, list_star_arg=None, dict_star_arg=None, ): BuiltinParameterSpec.__init__( self, name=name, arg_names=arg_names, default_count=default_count, pos_only_args=pos_only_args, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, ) if python_version < 0x370: builtin_int_spec = BuiltinParameterSpec("int", ("x", "base"), default_count=2) else: builtin_int_spec = BuiltinParameterSpecPosArgs( "int", ("x",), ("base",), default_count=2 ) # These builtins are only available for Python2 if python_version < 0x300: builtin_long_spec = BuiltinParameterSpec("long", ("x", "base"), default_count=2) builtin_execfile_spec = BuiltinParameterSpecNoKeywords( "execfile", ("filename", "globals", "locals"), default_count=2 ) builtin_unicode_p2_spec = BuiltinParameterSpec( "unicode", ("string", "encoding", "errors"), default_count=3 ) builtin_xrange_spec = BuiltinParameterSpecNoKeywords( "xrange" if python_version < 0x300 else "range", ("start", "stop", "step"), default_count=2, ) if python_version < 0x370: builtin_bool_spec = BuiltinParameterSpec("bool", ("x",), default_count=1) else: builtin_bool_spec = BuiltinParameterSpecNoKeywords("bool", ("x",), default_count=1) if python_version < 0x370: builtin_float_spec = BuiltinParameterSpec("float", ("x",), default_count=1) else: builtin_float_spec = BuiltinParameterSpecNoKeywords( "float", ("x",), default_count=1 ) builtin_complex_spec = BuiltinParameterSpec( "complex", ("real", "imag"), default_count=2 ) # This built-in have variable parameters for Python2/3 if python_version < 0x300: builtin_str_spec = BuiltinParameterSpec("str", ("object",), default_count=1) else: builtin_str_spec = BuiltinParameterSpec( "str", ("object", "encoding", "errors"), default_count=3 ) builtin_len_spec = BuiltinParameterSpecNoKeywords("len", ("object",), default_count=0) class BuiltinParameterSpecSinglePosArgStarDictArgs(BuiltinParameterSpec): def __init__(self, name): BuiltinParameterSpec.__init__( self, name=name, arg_names=(), default_count=0, list_star_arg="list_args", is_list_star_arg_single=True, dict_star_arg="kw_args", ) builtin_dict_spec = BuiltinParameterSpecSinglePosArgStarDictArgs("dict") builtin_any_spec = BuiltinParameterSpecNoKeywords("any", ("object",), default_count=0) builtin_abs_spec = BuiltinParameterSpecNoKeywords("abs", ("object",), default_count=0) builtin_all_spec = BuiltinParameterSpecNoKeywords("all", ("object",), default_count=0) if python_version < 0x370: builtin_tuple_spec = BuiltinParameterSpec("tuple", ("sequence",), default_count=1) builtin_list_spec = BuiltinParameterSpec("list", ("sequence",), default_count=1) else: builtin_tuple_spec = BuiltinParameterSpecNoKeywords( "tuple", ("sequence",), default_count=1 ) builtin_list_spec = BuiltinParameterSpecNoKeywords( "list", ("sequence",), default_count=1 ) builtin_set_spec = BuiltinParameterSpecNoKeywords("set", ("iterable",), default_count=1) builtin_frozenset_spec = BuiltinParameterSpecNoKeywords( "frozenset", ("iterable",), default_count=1 ) builtin_import_spec = BuiltinParameterSpec( "__import__", ("name", "globals", "locals", "fromlist", "level"), default_count=4 ) if python_version < 0x300: builtin_open_spec = BuiltinParameterSpec( "open", ("name", "mode", "buffering"), default_count=3 ) else: builtin_open_spec = BuiltinParameterSpec( "open", ( "file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", ), default_count=7, ) builtin_chr_spec = BuiltinParameterSpecNoKeywords("chr", ("i",), default_count=0) builtin_ord_spec = BuiltinParameterSpecNoKeywords("ord", ("c",), default_count=0) builtin_bin_spec = BuiltinParameterSpecNoKeywords("bin", ("number",), default_count=0) builtin_oct_spec = BuiltinParameterSpecNoKeywords("oct", ("number",), default_count=0) builtin_hex_spec = BuiltinParameterSpecNoKeywords("hex", ("number",), default_count=0) builtin_id_spec = BuiltinParameterSpecNoKeywords("id", ("object",), default_count=0) builtin_repr_spec = BuiltinParameterSpecNoKeywords("repr", ("object",), default_count=0) builtin_dir_spec = BuiltinParameterSpecNoKeywords("dir", ("object",), default_count=1) builtin_vars_spec = BuiltinParameterSpecNoKeywords("vars", ("object",), default_count=1) builtin_locals_spec = BuiltinParameterSpecNoKeywords("locals", (), default_count=0) builtin_globals_spec = BuiltinParameterSpecNoKeywords("globals", (), default_count=0) builtin_eval_spec = BuiltinParameterSpecNoKeywords( "eval", ("source", "globals", "locals"), 2 ) if python_version < 0x300: builtin_compile_spec = BuiltinParameterSpec( "compile", ("source", "filename", "mode", "flags", "dont_inherit"), default_count=2, ) else: builtin_compile_spec = BuiltinParameterSpec( "compile", ("source", "filename", "mode", "flags", "dont_inherit", "optimize"), default_count=3, ) if python_version >= 0x300: builtin_exec_spec = BuiltinParameterSpecNoKeywords( "exec", ("source", "globals", "locals"), default_count=2 ) # Note: Iter in fact names its first argument if the default applies # "collection", fixed up in a wrapper. builtin_iter_spec = BuiltinParameterSpecNoKeywords( "iter", ("callable", "sentinel"), default_count=1 ) builtin_next_spec = BuiltinParameterSpecNoKeywords( "next", ("iterator", "default"), default_count=1 ) # Note: type with 1 and type with 3 arguments are too different. builtin_type1_spec = BuiltinParameterSpecNoKeywords( "type", ("object",), default_count=0 ) builtin_type3_spec = BuiltinParameterSpecNoKeywords( "type", ("name", "bases", "dict"), default_count=0 ) builtin_super_spec = BuiltinParameterSpecNoKeywords( "super", ("type", "object"), default_count=1 if python_version < 0x300 else 2 ) builtin_hasattr_spec = BuiltinParameterSpecNoKeywords( "hasattr", ("object", "name"), default_count=0 ) builtin_getattr_spec = BuiltinParameterSpecNoKeywords( "getattr", ("object", "name", "default"), default_count=1 ) builtin_setattr_spec = BuiltinParameterSpecNoKeywords( "setattr", ("object", "name", "value"), default_count=0 ) builtin_isinstance_spec = BuiltinParameterSpecNoKeywords( "isinstance", ("instance", "classes"), default_count=0 ) builtin_issubclass_spec = BuiltinParameterSpecNoKeywords( "issubclass", ("cls", "classes"), default_count=0 ) class BuiltinBytearraySpec(BuiltinParameterSpecPosArgs): def isCompileTimeComputable(self, values): # For bytearrays, we need to avoid the case of large bytearray # construction from an integer at compile time. result = BuiltinParameterSpec.isCompileTimeComputable(self, values=values) if result and len(values) == 1: index_value = values[0].getIndexValue() if index_value is None: return result return index_value < 256 else: return result builtin_bytearray_spec = BuiltinBytearraySpec( "bytearray", ("string",), ("encoding", "errors"), default_count=2 ) builtin_bytes_p3_spec = BuiltinBytearraySpec( "bytes", ("string",), ("encoding", "errors"), default_count=3 ) # Beware: One argument version defines "stop", not "start". builtin_slice_spec = BuiltinParameterSpecNoKeywords( "slice", ("start", "stop", "step"), default_count=2 ) builtin_hash_spec = BuiltinParameterSpecNoKeywords("hash", ("object",), default_count=0) builtin_format_spec = BuiltinParameterSpecNoKeywords( "format", ("value", "format_spec"), default_count=1 ) if python_version < 0x380: builtin_sum_spec = BuiltinParameterSpecNoKeywords( "sum", ("sequence", "start"), default_count=1 ) else: builtin_sum_spec = BuiltinParameterSpecPosArgs( "sum", ("sequence",), ("start",), default_count=1 ) builtin_staticmethod_spec = BuiltinParameterSpecNoKeywords( "staticmethod", ("function",), default_count=0 ) builtin_classmethod_spec = BuiltinParameterSpecNoKeywords( "classmethod", ("function",), default_count=0 ) if python_version < 0x300: builtin_sorted_spec = BuiltinParameterSpecNoKeywords( "sorted", ("iterable", "cmp", "key", "reverse"), default_count=2 ) else: builtin_sorted_spec = BuiltinParameterSpecNoKeywords( "sorted", ("iterable", "key", "reverse"), default_count=2 ) builtin_reversed_spec = BuiltinParameterSpecNoKeywords( "reversed", ("object",), default_count=0 ) builtin_reversed_spec = BuiltinParameterSpecNoKeywords( "reversed", ("object",), default_count=0 ) if python_version < 0x300: builtin_enumerate_spec = BuiltinParameterSpec( "enumerate", ("sequence", "start"), default_count=1 ) else: builtin_enumerate_spec = BuiltinParameterSpec( "enumerate", ("iterable", "start"), default_count=1 ) class BuiltinRangeSpec(BuiltinParameterSpecNoKeywords): def isCompileTimeComputable(self, values): # For ranges, we need have many cases that can prevent the ability # to pre-compute, pylint: disable=too-many-branches,too-many-return-statements result = BuiltinParameterSpecNoKeywords.isCompileTimeComputable( self, values=values ) if result: arg_count = len(values) if arg_count == 1: low = values[0] # If it's not a number constant, we can compute the exception # that will be raised. if not low.isNumberConstant(): return True return low.getCompileTimeConstant() < 256 elif arg_count == 2: low, high = values # If it's not a number constant, we can compute the exception # that will be raised. if not low.isNumberConstant() or not high.isNumberConstant(): return True return ( high.getCompileTimeConstant() - low.getCompileTimeConstant() < 256 ) elif arg_count == 3: low, high, step = values if ( not low.isNumberConstant() or not high.isNumberConstant() or not step.isNumberConstant() ): return True low = low.getCompileTimeConstant() high = high.getCompileTimeConstant() step = step.getCompileTimeConstant() # It's going to give a ZeroDivisionError in this case. if step == 0: return True if low < high: if step < 0: return True else: return math.ceil(float(high - low) / step) < 256 else: if step > 0: return True else: return math.ceil(float(high - low) / step) < 256 else: assert False else: return False builtin_range_spec = BuiltinRangeSpec( "range", ("start", "stop", "step"), default_count=2 ) if python_version >= 0x300: builtin_ascii_spec = BuiltinParameterSpecNoKeywords( "ascii", ("object",), default_count=0 ) builtin_divmod_spec = BuiltinParameterSpecNoKeywords( "divmod", ("left", "right"), default_count=0 ) def extractBuiltinArgs(node, builtin_spec, builtin_class, empty_special_class=None): # Many cases to deal with, pylint: disable=too-many-branches try: kw = node.subnode_kwargs # TODO: Could check for too many / too few, even if they are unknown, we # might raise that error, but that need not be optimized immediately. if kw is not None: if not kw.isMappingWithConstantStringKeys(): return None pairs = kw.getMappingStringKeyPairs() if pairs and not builtin_spec.allowsKeywords(): raise TooManyArguments(TypeError(builtin_spec.getKeywordRefusalText())) else: pairs = () args = node.subnode_args if args: if not args.canPredictIterationValues(): return None positional = args.getIterationValues() else: positional = () if not positional and not pairs and empty_special_class is not None: return empty_special_class(source_ref=node.getSourceReference()) args_dict = matchCall( func_name=builtin_spec.getName(), args=builtin_spec.getArgumentNames(), kw_only_args=builtin_spec.getKwOnlyParameterNames(), star_list_arg=builtin_spec.getStarListArgumentName(), star_list_single_arg=builtin_spec.isStarListSingleArg(), star_dict_arg=builtin_spec.getStarDictArgumentName(), num_defaults=builtin_spec.getDefaultCount(), num_posonly=builtin_spec.getPosOnlyParameterCount(), positional=positional, pairs=pairs, ) except TooManyArguments as e: from nuitka.nodes.NodeMakingHelpers import ( makeRaiseExceptionReplacementExpressionFromInstance, wrapExpressionWithSideEffects, ) return wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=e.getRealException() ), old_node=node, side_effects=node.extractSideEffectsPreCall(), ) # Using list reference for passing the arguments without names where it # it possible, otherwise dictionary to make those distinuishable. args_list = [] for argument_name in builtin_spec.getArgumentNames(): args_list.append(args_dict[argument_name]) if builtin_spec.getStarListArgumentName() is not None: args_list.append(args_dict[builtin_spec.getStarListArgumentName()]) if builtin_spec.getStarDictArgumentName() is not None: args_list.append(args_dict[builtin_spec.getStarDictArgumentName()]) for argument_name in builtin_spec.getKwOnlyParameterNames(): args_list.append(args_dict[argument_name]) # Using list reference for passing the arguments without names, result = builtin_class(*args_list, source_ref=node.getSourceReference()) if python_version < 0x380: result.setCompatibleSourceReference(node.getCompatibleSourceReference()) return result Nuitka-0.6.19.1/nuitka/specs/BuiltinDictOperationSpecs.py0000600000372100037210000000471414166627112030350 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Dictionary operation specs. """ from .BuiltinParameterSpecs import ( BuiltinParameterSpecNoKeywords, BuiltinParameterSpecSinglePosArgStarDictArgs, ) class DictMethodSpec(BuiltinParameterSpecNoKeywords): __slots__ = () def __init__( self, name, arg_names=(), default_count=0, list_star_arg=None, dict_star_arg=None, pos_only_args=(), kw_only_args=(), ): BuiltinParameterSpecNoKeywords.__init__( self, name="dict." + name, arg_names=arg_names, default_count=default_count, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, pos_only_args=pos_only_args, kw_only_args=kw_only_args, ) dict_copy_spec = DictMethodSpec("copy") dict_clear_spec = DictMethodSpec("clear") dict_items_spec = DictMethodSpec("items") dict_iteritems_spec = DictMethodSpec("iteritems") dict_viewitems_spec = DictMethodSpec("viewitems") dict_keys_spec = DictMethodSpec("keys") dict_iterkeys_spec = DictMethodSpec("iterkeys") dict_viewkeys_spec = DictMethodSpec("viewkeys") dict_values_spec = DictMethodSpec("values") dict_itervalues_spec = DictMethodSpec("itervalues") dict_viewvalues_spec = DictMethodSpec("viewvalues") dict_get_spec = DictMethodSpec("get", arg_names=("key", "default"), default_count=1) dict_has_key_spec = DictMethodSpec("has_key", arg_names=("key",)) dict_setdefault_spec = DictMethodSpec( "setdefault", arg_names=("key", "default"), default_count=1 ) dict_pop_spec = DictMethodSpec("pop", arg_names=("key", "default"), default_count=1) dict_update_spec = BuiltinParameterSpecSinglePosArgStarDictArgs("dict.update") Nuitka-0.6.19.1/nuitka/specs/__init__.py0000600000372100037210000000150114166627112025005 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tree/0000700000372100037210000000000014167275622022525 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tree/ReformulationWhileLoopStatements.py0000600000372100037210000001302614166627112031616 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of while loop statements. Loops in Nuitka have no condition attached anymore, so while loops are re-formulated like this: .. code-block:: python while condition: something() .. code-block:: python while 1: if not condition: break something() This is to totally remove the specialization of loops, with the condition moved to the loop body in an initial conditional statement, which contains a ``break`` statement. That achieves, that only ``break`` statements exit the loop, and allow for optimization to remove always true loop conditions, without concerning code generation about it, and to detect such a situation, consider e.g. endless loops. .. note:: Loop analysis (not yet done) can then work on a reduced problem (which ``break`` statements are executed under what conditions) and is then automatically very general. The fact that the loop body may not be entered at all, is still optimized, but also in the general sense. Explicit breaks at the loop start and loop conditions are the same. """ from nuitka.nodes.AssignNodes import StatementAssignmentVariable from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.OperatorNodesUnary import ExpressionOperationNot from nuitka.nodes.StatementNodes import StatementsSequence from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from .TreeHelpers import ( buildNode, buildStatementsNode, makeStatementsSequence, makeStatementsSequenceFromStatements, popBuildContext, pushBuildContext, ) def buildWhileLoopNode(provider, node, source_ref): # The while loop is re-formulated according to Developer Manual. The # condition becomes an early condition to break the loop. The else block is # taken if a while loop exits normally, i.e. because of condition not being # true. We do this by introducing an indicator variable. else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref, ) if else_block is not None: temp_scope = provider.allocateTempScope("while_loop") # Indicator variable, will end up with C bool type, and need not be released. tmp_break_indicator = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator", temp_type="bool" ) statements = ( StatementAssignmentVariable( variable=tmp_break_indicator, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), StatementLoopBreak(source_ref=source_ref), ) else: statements = (StatementLoopBreak(source_ref=source_ref),) pushBuildContext("loop_body") loop_statements = buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref ) popBuildContext() # The loop body contains a conditional statement at the start that breaks # the loop if it fails. loop_body = makeStatementsSequence( statements=( makeStatementConditional( condition=ExpressionOperationNot( operand=buildNode(provider, node.test, source_ref), source_ref=source_ref, ), yes_branch=StatementsSequence( statements=statements, source_ref=source_ref ), no_branch=None, source_ref=source_ref, ), loop_statements, ), allow_none=True, source_ref=source_ref, ) loop_statement = StatementLoop(loop_body=loop_body, source_ref=source_ref) if else_block is None: return loop_statement else: return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_break_indicator, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), loop_statement, makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref ), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=else_block, no_branch=None, source_ref=source_ref, ), ) Nuitka-0.6.19.1/nuitka/tree/Operations.py0000600000372100037210000000620414166627112025220 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Operations on the tree. This is mostly for the different kinds of visits that the node tree can have. You can visit a scope, a tree (module), or every scope of a tree (module). """ from nuitka.containers.oset import OrderedSet from nuitka.Tracing import general def visitTree(tree, visitor): visitor.onEnterNode(tree) for visitable in tree.getVisitableNodes(): if visitable is None: raise AssertionError("'None' child encountered", tree, tree.source_ref) visitTree(visitable, visitor) visitor.onLeaveNode(tree) def visitFunction(function, visitor): visitor.onEnterNode(function) visitor.onLeaveNode(function) def visitModule(module, visitor): visitor.onEnterNode(module) visitor.onLeaveNode(module) class VisitorNoopMixin(object): def onEnterNode(self, node): """Overloaded for operation before the node children were done.""" def onLeaveNode(self, node): """Overloaded for operation after the node children were done.""" class DetectUsedModules(VisitorNoopMixin): def __init__(self): self.used_modules = OrderedSet() def onEnterNode(self, node): try: self._onEnterNode(node) except Exception: general.my_print( "Problem with %r at %s" % (node, node.getSourceReference().getAsString()) ) raise def _onEnterNode(self, node): if node.isExpressionBuiltinImport(): for ( used_module_name, used_module_filename, finding, level, ) in node.getUsedModules(): self.used_modules.add( ( used_module_name, used_module_filename, finding, level, node.source_ref, ) ) elif ( node.isExpressionImportModuleHard() or node.isExpressionImportModuleNameHard() or node.isExpressionImportModuleFixed() ): used_module_name, used_module_filename, finding = node.getUsedModule() self.used_modules.add( (used_module_name, used_module_filename, finding, 0, node.source_ref) ) def getUsedModules(self): return self.used_modules Nuitka-0.6.19.1/nuitka/tree/ReformulationContractionExpressions.py0000600000372100037210000005245314166627112032401 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of contraction expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.__past__ import intern from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.AsyncgenNodes import ( ExpressionAsyncgenObjectBody, ExpressionMakeAsyncgenObject, ) from nuitka.nodes.BuiltinIteratorNodes import ( ExpressionAsyncIter, ExpressionAsyncNext, ExpressionBuiltinIter1, ) from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.CodeObjectSpecs import CodeObjectSpec from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerOperationNodes import ( StatementListOperationAppend, StatementSetOperationAdd, ) from nuitka.nodes.DictionaryNodes import ( StatementDictOperationSet, StatementDictOperationSetKeyValue, ) from nuitka.nodes.FrameNodes import ( StatementsFrameFunction, StatementsFrameGenerator, ) from nuitka.nodes.FunctionNodes import ExpressionFunctionRef from nuitka.nodes.GeneratorNodes import ( ExpressionGeneratorObjectBody, ExpressionMakeGeneratorObject, StatementGeneratorReturnNone, ) from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.NodeMakingHelpers import makeVariableRefNode from nuitka.nodes.OutlineNodes import ( ExpressionOutlineBody, ExpressionOutlineFunction, ) from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.StatementNodes import ( StatementExpressionOnly, StatementsSequence, ) from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.nodes.YieldNodes import ( ExpressionYield, ExpressionYieldFromWaitable, ) from nuitka.PythonVersions import python_version from .ReformulationAssignmentStatements import buildAssignmentStatements from .ReformulationBooleanExpressions import makeAndNode from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildNodeList, detectFunctionBodyKind, getKind, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, mergeStatements, ) def _makeIteratorCreation(provider, qual, for_asyncgen, source_ref): if getattr(qual, "is_async", 0): result = ExpressionAsyncIter( value=buildNode(provider=provider, node=qual.iter, source_ref=source_ref), source_ref=source_ref, ) if not for_asyncgen or python_version < 0x370: result = ExpressionYieldFromWaitable( expression=result, source_ref=source_ref ) return result else: return ExpressionBuiltinIter1( value=buildNode(provider=provider, node=qual.iter, source_ref=source_ref), source_ref=source_ref, ) def _makeIteratorNext(qual, iterator_ref, source_ref): if getattr(qual, "is_async", 0): return ExpressionYieldFromWaitable( expression=ExpressionAsyncNext(value=iterator_ref, source_ref=source_ref), source_ref=source_ref, ) else: return ExpressionBuiltinNext1(value=iterator_ref, source_ref=source_ref) def _getStopIterationName(qual): if getattr(qual, "is_async", 0): return "StopAsyncIteration" else: return "StopIteration" def _buildPython2ListContraction(provider, node, source_ref): # The contraction nodes are reformulated to function bodies, with loops as # described in the Developer Manual. They use a lot of temporary names, # nested blocks, etc. and so a lot of variable names. # Note: The assign_provider is only to cover Python2 list contractions, # assigning one of the loop variables to the outside scope. function_body = ExpressionOutlineBody( provider=provider, name="list_contraction", source_ref=source_ref ) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") container_tmp = function_body.allocateTempVariable( temp_scope=None, name="contraction_result" ) statements, release_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=StatementListOperationAppend, iter_tmp=iter_tmp, temp_scope=None, start_value=[], container_tmp=container_tmp, function_body=function_body, assign_provider=True, for_asyncgen=False, source_ref=source_ref, ) statements.append( StatementReturn( expression=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref ), source_ref=source_ref, ) ) statement = makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal(), ) function_body.setChild( "body", makeStatementsSequenceFromStatement(statement=statement) ) return function_body def buildListContractionNode(provider, node, source_ref): # List contractions are dealt with by general code. if python_version < 0x300: return _buildPython2ListContraction( provider=provider, node=node, source_ref=source_ref ) return _buildContractionNode( provider=provider, node=node, name="", emit_class=StatementListOperationAppend, start_value=[], source_ref=source_ref, ) def buildSetContractionNode(provider, node, source_ref): # Set contractions are dealt with by general code. return _buildContractionNode( provider=provider, node=node, name="", emit_class=StatementSetOperationAdd, start_value=set(), source_ref=source_ref, ) def buildDictContractionNode(provider, node, source_ref): # Dict contractions are dealt with by general code. return _buildContractionNode( provider=provider, node=node, name="", emit_class=StatementDictOperationSet if python_version < 0x380 else StatementDictOperationSetKeyValue, start_value={}, source_ref=source_ref, ) def buildGeneratorExpressionNode(provider, node, source_ref): # Generator expressions are dealt with by general code. assert getKind(node) == "GeneratorExp" function_body = ExpressionOutlineBody( provider=provider, name="genexpr", source_ref=source_ref ) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name="", co_kind="Generator", co_varnames=(".0",), co_freevars=(), co_argcount=1, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) is_async = any(getattr(qual, "is_async", 0) for qual in node.generators) # Some of the newly allowed stuff in 3.7 fails to set the async flag. if not is_async and python_version >= 0x370: is_async = detectFunctionBodyKind(nodes=node.generators)[0] in ( "Asyncgen", "Coroutine", ) if is_async: code_body = ExpressionAsyncgenObjectBody( provider=provider, name="", code_object=code_object, flags=None, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeAsyncgenObject else: code_body = ExpressionGeneratorObjectBody( provider=provider, name="", code_object=code_object, flags=None, auto_release=None, source_ref=source_ref.atColumnNumber(node.col_offset + 1), ) maker_class = ExpressionMakeGeneratorObject function_body.setChild( "body", makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=iter_tmp, source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=is_async, source_ref=source_ref, ), source_ref=source_ref, ), makeTryFinallyStatement( provider=function_body, tried=StatementReturn( expression=maker_class( ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), final=StatementReleaseVariable( variable=iter_tmp, source_ref=source_ref ), source_ref=source_ref, ), ), ) statements, release_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=ExpressionYield, iter_tmp=iter_tmp, temp_scope=None, start_value=None, container_tmp=None, function_body=code_body, assign_provider=False, for_asyncgen=is_async, source_ref=source_ref, ) if is_async: statements.append(StatementGeneratorReturnNone(source_ref=source_ref)) statements = ( makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal(), ), ) code_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementsFrameGenerator( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref, ) ), ) return function_body def _buildContractionBodyNode( provider, node, emit_class, start_value, container_tmp, iter_tmp, temp_scope, assign_provider, function_body, for_asyncgen, source_ref, ): # This uses lots of variables and branches. There is no good way # around that, and we deal with many cases, due to having generator # expressions sharing this code, pylint: disable=too-many-branches,too-many-locals # Note: The assign_provider is only to cover Python2 list contractions, # assigning one of the loop variables to the outside scope. tmp_variables = [] if emit_class is not ExpressionYield: tmp_variables.append(iter_tmp) if container_tmp is not None: tmp_variables.append(container_tmp) statements = [] # First assign the iterator if we are an outline. if assign_provider: statements.append( StatementAssignmentVariable( variable=iter_tmp, source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=False, source_ref=source_ref, ), source_ref=source_ref.atInternal(), ) ) if for_asyncgen and python_version >= 0x370 and node.generators[0].is_async: statements.append( StatementAssignmentVariable( variable=iter_tmp, source=ExpressionTempVariableRef( variable=iter_tmp, source_ref=source_ref ), source_ref=source_ref, ) ) if start_value is not None: statements.append( StatementAssignmentVariable( variable=container_tmp, source=makeConstantRefNode(constant=start_value, source_ref=source_ref), source_ref=source_ref.atInternal(), ) ) if hasattr(node, "elt"): if start_value is not None: current_body = emit_class( ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref ), buildNode( provider=function_body if not assign_provider else provider, node=node.elt, source_ref=source_ref, ), source_ref=source_ref, ) else: assert emit_class is ExpressionYield current_body = emit_class( buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref, ) else: current_body = emit_class( dict_arg=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref ), key=buildNode( provider=function_body if not assign_provider else provider, node=node.key, source_ref=source_ref, ), value=buildNode( provider=function_body if not assign_provider else provider, node=node.value, source_ref=source_ref, ), source_ref=source_ref, ) if current_body.isExpression(): current_body = StatementExpressionOnly( expression=current_body, source_ref=source_ref ) for count, qual in enumerate(reversed(node.generators)): tmp_value_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="iter_value_%d" % count ) tmp_variables.append(tmp_value_variable) # The first iterated value is to be calculated outside of the function # and will be given as a parameter "_iterated", the others are built # inside the function. if qual is node.generators[0]: iterator_ref = makeVariableRefNode(variable=iter_tmp, source_ref=source_ref) if for_asyncgen and python_version >= 0x370: iterator_ref = ExpressionYieldFromWaitable( expression=iterator_ref, source_ref=source_ref ) tmp_iter_variable = None nested_statements = [] else: # First create the iterator and store it, next should be loop body value_iterator = _makeIteratorCreation( provider=provider if assign_provider else function_body, qual=qual, for_asyncgen=False, source_ref=source_ref, ) tmp_iter_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="contraction_iter_%d" % count ) tmp_variables.append(tmp_iter_variable) nested_statements = [ StatementAssignmentVariable( variable=tmp_iter_variable, source=value_iterator, source_ref=source_ref, ) ] iterator_ref = ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref ) loop_statements = [ makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_value_variable, source=_makeIteratorNext( iterator_ref=iterator_ref, qual=qual, source_ref=source_ref ), source_ref=source_ref, ), exception_name=_getStopIterationName(qual), handler_body=StatementLoopBreak(source_ref=source_ref), source_ref=source_ref, ), buildAssignmentStatements( provider=provider if assign_provider else function_body, temp_provider=function_body, node=qual.target, source=ExpressionTempVariableRef( variable=tmp_value_variable, source_ref=source_ref ), source_ref=source_ref, ), ] conditions = buildNodeList( provider=provider if assign_provider else function_body, nodes=qual.ifs, source_ref=source_ref, ) if len(conditions) >= 1: loop_statements.append( makeStatementConditional( condition=makeAndNode(values=conditions, source_ref=source_ref), yes_branch=current_body, no_branch=None, source_ref=source_ref, ) ) else: loop_statements.append(current_body) nested_statements.append( StatementLoop( loop_body=StatementsSequence( statements=mergeStatements(loop_statements), source_ref=source_ref ), source_ref=source_ref, ) ) if tmp_iter_variable is not None: nested_statements.append( StatementReleaseVariable( variable=tmp_iter_variable, source_ref=source_ref ) ) current_body = StatementsSequence( statements=mergeStatements(nested_statements, False), source_ref=source_ref ) statements.append(current_body) statements = mergeStatements(statements) release_statements = [ StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref) for tmp_variable in tmp_variables ] return statements, release_statements def _buildContractionNode(provider, node, name, emit_class, start_value, source_ref): # The contraction nodes are reformulated to function bodies, with loops as # described in the Developer Manual. They use a lot of temporary names, # nested blocks, etc. and so a lot of variable names. function_body = ExpressionOutlineFunction( provider=provider, name=intern(name[1:-1]), source_ref=source_ref ) iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0") container_tmp = function_body.allocateTempVariable( temp_scope=None, name="contraction" ) statements, release_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=emit_class, iter_tmp=iter_tmp, temp_scope=None, start_value=start_value, container_tmp=container_tmp, function_body=function_body, assign_provider=False, for_asyncgen=False, source_ref=source_ref, ) assign_iter_statement = StatementAssignmentVariable( source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=False, source_ref=source_ref, ), variable=iter_tmp, source_ref=source_ref, ) statements.append( StatementReturn( expression=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref ), source_ref=source_ref, ) ) statements = ( makeTryFinallyStatement( provider=function_body, tried=statements, final=release_statements, source_ref=source_ref.atInternal(), ), ) if python_version < 0x300: body = makeStatementsSequenceFromStatements(assign_iter_statement, statements) else: parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=name, co_kind="Function", co_varnames=(), co_freevars=(), co_argcount=1, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = makeStatementsSequenceFromStatements( assign_iter_statement, StatementsFrameFunction( statements=mergeStatements(statements, False), code_object=code_object, source_ref=source_ref, ), ) function_body.setChild("body", body) return function_body Nuitka-0.6.19.1/nuitka/tree/ReformulationAssertStatements.py0000600000372100037210000000536714166627112031166 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of assert statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.BuiltinRefNodes import ExpressionBuiltinExceptionRef from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTuple from nuitka.nodes.ExceptionNodes import StatementRaiseException from nuitka.nodes.OperatorNodesUnary import ExpressionOperationNot from nuitka.Options import hasPythonFlagNoAsserts from nuitka.PythonVersions import python_version from .TreeHelpers import buildNode def buildAssertNode(provider, node, source_ref): # Build assert statements. These are re-formulated as described in the # Developer Manual too. They end up as conditional statement with raises of # AssertionError exceptions. # Underlying assumption: # # Assert x, y is the same as: # if not x: # raise AssertionError, y # Therefore assert statements are really just conditional statements with a # static raise contained. # exception_value = buildNode(provider, node.msg, source_ref, True) if hasPythonFlagNoAsserts(): return None if exception_value is not None and python_version >= 0x272: exception_value = makeExpressionMakeTuple( elements=(exception_value,), source_ref=source_ref ) raise_statement = StatementRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name="AssertionError", source_ref=source_ref ), exception_value=exception_value, exception_trace=None, exception_cause=None, source_ref=source_ref, ) return makeStatementConditional( condition=ExpressionOperationNot( operand=buildNode(provider, node.test, source_ref), source_ref=source_ref ), yes_branch=raise_statement, no_branch=None, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/ReformulationTryExceptStatements.py0000600000372100037210000003442714166627112031653 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of try/except statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import StatementAssignmentVariable from nuitka.nodes.BuiltinRefNodes import ExpressionBuiltinExceptionRef from nuitka.nodes.ComparisonNodes import ( ExpressionComparisonExceptionMatch, ExpressionComparisonIs, ) from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ExceptionNodes import ( ExpressionCaughtExceptionTypeRef, ExpressionCaughtExceptionValueRef, ) from nuitka.nodes.StatementNodes import ( StatementPreserveFrameException, StatementPublishException, StatementRestoreFrameException, StatementsSequence, ) from nuitka.nodes.TryNodes import StatementTry from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.PythonVersions import python_version from .ReformulationAssignmentStatements import ( buildAssignmentStatements, buildDeleteStatementFromDecoded, decodeAssignTarget, ) from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .SyntaxErrors import raiseSyntaxError from .TreeHelpers import ( buildNode, buildStatementsNode, makeReraiseExceptionStatement, makeStatementsSequence, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, mergeStatements, ) def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. # Indicator variable, will end up with C bool type, and need not be released. tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator", temp_type="bool" ) statements = mergeStatements( ( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference(), ), handling, ), allow_none=True, ) handling = StatementsSequence(statements=statements, source_ref=source_ref) return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref ), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=no_raise, no_branch=None, source_ref=source_ref, ), ) def _makeTryExceptSingleHandlerNode( provider, public_exc, tried, exception_name, handler_body, source_ref ): # No need to create this in the first place if nothing is tried. if tried is None: return None if public_exc: preserver_id = provider.allocatePreserverId() handling = [ StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref ), StatementPublishException(source_ref=source_ref), ] else: handling = [] if not handler_body.isStatementsSequence(): handler_body = makeStatementsSequenceFromStatement(statement=handler_body) if not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(statement=tried) handling.append( makeStatementConditional( condition=ExpressionComparisonExceptionMatch( left=ExpressionCaughtExceptionTypeRef(source_ref=source_ref), right=ExpressionBuiltinExceptionRef( exception_name=exception_name, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=handler_body, no_branch=makeReraiseExceptionStatement(source_ref=source_ref), source_ref=source_ref, ) ) if python_version >= 0x300 and public_exc: handling = ( makeTryFinallyStatement( provider=provider, tried=handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), source_ref=source_ref.atInternal(), ), ) handling = makeStatementsSequenceFromStatements(*handling) return StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ) def makeTryExceptSingleHandlerNode(tried, exception_name, handler_body, source_ref): return _makeTryExceptSingleHandlerNode( provider=None, public_exc=False, tried=tried, exception_name=exception_name, handler_body=handler_body, source_ref=source_ref, ) def makeTryExceptSingleHandlerNodeWithPublish( provider, public_exc, tried, exception_name, handler_body, source_ref ): return _makeTryExceptSingleHandlerNode( provider=provider, public_exc=public_exc, tried=tried, exception_name=exception_name, handler_body=handler_body, source_ref=source_ref, ) def buildTryExceptionNode(provider, node, source_ref): # Try/except nodes. Re-formulated as described in the developer # manual. Exception handlers made the assignment to variables explicit. Same # for the "del" as done for Python3. Also catches always work a tuple of # exception types and hides away that they may be built or not. # Many variables and branches, due to the re-formulation that is going on # here, which just has the complexity, pylint: disable=too-many-branches,too-many-locals tried = buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref ) handlers = [] for handler in node.handlers: exception_expression, exception_assign, exception_block = ( handler.type, handler.name, handler.body, ) if exception_assign is None: statements = [ buildStatementsNode( provider=provider, nodes=exception_block, source_ref=source_ref ) ] elif python_version < 0x300: statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal() ), source_ref=source_ref.atInternal(), ), buildStatementsNode( provider=provider, nodes=exception_block, source_ref=source_ref ), ] else: # Python3 requires temporary assignment of exception assignment. target_info = decodeAssignTarget( provider=provider, node=exception_assign, source_ref=source_ref ) kind, detail = target_info assert kind == "Name", kind kind = "Name_Exception" statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal() ), source_ref=source_ref.atInternal(), ), makeTryFinallyStatement( provider=provider, tried=buildStatementsNode( provider=provider, nodes=exception_block, source_ref=source_ref ), final=buildDeleteStatementFromDecoded( provider=provider, kind=kind, detail=detail, source_ref=source_ref, ), source_ref=source_ref, ), ] handler_body = makeStatementsSequence( statements=statements, allow_none=True, source_ref=source_ref ) exception_types = buildNode( provider=provider, node=exception_expression, source_ref=source_ref, allow_none=True, ) # The exception types should be a tuple, so as to be most general. if exception_types is None: if handler is not node.handlers[-1]: raiseSyntaxError( "default 'except:' must be last", source_ref.atLineNumber(handler.lineno).atColumnNumber( handler.col_offset ), ) handlers.append((exception_types, handler_body)) # Re-raise by default exception_handling = makeReraiseExceptionStatement(source_ref=source_ref) for exception_type, handler in reversed(handlers): if exception_type is None: # A default handler was given, so use that indeed. exception_handling = handler else: exception_handling = StatementsSequence( statements=( makeStatementConditional( condition=ExpressionComparisonExceptionMatch( left=ExpressionCaughtExceptionTypeRef( source_ref=exception_type.source_ref ), right=exception_type, source_ref=exception_type.source_ref, ), yes_branch=handler, no_branch=exception_handling, source_ref=exception_type.source_ref, ), ), source_ref=exception_type.source_ref, ) if exception_handling is None: # For Python3, we need not publish at all, if all we do is to revert # that immediately. For Python2, the publish may release previously # published exception, which has side effects potentially. if python_version < 0x300: exception_handling = StatementsSequence( statements=( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal(), ), StatementPublishException(source_ref=source_ref.atInternal()), ), source_ref=source_ref.atInternal(), ) else: if python_version < 0x300: exception_handling.setChild( "statements", ( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal(), ), StatementPublishException(source_ref=source_ref.atInternal()), ) + exception_handling.subnode_statements, ) else: preserver_id = provider.allocatePreserverId() exception_handling = makeStatementsSequenceFromStatements( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), StatementPublishException(source_ref=source_ref.atInternal()), makeTryFinallyStatement( provider=provider, tried=exception_handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), source_ref=source_ref, ), ) no_raise = buildStatementsNode( provider=provider, nodes=node.orelse, source_ref=source_ref ) if no_raise is None: if tried is None: return None return StatementTry( tried=tried, except_handler=exception_handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ) else: if tried is None: return no_raise return makeTryExceptNoRaise( provider=provider, temp_scope=provider.allocateTempScope("try_except"), handling=exception_handling, tried=tried, no_raise=no_raise, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/ReformulationClasses3.py0000600000372100037210000007250514166627112027333 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of Python3 class statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import ( ExpressionAttributeCheck, ExpressionBuiltinGetattr, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinIteratorNodes import ExpressionBuiltinIter1 from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.BuiltinRefNodes import makeExpressionBuiltinTypeRef from nuitka.nodes.BuiltinTypeNodes import ExpressionBuiltinTuple from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.ClassNodes import ( ExpressionClassBody, ExpressionSelectMetaclass, ) from nuitka.nodes.CodeObjectSpecs import CodeObjectSpec from nuitka.nodes.ComparisonNodes import makeComparisonExpression from nuitka.nodes.ConditionalNodes import ( ExpressionConditional, makeStatementConditional, ) from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import ( makeExpressionMakeTuple, makeExpressionMakeTupleOrConstant, ) from nuitka.nodes.ContainerOperationNodes import ( ExpressionListOperationExtend, StatementListOperationAppend, ) from nuitka.nodes.DictionaryNodes import ( ExpressionDictOperationGet2, ExpressionDictOperationIn, StatementDictOperationRemove, StatementDictOperationUpdate, ) from nuitka.nodes.FunctionAttributeNodes import ExpressionFunctionQualnameRef from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCall, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.GlobalsLocalsNodes import ExpressionBuiltinLocalsRef from nuitka.nodes.LocalsDictNodes import ( StatementLocalsDictOperationSet, StatementReleaseLocals, StatementSetLocals, ) from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.ModuleAttributeNodes import ExpressionModuleAttributeNameRef from nuitka.nodes.NodeMakingHelpers import ( makeRaiseExceptionExpressionFromTemplate, mergeStatements, ) from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.StatementNodes import StatementExpressionOnly from nuitka.nodes.SubscriptNodes import ExpressionSubscriptLookup from nuitka.nodes.TypeNodes import ExpressionBuiltinType1, ExpressionTypeCheck from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableRef, ) from nuitka.PythonVersions import python_version from nuitka.specs.ParameterSpecs import ParameterSpec from .InternalModule import ( internal_source_ref, makeInternalHelperFunctionBody, once_decorator, ) from .ReformulationSequenceCreation import buildTupleUnpacking from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildFrameNode, buildNode, buildNodeList, extractDocFromBody, getKind, makeDictCreationOrConstant2, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, mangleName, ) def _buildBasesTupleCreationNode(provider, elements, source_ref): """For use in Python3 classes for the bases.""" for element in elements: if getKind(element) == "Starred": return buildTupleUnpacking( provider=provider, elements=elements, source_ref=source_ref ) return makeExpressionMakeTupleOrConstant( elements=buildNodeList(provider, elements, source_ref), user_provided=True, source_ref=source_ref, ) def buildClassNode3(provider, node, source_ref): # Many variables, due to the huge re-formulation that is going on here, # which just has the complexity and optimization checks: # pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements # This function is the Python3 special case with special re-formulation as # according to Developer Manual. class_statement_nodes, class_doc = extractDocFromBody(node) # We need a scope for the temporary variables, and they might be closured. temp_scope = provider.allocateTempScope(name="class_creation") tmp_class_decl_dict = provider.allocateTempVariable( temp_scope=temp_scope, name="class_decl_dict" ) tmp_metaclass = provider.allocateTempVariable( temp_scope=temp_scope, name="metaclass" ) tmp_prepared = provider.allocateTempVariable(temp_scope=temp_scope, name="prepared") class_creation_function = ExpressionClassBody( provider=provider, name=node.name, doc=class_doc, source_ref=source_ref ) class_locals_scope = class_creation_function.getLocalsScope() # Only local variable, for provision to methods. class_variable = class_locals_scope.getLocalVariable( owner=class_creation_function, variable_name="__class__" ) class_locals_scope.registerProvidedVariable(class_variable) class_variable_ref = ExpressionVariableRef( variable=class_variable, source_ref=source_ref ) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_freevars=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=class_creation_function, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) source_ref_orig = source_ref if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref locals_scope = class_creation_function.getLocalsScope() statements = [ StatementSetLocals( locals_scope=locals_scope, new_locals=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=class_creation_function, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference("__name__"), source_ref=source_ref, ), source_ref=source_ref, ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=class_creation_function, variable_name="__doc__", source=makeConstantRefNode( constant=class_doc, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ) ) # The "__qualname__" attribute is new in Python3. qualname = class_creation_function.getFunctionQualname() if python_version < 0x340: qualname_ref = makeConstantRefNode( constant=qualname, source_ref=source_ref, user_provided=True ) else: qualname_ref = ExpressionFunctionQualnameRef( function_body=class_creation_function, source_ref=source_ref ) statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__qualname__", value=qualname_ref, source_ref=source_ref, ) ) if python_version >= 0x340: qualname_assign = statements[-1] if python_version >= 0x360 and class_creation_function.needsAnnotationsDictionary(): statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__annotations__", value=makeConstantRefNode( constant={}, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ) ) statements.append(body) if node.bases: tmp_bases = provider.allocateTempVariable(temp_scope=temp_scope, name="bases") if python_version >= 0x370: tmp_bases_orig = provider.allocateTempVariable( temp_scope=temp_scope, name="bases_orig" ) def makeBasesRef(): return ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref) else: def makeBasesRef(): return makeConstantRefNode(constant=(), source_ref=source_ref) if python_version >= 0x370 and node.bases: statements.append( makeStatementConditional( condition=makeComparisonExpression( comparator="NotEq", left=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), right=ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__orig_bases__", value=ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ) ) statements += ( StatementAssignmentVariable( variable=class_variable, source=makeExpressionCall( called=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), args=makeExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), makeBasesRef(), ExpressionBuiltinLocalsRef( locals_scope=locals_scope, source_ref=source_ref ), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), StatementReturn(expression=class_variable_ref, source_ref=source_ref), ) body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=class_creation_function, tried=mergeStatements(statements, True), final=StatementReleaseLocals( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ) ) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. class_creation_function.setChild("body", body) # The class body is basically a function that implicitly, at the end # returns its created class and cannot have other return statements # contained. decorated_body = class_creation_function for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): decorated_body = makeExpressionCall( called=decorator, args=makeExpressionMakeTuple( elements=(decorated_body,), source_ref=source_ref ), kw=None, source_ref=decorator.getSourceReference(), ) if node.keywords and node.keywords[-1].arg is None: keywords = node.keywords[:-1] else: keywords = node.keywords statements = [] if node.bases: statements.append( StatementAssignmentVariable( variable=tmp_bases if python_version < 0x370 else tmp_bases_orig, source=_buildBasesTupleCreationNode( provider=provider, elements=node.bases, source_ref=source_ref ), source_ref=source_ref, ) ) if python_version >= 0x370: bases_conversion = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getClassBasesMroConversionHelper(), source_ref=source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=( ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), ), source_ref=source_ref, ) statements.append( StatementAssignmentVariable( variable=tmp_bases, source=bases_conversion, source_ref=source_ref ) ) statements.append( StatementAssignmentVariable( variable=tmp_class_decl_dict, source=makeDictCreationOrConstant2( keys=[keyword.arg for keyword in keywords], values=[ buildNode(provider, keyword.value, source_ref) for keyword in keywords ], source_ref=source_ref, ), source_ref=source_ref, ) ) if node.keywords and node.keywords[-1].arg is None: statements.append( StatementDictOperationUpdate( dict_arg=ExpressionVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), value=buildNode(provider, node.keywords[-1].value, source_ref), source_ref=source_ref, ) ) # Check if there are bases, and if there are, go with the type of the # first base class as a metaclass unless it was specified in the class # decl dict of course. if node.bases: unspecified_metaclass_expression = ExpressionBuiltinType1( value=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), subscript=makeConstantRefNode( constant=0, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ) # Might become empty behind our back during conversion, therefore make the # check at run time for 3.7 or higher. if python_version >= 0x370: unspecified_metaclass_expression = ExpressionConditional( condition=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), expression_yes=unspecified_metaclass_expression, expression_no=makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref ), source_ref=source_ref, ) else: unspecified_metaclass_expression = makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref ) call_prepare = StatementAssignmentVariable( variable=tmp_prepared, source=makeExpressionCall( called=makeExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), attribute_name="__prepare__", source_ref=source_ref, ), args=makeExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True ), makeBasesRef(), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) if python_version >= 0x364: call_prepare = makeStatementsSequenceFromStatements( call_prepare, makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), attribute_name="__getitem__", source_ref=source_ref, ), yes_branch=None, no_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template="%s.__prepare__() must return a mapping, not %s", template_args=( ExpressionBuiltinGetattr( expression=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), name=makeConstantRefNode( constant="__name__", source_ref=source_ref ), default=makeConstantRefNode( constant="", source_ref=source_ref ), source_ref=source_ref, ), makeExpressionAttributeLookup( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), source_ref=source_ref, ), attribute_name="__name__", source_ref=source_ref, ), ), source_ref=source_ref, ).asStatement(), source_ref=source_ref, ), ) statements += ( StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionSelectMetaclass( metaclass=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet2( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=unspecified_metaclass_expression, source_ref=source_ref, ), bases=makeBasesRef(), source_ref=source_ref, ), source_ref=source_ref_orig, ), makeStatementConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, yes_branch=StatementDictOperationRemove( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), attribute_name="__prepare__", source_ref=source_ref, ), yes_branch=call_prepare, no_branch=StatementAssignmentVariable( variable=tmp_prepared, source=makeConstantRefNode( constant={}, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_body, source_ref=source_ref, ), ) if python_version >= 0x340: class_creation_function.qualname_setup = node.name, qualname_assign final = [tmp_class_decl_dict, tmp_metaclass, tmp_prepared] if node.bases: final.insert(0, tmp_bases) if python_version >= 0x370: final.insert(0, tmp_bases_orig) return makeTryFinallyStatement( provider=provider, tried=statements, final=tuple( StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in final ), source_ref=source_ref, ) # Note: This emulates Python/bltinmodule.c/update_bases function. We have it # here, so we can hope to statically optimize it later on. @once_decorator def getClassBasesMroConversionHelper(): helper_name = "_mro_entries_conversion" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("bases",), ps_pos_only_args=(), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ), inline_const_args=False, # TODO: Allow this. ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "list") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "base") args_variable = result.getVariableForAssignment(variable_name="bases") non_type_case = makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionListOperationExtend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=makeExpressionCall( called=makeExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), args=makeExpressionMakeTuple( elements=( ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), ), source_ref=internal_source_ref, ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), no_branch=StatementListOperationAppend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) type_case = StatementListOperationAppend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ) loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionTypeCheck( cls=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=type_case, no_branch=non_type_case, source_ref=internal_source_ref, ), ) final = ( StatementReleaseVariable( variable=args_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionBuiltinTuple( value=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ), ) return result Nuitka-0.6.19.1/nuitka/tree/ReformulationFunctionStatements.py0000600000372100037210000006263014166627112031506 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of function statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementReleaseVariable, ) from nuitka.nodes.AsyncgenNodes import ( ExpressionAsyncgenObjectBody, ExpressionMakeAsyncgenObject, ) from nuitka.nodes.BuiltinIteratorNodes import ( ExpressionBuiltinIter1, StatementSpecialUnpackCheck, ) from nuitka.nodes.BuiltinNextNodes import ExpressionSpecialUnpack from nuitka.nodes.BuiltinRefNodes import makeExpressionBuiltinTypeRef from nuitka.nodes.CodeObjectSpecs import CodeObjectSpec from nuitka.nodes.CoroutineNodes import ( ExpressionCoroutineObjectBody, ExpressionMakeCoroutineObject, ) from nuitka.nodes.FunctionNodes import ( ExpressionFunctionBody, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.GeneratorNodes import ( ExpressionGeneratorObjectBody, ExpressionMakeGeneratorObject, StatementGeneratorReturnNone, ) from nuitka.nodes.LocalsDictNodes import StatementSetLocalsDictionary from nuitka.nodes.OutlineNodes import ExpressionOutlineFunction from nuitka.nodes.ReturnNodes import StatementReturn, StatementReturnNone from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableNameRef, ExpressionVariableRef, ) from nuitka.Options import hasPythonFlagNoAnnotations from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version from nuitka.specs.ParameterSpecs import ParameterSpec from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .SyntaxErrors import raiseSyntaxError from .TreeHelpers import ( buildAnnotationNode, buildFrameNode, buildNode, buildNodeList, detectFunctionBodyKind, extractDocFromBody, getKind, makeCallNode, makeDictCreationOrConstant2, makeStatementsSequenceFromStatement, mangleName, ) def _insertFinalReturnStatement(function_statements_body, return_statement): if function_statements_body is None: function_statements_body = makeStatementsSequenceFromStatement( statement=return_statement ) elif not function_statements_body.isStatementAborting(): function_statements_body.setChild( "statements", function_statements_body.subnode_statements + (return_statement,), ) return function_statements_body def _insertInitialSetLocalsDictStatement(function_body, function_statements_body): locals_statement = StatementSetLocalsDictionary( locals_scope=function_body.getLocalsScope(), source_ref=function_body.source_ref ) if function_statements_body is None: function_statements_body = makeStatementsSequenceFromStatement( statement=locals_statement ) else: function_statements_body.setChild( "statements", (locals_statement,) + function_statements_body.subnode_statements, ) return function_statements_body def _injectDecorator(decorators, inject, acceptable, source_ref): assert type(inject) is str assert type(acceptable) is tuple for decorator in decorators: if ( decorator.isExpressionVariableNameRef() and decorator.getVariableName() in acceptable ): break else: decorators.append( makeExpressionBuiltinTypeRef(builtin_name=inject, source_ref=source_ref) ) def buildFunctionNode(provider, node, source_ref): # Functions have way too many details, pylint: disable=too-many-locals assert getKind(node) == "FunctionDef" Plugins.onFunctionBodyParsing( provider=provider, function_name=node.name, body=node.body ) function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags = detectFunctionBodyKind(nodes=function_statement_nodes) function_body, code_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name=node.name, function_doc=function_doc, flags=flags, node=node, source_ref=source_ref, ) if function_kind in ("Generator", "Coroutine"): if function_kind == "Coroutine": code_body = ExpressionCoroutineObjectBody( provider=function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeCoroutineObject else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) maker_class = ExpressionMakeGeneratorObject code_body.qualname_provider = provider for variable in function_body.getProvidedVariables(): code_body.getVariableForReference(variable.getName()) function_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementReturn( expression=maker_class( ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ), ) decorators = buildNodeList( provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref ) defaults = buildNodeList( provider=provider, nodes=node.args.defaults, source_ref=source_ref ) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=function_body, source_ref=source_ref ) function_statements_body = buildFrameNode( provider=code_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref, ) if function_kind == "Function": # TODO: Generators might have to raise GeneratorExit instead. function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_statement=StatementReturnNone(source_ref=source_ref), ) if "has_exec" in flags: function_statements_body = _insertInitialSetLocalsDictStatement( function_body=code_body, function_statements_body=function_statements_body ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body ) code_body.setChild("body", function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, ) # Add the "staticmethod" decorator to __new__ methods if not provided. # CPython made these optional, but secretly applies them when it does # "class __new__". We add them earlier, so our optimization will see it. if ( python_version < 0x300 and node.name == "__new__" and provider.isExpressionClassBody() ): _injectDecorator( decorators, "staticmethod", ("staticmethod", "classmethod"), source_ref ) # Add the "classmethod" decorator to __init_subclass__ methods if not provided. if ( python_version >= 0x360 and node.name == "__init_subclass__" and provider.isExpressionClassBody() ): _injectDecorator(decorators, "classmethod", ("classmethod",), source_ref) if ( python_version >= 0x370 and node.name == "__class_getitem__" and provider.isExpressionClassBody() ): _injectDecorator(decorators, "classmethod", ("classmethod",), source_ref) decorated_function = function_creation for decorator in decorators: decorated_function = makeCallNode( decorator, decorated_function, decorator.getSourceReference() ) result = StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_function, source_ref=source_ref, ) if python_version >= 0x340: function_body.qualname_setup = result.getVariableName() return result def buildAsyncFunctionNode(provider, node, source_ref): # We are creating a function here that creates coroutine objects, with # many details each, pylint: disable=too-many-locals assert getKind(node) == "AsyncFunctionDef" Plugins.onFunctionBodyParsing( provider=provider, function_name=node.name, body=node.body ) function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags = detectFunctionBodyKind( nodes=function_statement_nodes, start_value="Coroutine" ) creator_function_body, _, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name=node.name, function_doc=function_doc, flags=(), node=node, source_ref=source_ref, ) if function_kind == "Coroutine": function_body = ExpressionCoroutineObjectBody( provider=creator_function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) else: function_body = ExpressionAsyncgenObjectBody( provider=creator_function_body, name=node.name, code_object=code_object, flags=flags, auto_release=None, source_ref=source_ref, ) function_body.qualname_provider = provider for variable in creator_function_body.getProvidedVariables(): function_body.getVariableForReference(variable.getName()) decorators = buildNodeList( provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref ) defaults = buildNodeList( provider=provider, nodes=node.args.defaults, source_ref=source_ref ) function_statements_body = buildFrameNode( provider=function_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref, ) function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_statement=StatementGeneratorReturnNone(source_ref=source_ref), ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body ) function_body.setChild("body", function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=creator_function_body, source_ref=source_ref, ) if function_kind == "Coroutine": creation_node = ExpressionMakeCoroutineObject( coroutine_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), source_ref=source_ref, ) else: creation_node = ExpressionMakeAsyncgenObject( asyncgen_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref ), source_ref=source_ref, ) creator_function_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementReturn(expression=creation_node, source_ref=source_ref) ), ) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=creator_function_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, ) decorated_function = function_creation for decorator in decorators: decorated_function = makeCallNode( decorator, decorated_function, decorator.getSourceReference() ) result = StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_function, source_ref=source_ref, ) function_body.qualname_setup = result.getVariableName() # Share the non-local declarations. TODO: This may also apply to generators # and async generators. creator_function_body.non_local_declarations = function_body.non_local_declarations return result def buildParameterKwDefaults(provider, node, function_body, source_ref): # Build keyword only arguments default values. We are hiding here, that it # is a Python3 only feature. if python_version >= 0x300: kw_only_names = function_body.getParameters().getKwOnlyParameterNames() if kw_only_names: keys = [] values = [] for kw_only_name, kw_default in zip(kw_only_names, node.args.kw_defaults): if kw_default is not None: keys.append(kw_only_name) values.append(buildNode(provider, kw_default, source_ref)) kw_defaults = makeDictCreationOrConstant2( keys=keys, values=values, source_ref=source_ref ) else: kw_defaults = None else: kw_defaults = None return kw_defaults def buildParameterAnnotations(provider, node, source_ref): # Too many branches, because there is too many cases, pylint: disable=too-many-branches # Build annotations. We are hiding here, that it is a Python3 only feature. if python_version < 0x300 or hasPythonFlagNoAnnotations(): return None # Starting with Python 3.4, the names of parameters are mangled in # annotations as well. if python_version < 0x340: mangle = lambda variable_name: variable_name else: mangle = lambda variable_name: mangleName(variable_name, provider) keys = [] values = [] def addAnnotation(key, value): keys.append(mangle(key)) values.append(value) def extractArgAnnotation(arg): if getKind(arg) == "Name": assert arg.annotation is None elif getKind(arg) == "arg": if arg.annotation is not None: addAnnotation( key=arg.arg, value=buildAnnotationNode(provider, arg.annotation, source_ref), ) elif getKind(arg) == "Tuple": for sub_arg in arg.elts: extractArgAnnotation(sub_arg) else: assert False, getKind(arg) if python_version >= 0x380: for arg in node.args.posonlyargs: extractArgAnnotation(arg) for arg in node.args.args: extractArgAnnotation(arg) for arg in node.args.kwonlyargs: extractArgAnnotation(arg) if python_version < 0x340: if node.args.varargannotation is not None: addAnnotation( key=node.args.vararg, value=buildNode(provider, node.args.varargannotation, source_ref), ) if node.args.kwargannotation is not None: addAnnotation( key=node.args.kwarg, value=buildNode(provider, node.args.kwargannotation, source_ref), ) else: if node.args.vararg is not None: extractArgAnnotation(node.args.vararg) if node.args.kwarg is not None: extractArgAnnotation(node.args.kwarg) # Return value annotation (not there for lambdas) if hasattr(node, "returns") and node.returns is not None: addAnnotation( key="return", value=buildAnnotationNode(provider, node.returns, source_ref) ) if keys: return makeDictCreationOrConstant2( keys=keys, values=values, source_ref=source_ref ) else: return None def _wrapFunctionWithSpecialNestedArgs( name, outer_body, parameters, special_args, source_ref ): inner_name = name.strip("<>") + "$inner" iter_vars = [] values = [] statements = [] def unpackFrom(source, arg_names): accesses = [] sub_special_index = 0 iter_var = outer_body.allocateTempVariable(None, "arg_iter_%d" % len(iter_vars)) iter_vars.append(iter_var) statements.append( StatementAssignmentVariable( variable=iter_var, source=ExpressionBuiltinIter1(value=source, source_ref=source_ref), source_ref=source_ref, ) ) for element_index, arg_name in enumerate(arg_names): if getKind(arg_name) == "Name": arg_var = outer_body.createProvidedVariable(arg_name.id) outer_body.getLocalsScope().registerProvidedVariable(arg_var) statements.append( StatementAssignmentVariable( variable=arg_var, source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=iter_var, source_ref=source_ref ), count=element_index + 1, expected=len(arg_names), starred=False, source_ref=source_ref, ), source_ref=source_ref, ) ) accesses.append( ExpressionVariableRef(variable=arg_var, source_ref=source_ref) ) elif getKind(arg_name) == "Tuple": accesses.extend( unpackFrom( source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=iter_var, source_ref=source_ref ), count=element_index + 1, expected=len(arg_names), starred=False, source_ref=source_ref, ), arg_names=arg_name.elts, ) ) sub_special_index += 1 else: assert False, arg_name statements.append( StatementSpecialUnpackCheck( iterator=ExpressionTempVariableRef( variable=iter_var, source_ref=source_ref ), count=len(arg_names), source_ref=source_ref, ) ) return accesses for arg_name in parameters.getParameterNames(): if arg_name.startswith("."): source = ExpressionVariableNameRef( provider=outer_body, variable_name=arg_name, source_ref=source_ref ) values.extend(unpackFrom(source, special_args[arg_name])) else: values.append( ExpressionVariableNameRef( provider=outer_body, variable_name=arg_name, source_ref=source_ref ) ) code_body = ExpressionOutlineFunction( provider=outer_body, name=inner_name, source_ref=source_ref ) statements.append(StatementReturn(expression=code_body, source_ref=source_ref)) outer_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outer_body, tried=statements, final=[ StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in sorted( outer_body.getTempVariables(), key=lambda variable: variable.getName(), ) ], source_ref=source_ref, public_exc=False, ) ), ) return code_body def buildFunctionWithParsing( provider, function_kind, name, function_doc, flags, node, source_ref ): # This contains a complex re-formulation for nested parameter functions. # pylint: disable=too-many-locals kind = getKind(node) assert kind in ("FunctionDef", "Lambda", "AsyncFunctionDef"), ( "unsupported for kind " + kind ) def extractArg(arg): if arg is None: return None elif type(arg) is str: return mangleName(arg, provider) elif getKind(arg) == "Name": return mangleName(arg.id, provider) elif getKind(arg) == "arg": return mangleName(arg.arg, provider) elif getKind(arg) == "Tuple": # These are to be re-formulated on the outside. assert False else: assert False, getKind(arg) special_args = {} def extractNormalArgs(args): normal_args = [] for arg in args: if type(arg) is not str and getKind(arg) == "Tuple": special_arg_name = ".%d" % (len(special_args) + 1) special_args[special_arg_name] = arg.elts normal_args.append(special_arg_name) else: normal_args.append(extractArg(arg)) return normal_args parameters = ParameterSpec( ps_name=name, ps_normal_args=extractNormalArgs(node.args.args), ps_pos_only_args=[extractArg(arg) for arg in node.args.posonlyargs] if python_version >= 0x380 else (), ps_kw_only_args=[extractArg(arg) for arg in node.args.kwonlyargs] if python_version >= 0x300 else (), ps_list_star_arg=extractArg(node.args.vararg), ps_dict_star_arg=extractArg(node.args.kwarg), ps_default_count=len(node.args.defaults), ) message = parameters.checkParametersValid() if message is not None: raiseSyntaxError(message, source_ref.atColumnNumber(node.col_offset)) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=name, co_kind=function_kind, co_varnames=parameters.getParameterNames(), co_freevars=(), co_argcount=parameters.getArgumentCount(), co_posonlyargcount=parameters.getPosOnlyParameterCount(), co_kwonlyargcount=parameters.getKwOnlyParameterCount(), co_has_starlist=parameters.getStarListArgumentName() is not None, co_has_stardict=parameters.getStarDictArgumentName() is not None, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) outer_body = ExpressionFunctionBody( provider=provider, name=name, code_object=code_object, flags=flags, doc=function_doc, parameters=parameters, auto_release=None, source_ref=source_ref, ) # Wrap if necessary for special nested arguments. if special_args: code_body = _wrapFunctionWithSpecialNestedArgs( name=name, outer_body=outer_body, parameters=parameters, special_args=special_args, source_ref=source_ref, ) else: code_body = outer_body return outer_body, code_body, code_object def addFunctionVariableReleases(function): assert function.isExpressionFunctionBodyBase() releases = [] # We attach everything to the function definition source location. source_ref = function.getSourceReference() for variable in function.getLocalVariables(): # Shared variables are freed by function attachment. if variable.getOwner() is not function: continue releases.append( StatementReleaseVariable(variable=variable, source_ref=source_ref) ) if releases: body = function.subnode_body if body.isStatementsFrame(): body = makeStatementsSequenceFromStatement(statement=body) body = makeTryFinallyStatement( provider=function, tried=body, final=releases, source_ref=source_ref ) function.setChild("body", makeStatementsSequenceFromStatement(statement=body)) Nuitka-0.6.19.1/nuitka/tree/ReformulationWithStatements.py0000600000372100037210000003362014166627112030631 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of with statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka import Options from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import ( ExpressionAttributeLookupSpecial, makeExpressionAttributeLookup, ) from nuitka.nodes.CallNodes import ( ExpressionCallEmpty, ExpressionCallNoKeywords, ) from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTuple from nuitka.nodes.CoroutineNodes import ( ExpressionAsyncWaitEnter, ExpressionAsyncWaitExit, ) from nuitka.nodes.ExceptionNodes import ( ExpressionCaughtExceptionTracebackRef, ExpressionCaughtExceptionTypeRef, ExpressionCaughtExceptionValueRef, ) from nuitka.nodes.StatementNodes import ( StatementExpressionOnly, StatementsSequence, ) from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.nodes.YieldNodes import ExpressionYieldFromWaitable from nuitka.PythonVersions import python_version from .ReformulationAssignmentStatements import buildAssignmentStatements from .ReformulationTryExceptStatements import ( makeTryExceptSingleHandlerNodeWithPublish, ) from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildStatementsNode, makeReraiseExceptionStatement, makeStatementsSequence, ) def _buildWithNode(provider, context_expr, assign_target, body, sync, source_ref): # Many details, pylint: disable=too-many-branches,too-many-locals with_source = buildNode(provider, context_expr, source_ref) if python_version < 0x380 and Options.is_fullcompat: source_ref = with_source.getCompatibleSourceReference() temp_scope = provider.allocateTempScope("with") tmp_source_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="source" ) tmp_exit_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="exit" ) tmp_enter_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="enter" ) # Indicator variable, will end up with C bool type, and need not be released. tmp_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="indicator", temp_type="bool" ) statements = ( buildAssignmentStatements( provider=provider, node=assign_target, allow_none=True, source=ExpressionTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref ), source_ref=source_ref, ), body, ) with_body = makeStatementsSequence( statements=statements, allow_none=True, source_ref=source_ref ) if body and python_version < 0x3A0: deepest = body while deepest.getVisitableNodes(): deepest = deepest.getVisitableNodes()[-1] if python_version < 0x370: body_lineno = deepest.getCompatibleSourceReference().getLineNumber() else: body_lineno = deepest.getSourceReference().getLineNumber() with_exit_source_ref = source_ref.atLineNumber(body_lineno) else: with_exit_source_ref = source_ref # The "__enter__" and "__exit__" were normal attribute lookups under # CPython2.6, but that changed with CPython2.7. if python_version < 0x270: attribute_lookup_maker = makeExpressionAttributeLookup else: attribute_lookup_maker = ExpressionAttributeLookupSpecial enter_value = ExpressionCallEmpty( called=attribute_lookup_maker( expression=ExpressionTempVariableRef( variable=tmp_source_variable, source_ref=source_ref ), attribute_name="__enter__" if sync else "__aenter__", source_ref=source_ref, ), source_ref=source_ref, ) exit_value_exception = ExpressionCallNoKeywords( called=ExpressionTempVariableRef( variable=tmp_exit_variable, source_ref=with_exit_source_ref ), args=makeExpressionMakeTuple( elements=( ExpressionCaughtExceptionTypeRef(source_ref=with_exit_source_ref), ExpressionCaughtExceptionValueRef(source_ref=with_exit_source_ref), ExpressionCaughtExceptionTracebackRef(source_ref=source_ref), ), source_ref=source_ref, ), source_ref=with_exit_source_ref, ) exit_value_no_exception = ExpressionCallNoKeywords( called=ExpressionTempVariableRef( variable=tmp_exit_variable, source_ref=source_ref ), args=makeConstantRefNode(constant=(None, None, None), source_ref=source_ref), source_ref=with_exit_source_ref, ) # For "async with", await the entered value and exit value must be awaited. if not sync: exit_value_exception = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitExit( expression=exit_value_exception, source_ref=source_ref ), source_ref=source_ref, ) exit_value_no_exception = ExpressionYieldFromWaitable( ExpressionAsyncWaitExit( expression=exit_value_no_exception, source_ref=source_ref ), source_ref=source_ref, ) # First assign the with context to a temporary variable. statements = [ StatementAssignmentVariable( variable=tmp_source_variable, source=with_source, source_ref=source_ref ) ] # Before 3.9, __aenter__ is immediately awaited, after we first do __aexit__ lookup. if not sync and python_version < 0x390: enter_value = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter( expression=enter_value, source_ref=source_ref ), source_ref=source_ref, ) attribute_enter_assignment = StatementAssignmentVariable( variable=tmp_enter_variable, source=enter_value, source_ref=source_ref ) attribute_exit_assignment = StatementAssignmentVariable( variable=tmp_exit_variable, source=attribute_lookup_maker( expression=ExpressionTempVariableRef( variable=tmp_source_variable, source_ref=source_ref ), attribute_name="__exit__" if sync else "__aexit__", source_ref=source_ref, ), source_ref=source_ref, ) # Next, assign "__enter__" and "__exit__" attributes to temporary variables, and # depending on Python versions switch the order of these lookups and the order of # awaiting enter. # Normal "with" statements are enter, exit ordered after 3.6, and "async with" # are since 3.9, and since 3.9 the enter is not awaited, until an exit is present. if python_version >= 0x390 and not sync: enter_await_statement = StatementAssignmentVariable( variable=tmp_enter_variable, source=ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter( expression=ExpressionTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ) attribute_assignments = ( attribute_enter_assignment, attribute_exit_assignment, enter_await_statement, ) elif python_version >= 0x360 and sync: attribute_assignments = (attribute_enter_assignment, attribute_exit_assignment) else: attribute_assignments = (attribute_exit_assignment, attribute_enter_assignment) statements.extend(attribute_assignments) statements.append( StatementAssignmentVariable( variable=tmp_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ) ) statements += ( makeTryFinallyStatement( provider=provider, tried=makeTryExceptSingleHandlerNodeWithPublish( provider=provider, tried=with_body, exception_name="BaseException", handler_body=StatementsSequence( statements=( # Prevents final block from calling __exit__ as # well. StatementAssignmentVariable( variable=tmp_indicator_variable, source=makeConstantRefNode( constant=False, source_ref=source_ref ), source_ref=source_ref, ), makeStatementConditional( condition=exit_value_exception, no_branch=makeReraiseExceptionStatement( source_ref=with_exit_source_ref ), yes_branch=None, source_ref=with_exit_source_ref, ), ), source_ref=source_ref, ), public_exc=python_version >= 0x270, source_ref=source_ref, ), final=makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref ), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=exit_value_no_exception, source_ref=source_ref ), no_branch=None, source_ref=source_ref, ), source_ref=source_ref, ), ) return makeTryFinallyStatement( provider=provider, tried=statements, final=( StatementReleaseVariable( variable=tmp_source_variable, source_ref=with_exit_source_ref ), StatementReleaseVariable( variable=tmp_enter_variable, source_ref=with_exit_source_ref ), StatementReleaseVariable( variable=tmp_exit_variable, source_ref=with_exit_source_ref ), ), source_ref=source_ref, ) def buildWithNode(provider, node, source_ref): # "with" statements are re-formulated as described in the developer # manual. Catches exceptions, and provides them to "__exit__", while making # the "__enter__" value available under a given name. # Before Python3.3, multiple context managers are not visible in the parse # tree, now we need to handle it ourselves. if hasattr(node, "items"): context_exprs = [item.context_expr for item in node.items] assign_targets = [item.optional_vars for item in node.items] else: # Make it a list for before Python3.3 context_exprs = [node.context_expr] assign_targets = [node.optional_vars] # The body for the first context manager is the other things. body = buildStatementsNode(provider, node.body, source_ref) assert context_exprs and len(context_exprs) == len(assign_targets) context_exprs.reverse() assign_targets.reverse() for context_expr, assign_target in zip(context_exprs, assign_targets): body = _buildWithNode( provider=provider, body=body, context_expr=context_expr, assign_target=assign_target, sync=True, source_ref=source_ref, ) return body def buildAsyncWithNode(provider, node, source_ref): # "with" statements are re-formulated as described in the developer # manual. Catches exceptions, and provides them to "__exit__", while making # the "__enter__" value available under a given name. # Before Python3.3, multiple context managers are not visible in the parse # tree, now we need to handle it ourselves. context_exprs = [item.context_expr for item in node.items] assign_targets = [item.optional_vars for item in node.items] # The body for the first context manager is the other things. body = buildStatementsNode(provider, node.body, source_ref) assert context_exprs and len(context_exprs) == len(assign_targets) context_exprs.reverse() assign_targets.reverse() for context_expr, assign_target in zip(context_exprs, assign_targets): body = _buildWithNode( provider=provider, body=body, context_expr=context_expr, assign_target=assign_target, sync=False, source_ref=source_ref, ) return body Nuitka-0.6.19.1/nuitka/tree/Extractions.py0000600000372100037210000000444714166627112025407 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Extracting visitors. This is used for look-aheads supporting abstract execution. We need to e.g. know the variables written by a piece of code ahead of abstractly executing a loop. """ from nuitka.containers.oset import OrderedSet from .Operations import VisitorNoopMixin, visitTree class VariableUsageExtractor(VisitorNoopMixin): """Extract variables used.""" def __init__(self): self.written_to = OrderedSet() def onEnterNode(self, node): if ( node.isStatementAssignmentVariable() or node.isStatementDelVariable() or node.isExpressionVariableRef() ): self.written_to.add(node.getVariable()) def getResult(self): return self.written_to def getVariablesWrittenOrRead(node): visitor = VariableUsageExtractor() visitTree(node, visitor) return visitor.getResult() class VariableUsageUpdater(VisitorNoopMixin): def __init__(self, old_variable, new_variable): self.old_variable = old_variable self.new_variable = new_variable def onEnterNode(self, node): if ( node.isStatementAssignmentVariable() or node.isStatementDelVariable() or node.isStatementReleaseVariable() ): if node.getVariable() is self.old_variable: node.setVariable(self.new_variable) def updateVariableUsage(provider, old_variable, new_variable): visitor = VariableUsageUpdater(old_variable=old_variable, new_variable=new_variable) visitTree(provider, visitor) Nuitka-0.6.19.1/nuitka/tree/ReformulationExecStatements.py0000600000372100037210000003464014166627112030605 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of "exec" statements Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.BuiltinRefNodes import ExpressionBuiltinExceptionRef from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import ( ExpressionConditional, makeStatementConditional, ) from nuitka.nodes.ConstantRefNodes import ( ExpressionConstantNoneRef, makeConstantRefNode, ) from nuitka.nodes.ExceptionNodes import StatementRaiseException from nuitka.nodes.ExecEvalNodes import StatementExec, StatementLocalsDictSync from nuitka.nodes.GlobalsLocalsNodes import ExpressionBuiltinGlobals from nuitka.nodes.NodeMakingHelpers import makeExpressionBuiltinLocals from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, getKind, makeStatementsSequence, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, ) def wrapEvalGlobalsAndLocals( provider, globals_node, locals_node, temp_scope, source_ref ): """Wrap the locals and globals arguments for "eval". This is called from the outside, and when the node tree already exists. """ locals_scope = provider.getLocalsScope() globals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="globals" ) locals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="locals" ) if locals_node is None: locals_node = ExpressionConstantNoneRef(source_ref=source_ref) if globals_node is None: globals_node = ExpressionConstantNoneRef(source_ref=source_ref) post_statements = [] if provider.isExpressionClassBody(): post_statements.append( StatementLocalsDictSync( locals_scope=locals_scope, locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), source_ref=source_ref.atInternal(), ) ) post_statements += ( StatementReleaseVariable( variable=globals_keeper_variable, source_ref=source_ref ), StatementReleaseVariable( variable=locals_keeper_variable, source_ref=source_ref ), ) # The locals default is dependent on exec_mode, globals or locals. locals_default = ExpressionConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), expression_no=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), expression_yes=makeExpressionBuiltinLocals( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ) pre_statements = [ # First assign globals and locals temporary the values given. StatementAssignmentVariable( variable=globals_keeper_variable, source=globals_node, source_ref=source_ref ), StatementAssignmentVariable( variable=locals_keeper_variable, source=locals_node, source_ref=source_ref ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementAssignmentVariable( variable=locals_keeper_variable, source=locals_default, source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementAssignmentVariable( variable=globals_keeper_variable, source=ExpressionBuiltinGlobals(source_ref=source_ref), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ] return ( ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref if globals_node is None else globals_node.getSourceReference(), ), ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref if locals_node is None else locals_node.getSourceReference(), ), makeStatementsSequence(pre_statements, False, source_ref), makeStatementsSequence(post_statements, False, source_ref), ) def buildExecNode(provider, node, source_ref): # "exec" statements, should only occur with Python2. # This is using many variables, due to the many details this is # dealing with. The locals and globals need to be dealt with in # temporary variables, and we need handling of indicators, so # that is just the complexity, pylint: disable=too-many-locals exec_globals = node.globals exec_locals = node.locals body = node.body # Handle exec(a,b,c) to be same as exec a, b, c if exec_locals is None and exec_globals is None and getKind(body) == "Tuple": parts = body.elts body = parts[0] if len(parts) > 1: exec_globals = parts[1] if len(parts) > 2: exec_locals = parts[2] else: return StatementRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name="TypeError", source_ref=source_ref ), exception_value=makeConstantRefNode( constant="""\ exec: arg 1 must be a string, file, or code object""", source_ref=source_ref, ), exception_trace=None, exception_cause=None, source_ref=source_ref, ) temp_scope = provider.allocateTempScope("exec") locals_value = buildNode(provider, exec_locals, source_ref, True) if locals_value is None: locals_value = ExpressionConstantNoneRef(source_ref=source_ref) globals_value = buildNode(provider, exec_globals, source_ref, True) if globals_value is None: globals_value = ExpressionConstantNoneRef(source_ref=source_ref) source_code = buildNode(provider, body, source_ref) source_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="exec_source" ) globals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="globals" ) locals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="locals" ) plain_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="plain" ) tried = ( # First evaluate the source code expressions. StatementAssignmentVariable( variable=source_variable, source=source_code, source_ref=source_ref ), # Assign globals and locals temporary the values given, then fix it # up, taking note in the "plain" temporary variable, if it was an # "exec" statement with None arguments, in which case the copy back # will be necessary. StatementAssignmentVariable( variable=globals_keeper_variable, source=globals_value, source_ref=source_ref, ), StatementAssignmentVariable( variable=locals_keeper_variable, source=locals_value, source_ref=source_ref ), StatementAssignmentVariable( variable=plain_indicator_variable, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=globals_keeper_variable, source=ExpressionBuiltinGlobals(source_ref=source_ref), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=locals_keeper_variable, source=makeExpressionBuiltinLocals( locals_scope=provider.getLocalsScope(), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=plain_indicator_variable, source=makeConstantRefNode( constant=True, source_ref=source_ref ), source_ref=source_ref, ), ), no_branch=None, source_ref=source_ref, ), ), no_branch=makeStatementsSequenceFromStatements( makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable=locals_keeper_variable, source=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), source_ref=source_ref, ) ), no_branch=None, source_ref=source_ref, ) ), source_ref=source_ref, ), makeTryFinallyStatement( provider=provider, tried=StatementExec( source_code=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), globals_arg=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref ), locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), source_ref=source_ref, ), final=makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=plain_indicator_variable, source_ref=source_ref ), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementLocalsDictSync( locals_scope=provider.getLocalsScope(), locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), source_ref=source_ref, ), ) final = ( StatementReleaseVariable(variable=source_variable, source_ref=source_ref), StatementReleaseVariable( variable=globals_keeper_variable, source_ref=source_ref ), StatementReleaseVariable( variable=locals_keeper_variable, source_ref=source_ref ), StatementReleaseVariable( variable=plain_indicator_variable, source_ref=source_ref ), ) return makeTryFinallyStatement( provider=provider, tried=tried, final=final, source_ref=source_ref ) # This is here, to make sure it can register, pylint: disable=W0611 import nuitka.optimizations.OptimizeBuiltinCalls # isort:skip Nuitka-0.6.19.1/nuitka/tree/ReformulationDictionaryCreation.py0000600000372100037210000002565314166627112031447 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of dictionary creations. Dictionary creations might be directly translated to constants, or they might become nodes that build dictionaries. For Python3.5, unpacking can happen while creating dictionaries, these are being re-formulated to an internal function. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import makeExpressionAttributeLookup from nuitka.nodes.BuiltinIteratorNodes import ExpressionBuiltinIter1 from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTuple from nuitka.nodes.DictionaryNodes import ( ExpressionKeyValuePair, StatementDictOperationUpdate, makeExpressionMakeDict, makeExpressionMakeDictOrConstant, makeExpressionPairs, ) from nuitka.nodes.ExceptionNodes import ( ExpressionBuiltinMakeException, StatementRaiseException, ) from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCall, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.OperatorNodes import makeBinaryOperationNode from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.TypeNodes import ExpressionBuiltinType1 from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableRef, ) from nuitka.PythonVersions import python_version from nuitka.specs.ParameterSpecs import ParameterSpec from .InternalModule import ( internal_source_ref, makeInternalHelperFunctionBody, once_decorator, ) from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildNodeList, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, ) def buildDictionaryNode(provider, node, source_ref): if python_version >= 0x350: for key in node.keys: if key is None: return buildDictionaryUnpacking( provider=provider, node=node, source_ref=source_ref ) return makeExpressionMakeDictOrConstant( pairs=makeExpressionPairs( keys=buildNodeList(provider, node.keys, source_ref), values=buildNodeList(provider, node.values, source_ref), ), user_provided=True, source_ref=source_ref, ) @once_decorator def getDictUnpackingHelper(): helper_name = "_unpack_dict" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=(), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "keys") loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), makeTryExceptSingleHandlerNode( tried=StatementDictOperationUpdate( dict_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), exception_name="AttributeError", handler_body=StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=( makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant="""\ '%s' object is not a mapping""", source_ref=internal_source_ref, user_provided=True, ), right=makeExpressionMakeTuple( elements=( makeExpressionAttributeLookup( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), attribute_name="__name__", source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) args_variable = result.getVariableForAssignment(variable_name="args") final = ( StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant={}, source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ), ) return result def buildDictionaryUnpackingArgs(provider, keys, values, source_ref): result = [] for key, value in zip(keys, values): # TODO: We could be a lot cleverer about the dictionaries for non-starred # arguments, but lets get this to work first. if key is None: result.append(buildNode(provider, value, source_ref)) elif type(key) is str: result.append( makeExpressionMakeDict( pairs=( ExpressionKeyValuePair( key=makeConstantRefNode( constant=key, source_ref=source_ref ), value=buildNode(provider, value, source_ref), source_ref=source_ref, ), ), source_ref=source_ref, ) ) else: result.append( makeExpressionMakeDict( pairs=( ExpressionKeyValuePair( key=buildNode(provider, key, source_ref), value=buildNode(provider, value, source_ref), source_ref=source_ref, ), ), source_ref=source_ref, ) ) return result def buildDictionaryUnpacking(provider, node, source_ref): helper_args = buildDictionaryUnpackingArgs( provider, node.keys, node.values, source_ref ) result = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getDictUnpackingHelper(), source_ref=source_ref ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=(makeExpressionMakeTuple(helper_args, source_ref),), source_ref=source_ref, ) result.setCompatibleSourceReference(helper_args[-1].getCompatibleSourceReference()) return result Nuitka-0.6.19.1/nuitka/tree/ReformulationYieldExpressions.py0000600000372100037210000000602014166627112031151 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of "yield" and "yield from" expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ import ast from nuitka.nodes.ConstantRefNodes import ExpressionConstantNoneRef from nuitka.nodes.YieldNodes import ExpressionYield, ExpressionYieldFrom from nuitka.PythonVersions import python_version from .SyntaxErrors import raiseSyntaxError from .TreeHelpers import buildNode def _checkInsideGenerator(provider, node, source_ref): if provider.isCompiledPythonModule(): raiseSyntaxError( "'yield' outside function", source_ref.atColumnNumber(node.col_offset) ) # This yield is forbidden in 3.5, but allowed in 3.6, but yield_from # is neither. if provider.isExpressionAsyncgenObjectBody() and ( node.__class__ is not ast.Yield or python_version < 0x360 ): raiseSyntaxError( "'%s' inside async function" % ("yield" if node.__class__ is ast.Yield else "yield from",), source_ref.atColumnNumber(node.col_offset), ) if ( python_version >= 0x380 and provider.isExpressionGeneratorObjectBody() and provider.name == "" ): raiseSyntaxError( "'%s' inside generator expression" % ("yield" if node.__class__ is ast.Yield else "yield from",), provider.getSourceReference(), ) assert ( provider.isExpressionGeneratorObjectBody() or provider.isExpressionAsyncgenObjectBody() ), provider def buildYieldNode(provider, node, source_ref): _checkInsideGenerator(provider, node, source_ref) if node.value is not None: return ExpressionYield( expression=buildNode(provider, node.value, source_ref), source_ref=source_ref, ) else: return ExpressionYield( expression=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ) def buildYieldFromNode(provider, node, source_ref): assert python_version >= 0x300 _checkInsideGenerator(provider, node, source_ref) return ExpressionYieldFrom( expression=buildNode(provider, node.value, source_ref), source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/tree/ReformulationBooleanExpressions.py0000600000372100037210000000560414166627112031471 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of boolean and/or expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.ConditionalNodes import ( ExpressionConditionalAnd, ExpressionConditionalOr, makeNotExpression, ) from .TreeHelpers import buildNode, buildNodeList, getKind def buildBoolOpNode(provider, node, source_ref): bool_op = getKind(node.op) if bool_op == "Or": # The "or" may be short circuit and is therefore not a plain operation. values = buildNodeList(provider, node.values, source_ref) for value in values[:-1]: value.setCompatibleSourceReference(values[-1].getSourceReference()) source_ref = values[-1].getSourceReference() return makeOrNode(values=values, source_ref=source_ref) elif bool_op == "And": # The "and" may be short circuit and is therefore not a plain operation. values = buildNodeList(provider, node.values, source_ref) for value in values[:-1]: value.setCompatibleSourceReference(values[-1].getSourceReference()) source_ref = values[-1].getSourceReference() return makeAndNode(values=values, source_ref=source_ref) elif bool_op == "Not": # The "not" is really only a unary operation and no special. return makeNotExpression( expression=buildNode(provider, node.operand, source_ref) ) else: assert False, bool_op def makeOrNode(values, source_ref): values = list(values) result = values.pop() # When we encounter, "or", we expect it to be at least two values. assert values while values: result = ExpressionConditionalOr( left=values.pop(), right=result, source_ref=source_ref ) return result def makeAndNode(values, source_ref): values = list(values) result = values.pop() # Unlike "or", for "and", this is used with only one value. while values: result = ExpressionConditionalAnd( left=values.pop(), right=result, source_ref=source_ref ) return result Nuitka-0.6.19.1/nuitka/tree/ReformulationLambdaExpressions.py0000600000372100037210000001460414166627112031272 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of lambda expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.ComparisonNodes import ExpressionComparisonIsNot from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import ExpressionConstantNoneRef from nuitka.nodes.FrameNodes import ( StatementsFrameFunction, StatementsFrameGenerator, ) from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.GeneratorNodes import ( ExpressionGeneratorObjectBody, ExpressionMakeGeneratorObject, ) from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.StatementNodes import StatementExpressionOnly from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.nodes.YieldNodes import ExpressionYield from nuitka.PythonVersions import python_version from .ReformulationFunctionStatements import ( buildFunctionWithParsing, buildParameterAnnotations, buildParameterKwDefaults, ) from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildNodeList, detectFunctionBodyKind, getKind, makeStatementsSequenceFromStatement, mergeStatements, ) def buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=too-many-locals assert getKind(node) == "Lambda" function_kind, flags = detectFunctionBodyKind(nodes=(node.body,)) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name="", function_doc=None, flags=flags, node=node, source_ref=source_ref, ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name="", code_object=code_object, flags=None, auto_release=None, source_ref=source_ref, ) code_body.qualname_provider = provider if function_kind == "Generator": function_body.setChild( "body", makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ), ) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=function_body, source_ref=source_ref ) body = buildNode(provider=code_body, node=node.body, source_ref=source_ref) if function_kind == "Generator": if python_version < 0x270: tmp_return_value = code_body.allocateTempVariable( temp_scope=None, name="yield_return" ) statements = ( StatementAssignmentVariable( variable=tmp_return_value, source=body, source_ref=source_ref ), makeStatementConditional( condition=ExpressionComparisonIsNot( left=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionYield( expression=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ) body = makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ) else: body = StatementExpressionOnly(expression=body, source_ref=source_ref) else: body = StatementReturn(expression=body, source_ref=source_ref) if function_kind == "Generator": frame_class = StatementsFrameGenerator else: frame_class = StatementsFrameFunction body = frame_class( statements=mergeStatements((body,)), code_object=code_object, source_ref=body.getSourceReference(), ) body = makeStatementsSequenceFromStatement(statement=body) code_body.setChild("body", body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=outer_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/ReformulationSubscriptExpressions.py0000600000372100037210000001132014166627112032060 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of subscript into slicing. For Python2, there is a difference between x[a], x[a:b], x[a:b:c] whereas Python3 treats the later by making a slice object, Python2 tries to have special slice access, if available, or building a slice object only at the end. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.ConstantRefNodes import ExpressionConstantEllipsisRef from nuitka.nodes.SliceNodes import ( ExpressionSliceLookup, makeExpressionBuiltinSlice, ) from nuitka.nodes.SubscriptNodes import ExpressionSubscriptLookup from nuitka.PythonVersions import python_version from .ReformulationAssignmentStatements import buildExtSliceNode from .TreeHelpers import buildNode, getKind def buildSubscriptNode(provider, node, source_ref): # Subscript expression nodes, various types are dispatched here. assert getKind(node.ctx) == "Load", source_ref # The subscript "[]" operator is one of many different things. This is # expressed by this kind, there are "slice" lookups (two values, even if one # is using default), and then "index" lookups. The form with three argument # is really an "index" lookup, with a slice object. And the "..." lookup is # also an index loop-up, with it as the argument. So this splits things into # two different operations, "subscript" with a single "subscript" object. Or # a slice lookup with a lower and higher boundary. These things should # behave similar, but they are different slots. kind = getKind(node.slice) if kind == "Index": return ExpressionSubscriptLookup( expression=buildNode(provider, node.value, source_ref), subscript=buildNode(provider, node.slice.value, source_ref), source_ref=source_ref, ) elif kind == "Slice": lower = buildNode( provider=provider, node=node.slice.lower, source_ref=source_ref, allow_none=True, ) upper = buildNode( provider=provider, node=node.slice.upper, source_ref=source_ref, allow_none=True, ) step = buildNode( provider=provider, node=node.slice.step, source_ref=source_ref, allow_none=True, ) # For Python3 there is no slicing operation, this is always done # with subscript using a slice object. For Python2, it is only done # if no "step" is provided. use_sliceobj = step is not None or python_version >= 0x300 if use_sliceobj: return ExpressionSubscriptLookup( expression=buildNode(provider, node.value, source_ref), subscript=makeExpressionBuiltinSlice( start=lower, stop=upper, step=step, source_ref=source_ref ), source_ref=source_ref, ) else: return ExpressionSliceLookup( expression=buildNode(provider, node.value, source_ref), lower=lower, upper=upper, source_ref=source_ref, ) elif kind == "ExtSlice": return ExpressionSubscriptLookup( expression=buildNode(provider, node.value, source_ref), subscript=buildExtSliceNode(provider, node, source_ref), source_ref=source_ref, ) elif kind == "Ellipsis": return ExpressionSubscriptLookup( expression=buildNode(provider, node.value, source_ref), subscript=ExpressionConstantEllipsisRef(source_ref=source_ref), source_ref=source_ref, ) elif python_version >= 0x390: return ExpressionSubscriptLookup( expression=buildNode(provider, node.value, source_ref), subscript=buildNode(provider, node.slice, source_ref), source_ref=source_ref, ) else: assert False, kind Nuitka-0.6.19.1/nuitka/tree/ReformulationNamespacePackages.py0000600000372100037210000001742214166627112031203 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Namespace packages of Python3.3 or higher """ import os from nuitka import Options from nuitka.nodes.AssignNodes import StatementAssignmentVariableName from nuitka.nodes.AttributeNodes import makeExpressionAttributeLookup from nuitka.nodes.CallNodes import ExpressionCallNoKeywords from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import ( makeExpressionMakeList, makeExpressionMakeTuple, makeExpressionMakeTupleOrConstant, ) from nuitka.nodes.DictionaryNodes import StatementDictOperationSet from nuitka.nodes.FutureSpecs import FutureSpec from nuitka.nodes.ImportNodes import ( ExpressionImportModuleNameHard, ExpressionImportName, makeExpressionImportModuleFixed, ) from nuitka.nodes.ModuleAttributeNodes import ( ExpressionModuleAttributeFileRef, ExpressionNuitkaLoaderCreation, ) from nuitka.nodes.ModuleNodes import CompiledPythonPackage from nuitka.nodes.SubscriptNodes import ExpressionSubscriptLookup from nuitka.nodes.VariableRefNodes import ExpressionVariableNameRef from nuitka.PythonVersions import python_version from .TreeHelpers import makeStatementsSequenceFromStatement from .VariableClosure import completeVariableClosures def _makeCall(module_name, import_name, attribute_name, source_ref, *args): return ExpressionCallNoKeywords( called=makeExpressionAttributeLookup( expression=ExpressionImportModuleNameHard( module_name=module_name, import_name=import_name, source_ref=source_ref ), attribute_name=attribute_name, source_ref=source_ref, ), args=makeExpressionMakeTupleOrConstant( elements=args, user_provided=True, source_ref=source_ref ), source_ref=source_ref, ) def getNameSpacePathExpression(package, source_ref): """Create the __path__ expression for a package.""" reference_mode = Options.getFileReferenceMode() if reference_mode == "original": return makeConstantRefNode( constant=[package.getCompileTimeDirectory()], source_ref=source_ref, ) elif reference_mode == "frozen": return makeConstantRefNode( constant=[], source_ref=source_ref, ) else: elements = [ ExpressionCallNoKeywords( called=makeExpressionAttributeLookup( expression=ExpressionImportModuleNameHard( module_name="os", import_name="path", source_ref=source_ref ), attribute_name="dirname", source_ref=source_ref, ), args=makeExpressionMakeTuple( elements=( ExpressionModuleAttributeFileRef( variable=package.getVariableForReference("__file__"), source_ref=source_ref, ), ), source_ref=source_ref, ), source_ref=source_ref, ) ] if package.canHaveExternalImports(): parts = package.getFullName().asString().split(".") for count in range(len(parts)): path_part = _makeCall( "os", "environ", "get", source_ref, makeConstantRefNode( constant="NUITKA_PACKAGE_%s" % "_".join(parts[: count + 1]), source_ref=source_ref, ), makeConstantRefNode(constant="/notexist", source_ref=source_ref), ) if parts[count + 1 :]: path_part = _makeCall( "os", "path", "join", source_ref, path_part, makeConstantRefNode( constant=os.path.join(*parts[count + 1 :]), source_ref=source_ref, ), ) elements.append(path_part) return makeExpressionMakeList(elements=elements, source_ref=source_ref) def createPathAssignment(package, source_ref): return StatementAssignmentVariableName( provider=package, variable_name="__path__", source=getNameSpacePathExpression(package=package, source_ref=source_ref), source_ref=source_ref, ) def createPython3NamespacePath(package, source_ref): return StatementAssignmentVariableName( provider=package, variable_name="__path__", source=ExpressionCallNoKeywords( called=ExpressionImportName( module=makeExpressionImportModuleFixed( module_name="_frozen_importlib" if python_version < 0x350 else "_frozen_importlib_external", source_ref=source_ref, ), import_name="_NamespacePath", level=0, source_ref=source_ref, ), args=makeExpressionMakeTupleOrConstant( elements=( makeConstantRefNode( constant=package.getFullName().asString(), user_provided=True, source_ref=source_ref, ), getNameSpacePathExpression(package=package, source_ref=source_ref), makeConstantRefNode(constant=None, source_ref=source_ref), ), user_provided=True, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ) def createNamespacePackage(module_name, is_top, source_ref): package = CompiledPythonPackage( module_name=module_name, is_top=is_top, mode="compiled", future_spec=FutureSpec(), source_ref=source_ref, ) if python_version >= 0x300: statement = createPython3NamespacePath(package=package, source_ref=source_ref) else: statement = createPathAssignment(package, source_ref) package.setChild("body", makeStatementsSequenceFromStatement(statement=statement)) completeVariableClosures(package) return package def createImporterCacheAssignment(package, source_ref): return StatementDictOperationSet( dict_arg=ExpressionImportModuleNameHard( module_name="sys", import_name="path_importer_cache", source_ref=source_ref ), key=ExpressionSubscriptLookup( expression=ExpressionVariableNameRef( provider=package, variable_name="__path__", source_ref=source_ref ), subscript=makeConstantRefNode(constant=0, source_ref=source_ref), source_ref=source_ref, ), value=ExpressionNuitkaLoaderCreation(provider=package, source_ref=source_ref), source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/Building.py0000600000372100037210000012617514166627112024644 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Build the internal node tree from source code. Does all the Python parsing and puts it into a tree structure for use in later stages of the compilation process. In the "nuitka.tree.TreeHelpers" module, the dispatching is happening. One function deals with every node kind as found in the AST. The parsing is centered around the module "ast" output. Many higher level language features and translated into lower level ones. In-place assignments, for loops, while loops, classes, complex calls, with statements, and even or/and etc. are all translated to simpler constructs. The output of this module is a node tree, which contains only relatively low level operations. A property of the output is also an overlaid tree of provider structure that indicates variable provision. Classes are handled in a separate module. They are re-formulated into functions producing dictionaries used to call the metaclass with. Try/except/else statements are handled in a separate module. They are re-formulated into using a temporary variable to track if the else branch should execute. Try/finally statements are handled in a separate module. They are re-formulated to use a nested try/finally for (un)publishing the exception for Python3. With statements are handled in a separate module. They are re-formulated into special attribute lookups for "__enter__" and "__exit__", calls of them, catching and passing in exceptions raised. """ import marshal import os from nuitka import ( ModuleRegistry, Options, OutputDirectories, SourceCodeReferences, ) from nuitka.__past__ import long, unicode from nuitka.Caching import ( getCachedImportedModulesNames, hasCachedImportedModulesNames, ) from nuitka.containers.oset import OrderedSet from nuitka.Errors import CodeTooComplexCode from nuitka.freezer.Standalone import detectEarlyImports from nuitka.importing import Importing from nuitka.importing.ImportCache import addImportedModule from nuitka.importing.PreloadedPackages import getPthImportedPackages from nuitka.nodes.AssignNodes import StatementAssignmentVariableName from nuitka.nodes.AttributeNodes import ( StatementAssignmentAttribute, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinFormatNodes import ( ExpressionBuiltinAscii, ExpressionBuiltinFormat, ) from nuitka.nodes.BuiltinRefNodes import quick_names from nuitka.nodes.BuiltinTypeNodes import ExpressionBuiltinStrP3 from nuitka.nodes.ConditionalNodes import ( ExpressionConditional, makeStatementConditional, ) from nuitka.nodes.ConstantRefNodes import ( ExpressionConstantEllipsisRef, ExpressionConstantNoneRef, makeConstantRefNode, ) from nuitka.nodes.CoroutineNodes import ExpressionAsyncWait from nuitka.nodes.ExceptionNodes import ( StatementRaiseException, StatementReraiseException, ) from nuitka.nodes.FutureSpecs import FutureSpec from nuitka.nodes.GeneratorNodes import StatementGeneratorReturn from nuitka.nodes.ImportNodes import ( isHardModuleWithoutSideEffect, makeExpressionImportModuleFixed, ) from nuitka.nodes.LoopNodes import StatementLoopBreak, StatementLoopContinue from nuitka.nodes.ModuleAttributeNodes import ( ExpressionModuleAttributeFileRef, ExpressionModuleAttributeSpecRef, ) from nuitka.nodes.ModuleNodes import ( CompiledPythonModule, CompiledPythonPackage, PythonMainModule, PythonShlibModule, makeUncompiledPythonModule, ) from nuitka.nodes.NodeMakingHelpers import ( makeRaiseExceptionStatementFromInstance, ) from nuitka.nodes.OperatorNodes import makeBinaryOperationNode from nuitka.nodes.OperatorNodesUnary import makeExpressionOperationUnary from nuitka.nodes.ReturnNodes import makeStatementReturn from nuitka.nodes.SliceNodes import makeExpressionBuiltinSlice from nuitka.nodes.StatementNodes import StatementExpressionOnly from nuitka.nodes.StringConcatenationNodes import ExpressionStringConcatenation from nuitka.nodes.VariableRefNodes import ExpressionVariableNameRef from nuitka.nodes.YieldNodes import ExpressionYieldFromWaitable from nuitka.optimizations.BytecodeDemotion import demoteSourceCodeToBytecode from nuitka.Options import shallWarnUnusualCode from nuitka.pgo.PGO import decideCompilationFromPGO from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version from nuitka.Tracing import ( general, memory_logger, optimization_logger, plugins_logger, recursion_logger, unusual_logger, ) from nuitka.utils import MemoryUsage from nuitka.utils.ModuleNames import ModuleName from . import SyntaxErrors from .ReformulationAssertStatements import buildAssertNode from .ReformulationAssignmentStatements import ( buildAnnAssignNode, buildAssignNode, buildDeleteNode, buildInplaceAssignNode, buildNamedExprNode, ) from .ReformulationBooleanExpressions import buildBoolOpNode from .ReformulationCallExpressions import buildCallNode from .ReformulationClasses import buildClassNode from .ReformulationComparisonExpressions import buildComparisonNode from .ReformulationContractionExpressions import ( buildDictContractionNode, buildGeneratorExpressionNode, buildListContractionNode, buildSetContractionNode, ) from .ReformulationDictionaryCreation import buildDictionaryNode from .ReformulationExecStatements import buildExecNode from .ReformulationForLoopStatements import ( buildAsyncForLoopNode, buildForLoopNode, ) from .ReformulationFunctionStatements import ( buildAsyncFunctionNode, buildFunctionNode, ) from .ReformulationImportStatements import ( buildImportFromNode, buildImportModulesNode, checkFutureImportsOnlyAtStart, getFutureSpec, popFutureSpec, pushFutureSpec, ) from .ReformulationLambdaExpressions import buildLambdaNode from .ReformulationMatchStatements import buildMatchNode from .ReformulationNamespacePackages import ( createImporterCacheAssignment, createNamespacePackage, createPathAssignment, ) from .ReformulationPrintStatements import buildPrintNode from .ReformulationSequenceCreation import ( buildListCreationNode, buildSetCreationNode, buildTupleCreationNode, ) from .ReformulationSubscriptExpressions import buildSubscriptNode from .ReformulationTryExceptStatements import buildTryExceptionNode from .ReformulationTryFinallyStatements import buildTryFinallyNode from .ReformulationWhileLoopStatements import buildWhileLoopNode from .ReformulationWithStatements import buildAsyncWithNode, buildWithNode from .ReformulationYieldExpressions import buildYieldFromNode, buildYieldNode from .SourceReading import ( checkPythonVersionFromCode, readSourceCodeFromFilename, ) from .TreeHelpers import ( buildNode, buildNodeList, buildStatementsNode, extractDocFromBody, getBuildContext, getKind, makeModuleFrame, makeStatementsSequence, makeStatementsSequenceFromStatement, mangleName, mergeStatements, parseSourceCodeToAst, setBuildingDispatchers, ) from .VariableClosure import completeVariableClosures if str is not bytes: def buildVariableReferenceNode(provider, node, source_ref): # Shortcut for Python3, which gives syntax errors for assigning these. if node.id in quick_names: return makeConstantRefNode( constant=quick_names[node.id], source_ref=source_ref ) return ExpressionVariableNameRef( provider=provider, variable_name=mangleName(node.id, provider), source_ref=source_ref, ) else: def buildVariableReferenceNode(provider, node, source_ref): return ExpressionVariableNameRef( provider=provider, variable_name=mangleName(node.id, provider), source_ref=source_ref, ) # Python3.4 or higher, True and False, are not given as variables anymore. # Python3.8, all kinds of constants are like this. def buildNamedConstantNode(node, source_ref): return makeConstantRefNode( constant=node.value, source_ref=source_ref, user_provided=True ) def buildConditionNode(provider, node, source_ref): # Conditional statements may have one or two branches. We will never see an # "elif", because that's already dealt with by module "ast", which turns it # into nested conditional statements. return makeStatementConditional( condition=buildNode(provider, node.test, source_ref), yes_branch=buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref ), no_branch=buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref, ), source_ref=source_ref, ) def buildTryFinallyNode2(provider, node, source_ref): # Try/finally node statements of old style. return buildTryFinallyNode( provider=provider, build_tried=lambda: buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref ), node=node, source_ref=source_ref, ) def buildTryNode(provider, node, source_ref): # Note: This variant is used for Python3.3 or higher only, older stuff uses # the above ones, this one merges try/except with try/finally in the # "ast". We split it up again, as it's logically separated of course. # Shortcut missing try/finally. if not node.handlers: return buildTryFinallyNode2(provider, node, source_ref) if not node.finalbody: return buildTryExceptionNode( provider=provider, node=node, source_ref=source_ref ) return buildTryFinallyNode( provider=provider, build_tried=lambda: makeStatementsSequence( statements=mergeStatements( ( buildTryExceptionNode( provider=provider, node=node, source_ref=source_ref ), ), allow_none=True, ), allow_none=True, source_ref=source_ref, ), node=node, source_ref=source_ref, ) def buildRaiseNode(provider, node, source_ref): # Raise statements. Under Python2 they may have type, value and traceback # attached, for Python3, you can only give type (actually value) and cause. if python_version < 0x300: exception_type = buildNode(provider, node.type, source_ref, allow_none=True) exception_value = buildNode(provider, node.inst, source_ref, allow_none=True) exception_trace = buildNode(provider, node.tback, source_ref, allow_none=True) exception_cause = None else: exception_type = buildNode(provider, node.exc, source_ref, allow_none=True) exception_value = None exception_trace = None exception_cause = buildNode(provider, node.cause, source_ref, allow_none=True) if exception_type is None: assert exception_value is None assert exception_trace is None assert exception_cause is None result = StatementReraiseException(source_ref=source_ref) else: result = StatementRaiseException( exception_type=exception_type, exception_value=exception_value, exception_trace=exception_trace, exception_cause=exception_cause, source_ref=source_ref, ) if exception_cause is not None: result.setCompatibleSourceReference( source_ref=exception_cause.getCompatibleSourceReference() ) elif exception_trace is not None: result.setCompatibleSourceReference( source_ref=exception_trace.getCompatibleSourceReference() ) elif exception_value is not None: result.setCompatibleSourceReference( source_ref=exception_value.getCompatibleSourceReference() ) elif exception_type is not None: result.setCompatibleSourceReference( source_ref=exception_type.getCompatibleSourceReference() ) return result def handleGlobalDeclarationNode(provider, node, source_ref): # On the module level, there is nothing to do. if provider.isCompiledPythonModule(): if shallWarnUnusualCode(): unusual_logger.warning( "%s: Using 'global' statement on module level has no effect." % source_ref.getAsString(), ) return None # Need to catch the error of declaring a parameter variable as global # ourselves here. The AST parsing doesn't catch it, so we check here. if provider.isExpressionFunctionBody(): parameters = provider.getParameters() for variable_name in node.names: if variable_name in parameters.getParameterNames(): SyntaxErrors.raiseSyntaxError( "name '%s' is %s and global" % ( variable_name, "local" if python_version < 0x300 else "parameter", ), source_ref.atColumnNumber(node.col_offset), ) # The module the "global" statement refers to. module = provider.getParentModule() # Can give multiple names. for variable_name in node.names: closure_variable = None # Re-use already taken global variables, in order to avoid creating yet # another instance, esp. as the indications could then potentially not # be shared. if provider.hasTakenVariable(variable_name): closure_variable = provider.getTakenVariable(variable_name) # Only global variables count. Could have a closure reference to # a location of a parent function here. if not closure_variable.isModuleVariable(): closure_variable = None if closure_variable is None: module_variable = module.getVariableForAssignment( variable_name=variable_name ) closure_variable = provider.addClosureVariable(variable=module_variable) assert closure_variable.isModuleVariable() if ( python_version < 0x340 and provider.isExpressionClassBody() and closure_variable.getName() == "__class__" ): SyntaxErrors.raiseSyntaxError("cannot make __class__ global", source_ref) provider.getLocalsScope().registerClosureVariable(variable=closure_variable) # Drop this, not really part of our tree. return None def handleNonlocalDeclarationNode(provider, node, source_ref): # Need to catch the error of declaring a parameter variable as global # ourselves here. The AST parsing doesn't catch it, but we can do it here. parameter_provider = provider while ( parameter_provider.isExpressionGeneratorObjectBody() or parameter_provider.isExpressionCoroutineObjectBody() or parameter_provider.isExpressionAsyncgenObjectBody() ): parameter_provider = parameter_provider.getParentVariableProvider() if parameter_provider.isExpressionClassBody(): parameter_names = () else: parameter_names = parameter_provider.getParameters().getParameterNames() for variable_name in node.names: if variable_name in parameter_names: SyntaxErrors.raiseSyntaxError( "name '%s' is parameter and nonlocal" % (variable_name), source_ref.atColumnNumber(node.col_offset), ) provider.addNonlocalsDeclaration( names=tuple(node.names), user_provided=True, source_ref=source_ref.atColumnNumber(node.col_offset), ) # Drop this, not really part of our tree. return None def buildStringNode(node, source_ref): assert type(node.s) in (str, unicode) return makeConstantRefNode( constant=node.s, source_ref=source_ref, user_provided=True ) def buildNumberNode(node, source_ref): assert type(node.n) in (int, long, float, complex), type(node.n) return makeConstantRefNode( constant=node.n, source_ref=source_ref, user_provided=True ) def buildBytesNode(node, source_ref): return makeConstantRefNode( constant=node.s, source_ref=source_ref, user_provided=True ) def buildEllipsisNode(source_ref): return ExpressionConstantEllipsisRef(source_ref=source_ref) def buildStatementLoopContinue(node, source_ref): source_ref = source_ref.atColumnNumber(node.col_offset) # Python forbids this, although technically it's probably not much of # an issue. if getBuildContext() == "finally" and python_version < 0x380: SyntaxErrors.raiseSyntaxError( "'continue' not supported inside 'finally' clause", source_ref ) return StatementLoopContinue(source_ref=source_ref) def buildStatementLoopBreak(provider, node, source_ref): # A bit unusual, we need the provider, but not the node, # pylint: disable=unused-argument return StatementLoopBreak(source_ref=source_ref.atColumnNumber(node.col_offset)) def buildAttributeNode(provider, node, source_ref): return makeExpressionAttributeLookup( expression=buildNode(provider, node.value, source_ref), attribute_name=mangleName(node.attr, provider), source_ref=source_ref, ) def buildReturnNode(provider, node, source_ref): if provider.isExpressionClassBody() or provider.isCompiledPythonModule(): SyntaxErrors.raiseSyntaxError( "'return' outside function", source_ref.atColumnNumber(node.col_offset) ) expression = buildNode(provider, node.value, source_ref, allow_none=True) if provider.isExpressionGeneratorObjectBody(): if expression is not None and python_version < 0x300: SyntaxErrors.raiseSyntaxError( "'return' with argument inside generator", source_ref.atColumnNumber(node.col_offset), ) if provider.isExpressionAsyncgenObjectBody(): if expression is not None: SyntaxErrors.raiseSyntaxError( "'return' with value in async generator", source_ref.atColumnNumber(node.col_offset), ) if ( provider.isExpressionGeneratorObjectBody() or provider.isExpressionAsyncgenObjectBody() ): if expression is None: expression = ExpressionConstantNoneRef(source_ref=source_ref) return StatementGeneratorReturn(expression=expression, source_ref=source_ref) else: return makeStatementReturn(expression=expression, source_ref=source_ref) def buildExprOnlyNode(provider, node, source_ref): result = StatementExpressionOnly( expression=buildNode(provider, node.value, source_ref), source_ref=source_ref ) result.setCompatibleSourceReference( result.subnode_expression.getCompatibleSourceReference() ) return result def buildUnaryOpNode(provider, node, source_ref): operator = getKind(node.op) # Delegate this one to boolean operation code. if operator == "Not": return buildBoolOpNode(provider=provider, node=node, source_ref=source_ref) operand = buildNode(provider, node.operand, source_ref) return makeExpressionOperationUnary( operator=operator, operand=operand, source_ref=source_ref ) def buildBinaryOpNode(provider, node, source_ref): operator = getKind(node.op) if operator == "Div": operator = "TrueDiv" if getFutureSpec().isFutureDivision() else "OldDiv" left = buildNode(provider, node.left, source_ref) right = buildNode(provider, node.right, source_ref) result = makeBinaryOperationNode( operator=operator, left=left, right=right, source_ref=source_ref ) result.setCompatibleSourceReference(source_ref=right.getCompatibleSourceReference()) return result def buildReprNode(provider, node, source_ref): return makeExpressionOperationUnary( operator="Repr", operand=buildNode(provider, node.value, source_ref), source_ref=source_ref, ) def buildConditionalExpressionNode(provider, node, source_ref): return ExpressionConditional( condition=buildNode(provider, node.test, source_ref), expression_yes=buildNode(provider, node.body, source_ref), expression_no=buildNode(provider, node.orelse, source_ref), source_ref=source_ref, ) def buildAwaitNode(provider, node, source_ref): return ExpressionYieldFromWaitable( expression=ExpressionAsyncWait( expression=buildNode(provider, node.value, source_ref), source_ref=source_ref, ), source_ref=source_ref, ) def buildFormattedValueNode(provider, node, source_ref): value = buildNode(provider, node.value, source_ref) conversion = node.conversion % 4 if node.conversion > 0 else 0 if conversion == 0: pass elif conversion == 3: # TODO: We might start using this for Python2 too. assert str is not bytes value = ExpressionBuiltinStrP3( value=value, encoding=None, errors=None, source_ref=source_ref ) elif conversion == 2: value = makeExpressionOperationUnary( operator="Repr", operand=value, source_ref=source_ref ) elif conversion == 1: value = ExpressionBuiltinAscii(value=value, source_ref=source_ref) else: assert False, conversion return ExpressionBuiltinFormat( value=value, format_spec=buildNode(provider, node.format_spec, source_ref, allow_none=True), source_ref=source_ref, ) def buildJoinedStrNode(provider, node, source_ref): if node.values: return ExpressionStringConcatenation( values=buildNodeList(provider, node.values, source_ref), source_ref=source_ref, ) else: return makeConstantRefNode(constant="", source_ref=source_ref) def buildSliceNode(provider, node, source_ref): """Python3.9 or higher, slice notations.""" return makeExpressionBuiltinSlice( start=buildNode(provider, node.lower, source_ref, allow_none=True), stop=buildNode(provider, node.upper, source_ref, allow_none=True), step=buildNode(provider, node.step, source_ref, allow_none=True), source_ref=source_ref, ) setBuildingDispatchers( path_args3={ "Name": buildVariableReferenceNode, "Assign": buildAssignNode, "AnnAssign": buildAnnAssignNode, "Delete": buildDeleteNode, "Lambda": buildLambdaNode, "GeneratorExp": buildGeneratorExpressionNode, "If": buildConditionNode, "While": buildWhileLoopNode, "For": buildForLoopNode, "AsyncFor": buildAsyncForLoopNode, "Compare": buildComparisonNode, "ListComp": buildListContractionNode, "DictComp": buildDictContractionNode, "SetComp": buildSetContractionNode, "Dict": buildDictionaryNode, "Set": buildSetCreationNode, "Tuple": buildTupleCreationNode, "List": buildListCreationNode, "Global": handleGlobalDeclarationNode, "Nonlocal": handleNonlocalDeclarationNode, "TryExcept": buildTryExceptionNode, "TryFinally": buildTryFinallyNode2, "Try": buildTryNode, "Raise": buildRaiseNode, "Import": buildImportModulesNode, "ImportFrom": buildImportFromNode, "Assert": buildAssertNode, "Exec": buildExecNode, "With": buildWithNode, "AsyncWith": buildAsyncWithNode, "FunctionDef": buildFunctionNode, "AsyncFunctionDef": buildAsyncFunctionNode, "Await": buildAwaitNode, "ClassDef": buildClassNode, "Print": buildPrintNode, "Call": buildCallNode, "Subscript": buildSubscriptNode, "BoolOp": buildBoolOpNode, "Attribute": buildAttributeNode, "Return": buildReturnNode, "Yield": buildYieldNode, "YieldFrom": buildYieldFromNode, "Expr": buildExprOnlyNode, "UnaryOp": buildUnaryOpNode, "BinOp": buildBinaryOpNode, "Repr": buildReprNode, "AugAssign": buildInplaceAssignNode, "IfExp": buildConditionalExpressionNode, "Break": buildStatementLoopBreak, "JoinedStr": buildJoinedStrNode, "FormattedValue": buildFormattedValueNode, "NamedExpr": buildNamedExprNode, "Slice": buildSliceNode, "Match": buildMatchNode, }, path_args2={ "Constant": buildNamedConstantNode, # Python3.8 "NameConstant": buildNamedConstantNode, # Python3.8 or below "Str": buildStringNode, "Num": buildNumberNode, "Bytes": buildBytesNode, "Continue": buildStatementLoopContinue, }, path_args1={"Ellipsis": buildEllipsisNode}, ) def buildParseTree(provider, ast_tree, source_ref, is_module, is_main): # There are a bunch of branches here, mostly to deal with version # differences for module default variables. pylint: disable=too-many-branches # Maybe one day, we do exec inlining again, that is what this is for, # then is_module won't be True, for now it always is. pushFutureSpec() if is_module: provider.setFutureSpec(getFutureSpec()) body, doc = extractDocFromBody(ast_tree) if is_module and is_main and python_version >= 0x360: provider.markAsNeedsAnnotationsDictionary() result = buildStatementsNode(provider=provider, nodes=body, source_ref=source_ref) # After building, we can verify that all future statements were where they # belong, namely at the start of the module. checkFutureImportsOnlyAtStart(body) internal_source_ref = source_ref.atInternal() statements = [] if is_module: # Add import of "site" module of main programs visibly in the node tree, # so recursion and optimization can pick it up, checking its effects. if is_main and not Options.hasPythonFlagNoSite(): statements.append( StatementExpressionOnly( expression=makeExpressionImportModuleFixed( module_name="site", source_ref=source_ref ), source_ref=source_ref, ) ) for path_imported_name in getPthImportedPackages(): if isHardModuleWithoutSideEffect(path_imported_name): continue statements.append( StatementExpressionOnly( expression=makeExpressionImportModuleFixed( module_name=path_imported_name, source_ref=source_ref ), source_ref=source_ref, ) ) statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__doc__", source=makeConstantRefNode( constant=doc, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ) ) statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__file__", source=ExpressionModuleAttributeFileRef( variable=provider.getVariableForReference("__file__"), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) if provider.isCompiledPythonPackage(): # This assigns "__path__" value. statements.append(createPathAssignment(provider, internal_source_ref)) statements.append( createImporterCacheAssignment(provider, internal_source_ref) ) if python_version >= 0x340 and not is_main: statements += ( StatementAssignmentAttribute( expression=ExpressionModuleAttributeSpecRef( variable=provider.getVariableForReference("__spec__"), source_ref=internal_source_ref, ), attribute_name="origin", source=ExpressionModuleAttributeFileRef( variable=provider.getVariableForReference("__file__"), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentAttribute( expression=ExpressionModuleAttributeSpecRef( variable=provider.getVariableForReference("__spec__"), source_ref=internal_source_ref, ), attribute_name="has_location", source=makeConstantRefNode(True, internal_source_ref), source_ref=internal_source_ref, ), ) if provider.isCompiledPythonPackage(): statements.append( StatementAssignmentAttribute( expression=ExpressionModuleAttributeSpecRef( variable=provider.getVariableForReference("__spec__"), source_ref=internal_source_ref, ), attribute_name="submodule_search_locations", source=ExpressionVariableNameRef( provider=provider, variable_name="__path__", source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) if python_version >= 0x300: statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__cached__", source=ExpressionConstantNoneRef(source_ref=internal_source_ref), source_ref=internal_source_ref, ) ) needs__initializing__ = ( not provider.isMainModule() and 0x300 <= python_version < 0x340 ) if needs__initializing__: # Set "__initializing__" at the beginning to True statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__initializing__", source=makeConstantRefNode( constant=True, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ) ) if provider.needsAnnotationsDictionary(): # Set "__annotations__" on module level to {} statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__annotations__", source=makeConstantRefNode( constant={}, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ) ) # Now the module body if there is any at all. if result is not None: statements.extend(result.subnode_statements) if needs__initializing__: # Set "__initializing__" at the end to False statements.append( StatementAssignmentVariableName( provider=provider, variable_name="__initializing__", source=makeConstantRefNode( constant=False, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ) ) if is_module: result = makeModuleFrame( module=provider, statements=statements, source_ref=source_ref ) popFutureSpec() return result else: assert False def decideCompilationMode(is_top, module_name, for_pgo): """Decide the compilation mode for a module. module_name - The module to decide compilation mode for. for_pgo - consider PGO information or not """ result = Plugins.decideCompilation(module_name) # Cannot change mode of __main__ to bytecode, that is not going # to work currently. if result == "bytecode" and is_top: plugins_logger.warning( """\ Ignoring plugin decision to compile top level package '%s' as bytecode, the extension module entry point is technically required to compiled.""" % module_name ) result = "compiled" # Plugins need to win over PGO, as they might know it better if result is None and not for_pgo: result = decideCompilationFromPGO(module_name=module_name) # Default if neither plugins nor PGO have expressed an opinion if result is None: result = "compiled" return result def _createModule( module_name, source_code, source_ref, is_shlib, is_namespace, is_package, is_top, is_main, main_added, ): # Many details due to the caching done here. # pylint: disable=too-many-locals if is_shlib: result = PythonShlibModule(module_name=module_name, source_ref=source_ref) elif is_main: result = PythonMainModule( main_added=main_added, module_name=module_name, mode=decideCompilationMode( is_top=is_top, module_name=module_name, for_pgo=False ), future_spec=None, source_ref=source_ref, ) checkPythonVersionFromCode(source_code) elif is_namespace: result = createNamespacePackage(module_name, is_top, source_ref) else: mode = decideCompilationMode( is_top=is_top, module_name=module_name, for_pgo=False ) if ( mode == "bytecode" and not is_top and hasCachedImportedModulesNames(module_name, source_code) ): optimization_logger.info( "'%s' is included as bytecode." % (module_name.asString()) ) result = makeUncompiledPythonModule( module_name=module_name, filename=source_ref.getFilename(), bytecode=demoteSourceCodeToBytecode( module_name=module_name, source_code=source_code, filename=source_ref.getFilename(), ), user_provided=False, technical=False, is_package=is_package, ) used_modules = OrderedSet() for used_module_name in getCachedImportedModulesNames( module_name=module_name, source_code=source_code ): (_module_name, module_filename, _finding,) = Importing.locateModule( module_name=used_module_name, parent_package=None, level=0, ) used_modules.add((used_module_name, os.path.relpath(module_filename))) result.setUsedModules(used_modules) # Not used anymore source_code = None else: if is_package: result = CompiledPythonPackage( module_name=module_name, is_top=is_top, mode=mode, future_spec=None, source_ref=source_ref, ) else: result = CompiledPythonModule( module_name=module_name, is_top=is_top, mode=mode, future_spec=None, source_ref=source_ref, ) return result def createModuleTree(module, source_ref, ast_tree, is_main): if Options.isShowMemory(): memory_watch = MemoryUsage.MemoryWatch() module_body = buildParseTree( provider=module, ast_tree=ast_tree, source_ref=source_ref, is_module=True, is_main=is_main, ) if module_body.isStatementsFrame(): module_body = makeStatementsSequenceFromStatement(statement=module_body) module.setChild("body", module_body) completeVariableClosures(module) if Options.isShowMemory(): memory_watch.finish() memory_logger.info( "Memory usage changed loading module '%s': %s" % (module.getFullName(), memory_watch.asStr()) ) def buildMainModuleTree(filename, is_main): # Detect to be frozen modules if any, so we can consider to not follow # to them. if is_main: # TODO: Doesn't work for deeply nested packages at all. if Options.hasPythonFlagPackageMode(): module_name = ModuleName(os.path.basename(filename) + ".__main__") else: module_name = ModuleName("__main__") else: module_name = Importing.getModuleNameAndKindFromFilename(filename)[0] module, _added = buildModule( module_name=module_name, module_filename=filename, source_code=None, is_top=True, is_main=is_main, is_shlib=False, is_fake=False, hide_syntax_error=False, ) if Options.isStandaloneMode() and is_main: module.setEarlyModules(detectEarlyImports()) # Main modules do not get added to the import cache, but plugins get to see it. if module.isMainModule(): Plugins.onModuleDiscovered(module) else: addImportedModule(imported_module=module) return module def _makeModuleBodyFromSyntaxError(exc, module_name, module_filename): if module_filename not in Importing.warned_about: Importing.warned_about.add(module_filename) recursion_logger.warning( """\ Cannot follow import to module '%s' because of %r.""" % (module_name, exc.__class__.__name__) ) source_ref = SourceCodeReferences.fromFilename(filename=module_filename) module = CompiledPythonModule( module_name=module_name, is_top=False, mode="compiled", future_spec=FutureSpec(), source_ref=source_ref, ) module_body = makeModuleFrame( module=module, statements=( makeRaiseExceptionStatementFromInstance( source_ref=source_ref, exception=exc ), ), source_ref=source_ref, ) module_body = makeStatementsSequenceFromStatement(statement=module_body) module.setChild("body", module_body) return module def _makeModuleBodyTooComplex(module_name, module_filename, source_code, is_package): if module_filename not in Importing.warned_about: Importing.warned_about.add(module_filename) recursion_logger.warning( """\ Cannot follow import to import module '%r' ('%r') because code is too complex.""" % ( module_name, module_filename, ) ) module = makeUncompiledPythonModule( module_name=module_name, filename=module_filename, bytecode=marshal.dumps( compile(source_code, module_filename, "exec", dont_inherit=True) ), is_package=is_package, user_provided=True, technical=False, ) ModuleRegistry.addUncompiledModule(module) def buildModule( module_name, module_filename, source_code, is_top, is_main, is_shlib, is_fake, hide_syntax_error, ): # Many details to deal with, pylint: disable=too-many-branches,too-many-locals ( main_added, is_package, is_namespace, source_ref, source_filename, ) = Importing.decideModuleSourceRef( filename=module_filename, module_name=module_name, is_main=is_main, is_fake=is_fake, logger=general, ) if Options.hasPythonFlagPackageMode(): if is_top and Options.shallMakeModule(): optimization_logger.warning( "Python flag -m (package_mode) has no effect in module mode, it's only for executables." ) elif is_main and not main_added: optimization_logger.warning( "Python flag -m (package_mode) only works on packages with '__main__.py'." ) # Read source code if necessary. Might give a SyntaxError due to not being proper # encoded source. if source_filename is not None and not is_namespace and not is_shlib: try: # For fake modules, source is provided directly. if source_code is None: source_code = readSourceCodeFromFilename( module_name=module_name, source_filename=source_filename ) except SyntaxError as e: # Avoid hiding our own syntax errors. if not hasattr(e, "generated_by_nuitka"): raise # Do not hide SyntaxError in main module. if not hide_syntax_error: raise module = _makeModuleBodyFromSyntaxError( exc=e, module_name=module_name, module_filename=module_filename ) return module, True try: ast_tree = parseSourceCodeToAst( source_code=source_code, module_name=module_name, filename=source_filename, line_offset=0, ) except (SyntaxError, IndentationError) as e: # Do not hide SyntaxError if asked not to. if not hide_syntax_error: raise module = _makeModuleBodyFromSyntaxError( exc=e, module_name=module_name, module_filename=module_filename ) return module, True except CodeTooComplexCode: # Do not hide CodeTooComplexCode in main module. if is_main: raise module = _makeModuleBodyTooComplex( module_name=module_name, module_filename=module_filename, source_code=source_code, is_package=is_package, ) return module, False else: ast_tree = None source_code = None module = _createModule( module_name=module_name, source_code=source_code, source_ref=source_ref, is_top=is_top, is_main=is_main, is_shlib=is_shlib, is_namespace=is_namespace, is_package=is_package, main_added=main_added, ) if is_top: ModuleRegistry.addRootModule(module) OutputDirectories.setMainModule(module) if module.isCompiledPythonModule() and source_code is not None: createModuleTree( module=module, source_ref=source_ref, ast_tree=ast_tree, is_main=is_main, ) return module, True Nuitka-0.6.19.1/nuitka/tree/ReformulationClasses.py0000600000372100037210000003543514166627112027251 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of Python2 class statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import makeExpressionAttributeLookup from nuitka.nodes.BuiltinRefNodes import ExpressionBuiltinAnonymousRef from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.ClassNodes import ExpressionClassBody from nuitka.nodes.CodeObjectSpecs import CodeObjectSpec from nuitka.nodes.ConditionalNodes import ExpressionConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import ( makeExpressionMakeTuple, makeExpressionMakeTupleOrConstant, ) from nuitka.nodes.DictionaryNodes import ( ExpressionDictOperationGet2, ExpressionDictOperationIn, ) from nuitka.nodes.GlobalsLocalsNodes import ExpressionBuiltinLocalsRef from nuitka.nodes.LocalsDictNodes import ( StatementReleaseLocals, StatementSetLocalsDictionary, ) from nuitka.nodes.ModuleAttributeNodes import ExpressionModuleAttributeNameRef from nuitka.nodes.NodeMakingHelpers import mergeStatements from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.SubscriptNodes import ExpressionSubscriptLookup from nuitka.nodes.TryNodes import StatementTry from nuitka.nodes.TypeNodes import ExpressionBuiltinType1 from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableNameRef, ) from nuitka.PythonVersions import python_version from .ReformulationClasses3 import buildClassNode3 from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildFrameNode, buildNodeList, extractDocFromBody, getKind, makeStatementsSequence, makeStatementsSequenceFromStatement, mangleName, ) def buildClassNode2(provider, node, source_ref): # This function is the Python2 special case with special re-formulation as # according to Developer Manual, and it's very detailed, pylint: disable=too-many-locals class_statement_nodes, class_doc = extractDocFromBody(node) function_body = ExpressionClassBody( provider=provider, name=node.name, doc=class_doc, source_ref=source_ref ) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_freevars=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=function_body, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref.atInternal() locals_scope = function_body.getLocalsScope() # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained, and # starts out with a variables "__module__" and potentially "__doc__" set. statements = [ StatementSetLocalsDictionary(locals_scope=locals_scope, source_ref=source_ref), StatementAssignmentVariableName( provider=function_body, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference("__name__"), source_ref=source_ref, ), source_ref=source_ref.atInternal(), ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=function_body, variable_name="__doc__", source=makeConstantRefNode( constant=class_doc, source_ref=source_ref, user_provided=True ), source_ref=source_ref.atInternal(), ) ) statements += ( body, StatementReturn( expression=ExpressionBuiltinLocalsRef( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ), ) body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=function_body, tried=mergeStatements(statements, True), final=StatementReleaseLocals( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ) ) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. function_body.setChild("body", body) temp_scope = provider.allocateTempScope("class_creation") tmp_bases = provider.allocateTempVariable(temp_scope, "bases") tmp_class_dict = provider.allocateTempVariable(temp_scope, "class_dict") tmp_metaclass = provider.allocateTempVariable(temp_scope, "metaclass") tmp_class = provider.allocateTempVariable(temp_scope, "class") select_metaclass = ExpressionOutlineBody( provider=provider, name="select_metaclass", body=None, source_ref=source_ref ) if node.bases: tmp_base = select_metaclass.allocateTempVariable(temp_scope=None, name="base") statements = ( StatementAssignmentVariable( variable=tmp_base, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), subscript=makeConstantRefNode( constant=0, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), makeTryFinallyStatement( provider, tried=StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=makeExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref ), attribute_name="__class__", source_ref=source_ref, ), source_ref=source_ref, ) ), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), final=StatementReleaseVariable( variable=tmp_base, source_ref=source_ref ), source_ref=source_ref, public_exc=False, ), ) else: statements = ( StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( # TODO: Should avoid checking __builtins__ for this. expression=ExpressionVariableNameRef( variable_name="__metaclass__", provider=parent_module, source_ref=source_ref, ), source_ref=source_ref, ) ), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinAnonymousRef( builtin_name="classobj", source_ref=source_ref ), source_ref=source_ref, ) ), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), ) select_metaclass.setChild( "body", makeStatementsSequence( statements=statements, allow_none=False, source_ref=source_ref ), ) statements = [ StatementAssignmentVariable( variable=tmp_bases, source=makeExpressionMakeTupleOrConstant( elements=buildNodeList( provider=provider, nodes=node.bases, source_ref=source_ref ), user_provided=True, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_class_dict, source=function_body, source_ref=source_ref ), StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet2( dict_arg=ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=select_metaclass, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), args=makeExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), ExpressionTempVariableRef( variable=tmp_class_dict, source_ref=source_ref ), ), source_ref=source_ref, ), kw=None, source_ref=source_ref, ), source_ref=source_ref, ), ] for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): statements.append( StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=decorator, args=makeExpressionMakeTuple( elements=( ExpressionTempVariableRef( variable=tmp_class, source_ref=source_ref ), ), source_ref=source_ref, ), kw=None, source_ref=decorator.getSourceReference(), ), source_ref=decorator.getSourceReference(), ) ) statements.append( StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=ExpressionTempVariableRef(variable=tmp_class, source_ref=source_ref), source_ref=source_ref, ) ) final = ( StatementReleaseVariable(variable=tmp_class, source_ref=source_ref), StatementReleaseVariable(variable=tmp_bases, source_ref=source_ref), StatementReleaseVariable(variable=tmp_class_dict, source_ref=source_ref), StatementReleaseVariable(variable=tmp_metaclass, source_ref=source_ref), ) return makeTryFinallyStatement( provider=function_body, tried=statements, final=final, source_ref=source_ref ) def buildClassNode(provider, node, source_ref): assert getKind(node) == "ClassDef" # There appears to be a inconsistency with the top level line number # not being the one really the class has, if there are bases, and a # decorator. if node.bases: source_ref = source_ref.atLineNumber(node.bases[-1].lineno) # Python2 and Python3 are similar, but fundamentally different, so handle # them in dedicated code. if python_version < 0x300: return buildClassNode2(provider, node, source_ref) else: return buildClassNode3(provider, node, source_ref) Nuitka-0.6.19.1/nuitka/tree/ReformulationSequenceCreation.py0000600000372100037210000003556414166627112031114 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of sequence creations. Sequences might be directly translated to constants, or they might become nodes that build tuples, lists, or sets. For Python3.5, unpacking can happen while creating sequences, these are being re-formulated to an internal function. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.BuiltinIteratorNodes import ExpressionBuiltinIter1 from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.BuiltinTypeNodes import ExpressionBuiltinTuple from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import ( makeExpressionMakeListOrConstant, makeExpressionMakeSetLiteralOrConstant, makeExpressionMakeTuple, makeExpressionMakeTupleOrConstant, ) from nuitka.nodes.ContainerOperationNodes import ( ExpressionListOperationExtend, ExpressionListOperationExtendForUnpack, ExpressionSetOperationUpdate, ) from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCall, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.StatementNodes import StatementExpressionOnly from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableRef, ) from nuitka.PythonVersions import python_version from nuitka.specs.ParameterSpecs import ParameterSpec from . import SyntaxErrors from .InternalModule import ( internal_source_ref, makeInternalHelperFunctionBody, once_decorator, ) from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildNodeList, getKind, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, ) def _raiseStarredSyntaxError(element, source_ref): SyntaxErrors.raiseSyntaxError( "can use starred expression only as assignment target", source_ref.atColumnNumber(element.col_offset), ) def buildTupleCreationNode(provider, node, source_ref): if python_version >= 0x300: for element in node.elts: if getKind(element) == "Starred": if python_version < 0x350: _raiseStarredSyntaxError(element, source_ref) else: return buildTupleUnpacking( provider=provider, elements=node.elts, source_ref=source_ref ) return makeExpressionMakeTupleOrConstant( elements=buildNodeList(provider, node.elts, source_ref), user_provided=True, source_ref=source_ref, ) def buildListCreationNode(provider, node, source_ref): if python_version >= 0x300: for element in node.elts: if getKind(element) == "Starred": if python_version < 0x350: _raiseStarredSyntaxError(element, source_ref) else: return buildListUnpacking( provider=provider, elements=node.elts, source_ref=source_ref ) return makeExpressionMakeListOrConstant( elements=buildNodeList(provider, node.elts, source_ref), user_provided=True, source_ref=source_ref, ) def buildSetCreationNode(provider, node, source_ref): if python_version >= 0x300: for element in node.elts: if getKind(element) == "Starred": if python_version < 0x350: _raiseStarredSyntaxError(element, source_ref) else: return _buildSetUnpacking( provider=provider, elements=node.elts, source_ref=source_ref ) return makeExpressionMakeSetLiteralOrConstant( elements=buildNodeList(provider, node.elts, source_ref), user_provided=True, source_ref=source_ref, ) @once_decorator def getListUnpackingHelper(): helper_name = "_unpack_list" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=(), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "list") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "keys") if python_version < 0x390: list_operation_extend = ExpressionListOperationExtend else: list_operation_extend = ExpressionListOperationExtendForUnpack loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementExpressionOnly( expression=list_operation_extend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) args_variable = result.getVariableForAssignment(variable_name="args") final = ( StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ), ) return result @once_decorator def getSetUnpackingHelper(): helper_name = "_unpack_set" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=(), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "set") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "keys") loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementExpressionOnly( expression=ExpressionSetOperationUpdate( set_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) args_variable = result.getVariableForAssignment(variable_name="args") final = ( StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=set(), source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ), ) return result def buildListUnpacking(provider, elements, source_ref): helper_args = [] for element in elements: # We could be a lot cleverer about the tuples for non-starred # arguments, but lets get this to work first. And then rely on # future optimization to inline the list unpacking helper in a # way that has the same effect. if getKind(element) == "Starred": helper_args.append(buildNode(provider, element.value, source_ref)) else: helper_args.append( makeExpressionMakeTupleOrConstant( elements=(buildNode(provider, element, source_ref),), user_provided=True, source_ref=source_ref, ) ) result = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getListUnpackingHelper(), source_ref=source_ref ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=(makeExpressionMakeTuple(helper_args, source_ref),), source_ref=source_ref, ) result.setCompatibleSourceReference(helper_args[-1].getCompatibleSourceReference()) return result def buildTupleUnpacking(provider, elements, source_ref): return ExpressionBuiltinTuple( value=buildListUnpacking(provider, elements, source_ref), source_ref=source_ref ) def _buildSetUnpacking(provider, elements, source_ref): helper_args = [] for element in elements: # We could be a lot cleverer about the tuples for non-starred # arguments, but lets get this to work first. And then rely on # future optimization to inline the list unpacking helper in a # way that has the same effect. if getKind(element) == "Starred": helper_args.append(buildNode(provider, element.value, source_ref)) else: helper_args.append( makeExpressionMakeTupleOrConstant( elements=(buildNode(provider, element, source_ref),), user_provided=True, source_ref=source_ref, ) ) result = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getSetUnpackingHelper(), source_ref=source_ref ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=(makeExpressionMakeTuple(helper_args, source_ref),), source_ref=source_ref, ) result.setCompatibleSourceReference(helper_args[-1].getCompatibleSourceReference()) return result Nuitka-0.6.19.1/nuitka/tree/ReformulationPrintStatements.py0000600000372100037210000001064314166627112031012 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of print statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import ExpressionConstantNoneRef from nuitka.nodes.ImportNodes import ExpressionImportModuleNameHard from nuitka.nodes.PrintNodes import StatementPrintNewline, StatementPrintValue from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildNodeList, makeStatementsSequenceFromStatements, ) def buildPrintNode(provider, node, source_ref): # "print" statements, should only occur with Python2. if node.dest is not None: temp_scope = provider.allocateTempScope("print") tmp_target_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="target" ) target_default_statement = StatementAssignmentVariable( variable=tmp_target_variable, source=ExpressionImportModuleNameHard( module_name="sys", import_name="stdout", source_ref=source_ref ), source_ref=source_ref, ) statements = [ StatementAssignmentVariable( variable=tmp_target_variable, source=buildNode( provider=provider, node=node.dest, source_ref=source_ref ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=target_default_statement, no_branch=None, source_ref=source_ref, ), ] values = buildNodeList(provider=provider, nodes=node.values, source_ref=source_ref) if node.dest is not None: print_statements = [ StatementPrintValue( dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref ), value=value, source_ref=source_ref, ) for value in values ] if node.nl: print_statements.append( StatementPrintNewline( dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref ), source_ref=source_ref, ) ) statements.append( makeTryFinallyStatement( provider=provider, tried=print_statements, final=StatementReleaseVariable( variable=tmp_target_variable, source_ref=source_ref ), source_ref=source_ref, ) ) else: statements = [ StatementPrintValue(dest=None, value=value, source_ref=source_ref) for value in values ] if node.nl: statements.append(StatementPrintNewline(dest=None, source_ref=source_ref)) return makeStatementsSequenceFromStatements(*statements) Nuitka-0.6.19.1/nuitka/tree/ReformulationTryFinallyStatements.py0000600000372100037210000001550614166627112032016 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of try/finally statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.LoopNodes import StatementLoopBreak, StatementLoopContinue from nuitka.nodes.ReturnNodes import StatementReturnReturnedValue from nuitka.nodes.StatementNodes import ( StatementPreserveFrameException, StatementPublishException, StatementRestoreFrameException, StatementsSequence, ) from nuitka.nodes.TryNodes import StatementTry from nuitka.PythonVersions import python_version from .TreeHelpers import ( buildStatementsNode, getStatementsAppended, getStatementsPrepended, makeReraiseExceptionStatement, makeStatementsSequence, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, mergeStatements, popBuildContext, pushBuildContext, ) def _checkCloning(final, provider): final2 = final.makeClone() final2.parent = provider import nuitka.TreeXML if nuitka.TreeXML.Element is not None: f1 = final.asXml() f2 = final2.asXml() def compare(a, b): for c1, c2 in zip(a, b): compare(c1, c2) assert a.attrib == b.attrib, (a.attrib, b.attrib) compare(f1, f2) def makeTryFinallyStatement(provider, tried, final, source_ref, public_exc=False): # Complex handling, due to the many variants, pylint: disable=too-many-branches if type(tried) in (tuple, list): if tried: tried = makeStatementsSequenceFromStatements(*tried) else: tried = None if type(final) in (tuple, list): if final: final = StatementsSequence( statements=mergeStatements(final, False), source_ref=source_ref ) else: final = None if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) # Trivial case, nothing tried needs only do the final stuff. if tried is None: return final # Trivial case, nothing final needs nothing but the tried stuff. if final is None: return tried # Parent them to us already. if provider is not None: tried.parent = provider final.parent = provider def getFinal(): # Make a clone of "final" only if necessary. if hasattr(getFinal, "used"): return final.makeClone() else: getFinal.used = True return final if tried.mayRaiseException(BaseException): except_handler = getStatementsAppended( statement_sequence=getFinal(), statements=makeReraiseExceptionStatement(source_ref=source_ref), ) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence=except_handler, statements=( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), StatementPublishException(source_ref=source_ref), ), ) except_handler = makeTryFinallyStatement( provider=provider, tried=except_handler, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), public_exc=False, source_ref=source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement=except_handler ) else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopBreak(source_ref=source_ref), ) else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopContinue(source_ref=source_ref), ) else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementReturnReturnedValue( source_ref=source_ref, ), ) else: return_handler = None result = StatementTry( tried=tried, except_handler=except_handler, break_handler=break_handler, continue_handler=continue_handler, return_handler=return_handler, source_ref=source_ref, ) if result.isStatementAborting(): return result else: return makeStatementsSequence( statements=(result, getFinal()), allow_none=False, source_ref=source_ref ) def buildTryFinallyNode(provider, build_tried, node, source_ref): if python_version < 0x300: # Prevent "continue" statements in the final blocks pushBuildContext("finally") final = buildStatementsNode( provider=provider, nodes=node.finalbody, source_ref=source_ref ) popBuildContext() return makeTryFinallyStatement( provider=provider, tried=build_tried(), final=final, source_ref=source_ref, public_exc=False, ) else: tried = build_tried() # Prevent "continue" statements in the final blocks, these have to # become "SyntaxError". pushBuildContext("finally") final = buildStatementsNode( provider=provider, nodes=node.finalbody, source_ref=source_ref ) popBuildContext() return makeTryFinallyStatement( provider=provider, tried=tried, final=final, public_exc=True, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/ReformulationImportStatements.py0000600000372100037210000003154214166627112031171 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of import statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementReleaseVariable, ) from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.FutureSpecs import FutureSpec from nuitka.nodes.GlobalsLocalsNodes import ExpressionBuiltinGlobals from nuitka.nodes.ImportNodes import ( ExpressionBuiltinImport, ExpressionImportModuleHard, ExpressionImportName, StatementImportStar, ) from nuitka.nodes.NodeMakingHelpers import mergeStatements from nuitka.nodes.StatementNodes import StatementsSequence from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.PythonVersions import python_version from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .SyntaxErrors import raiseSyntaxError from .TreeHelpers import makeStatementsSequenceOrStatement, mangleName # For checking afterwards, if __future__ imports really were at the beginning # of the file. _future_import_nodes = [] def checkFutureImportsOnlyAtStart(body): # Check if a __future__ imports really were at the beginning of the file. for node in body: if node in _future_import_nodes: _future_import_nodes.remove(node) else: if _future_import_nodes: raiseSyntaxError( """\ from __future__ imports must occur at the beginning of the file""", _future_import_nodes[0].source_ref.atColumnNumber( _future_import_nodes[0].col_offset ), ) def _handleFutureImport(provider, node, source_ref): # Don't allow future imports in functions or classes. if not provider.isCompiledPythonModule(): raiseSyntaxError( """\ from __future__ imports must occur at the beginning of the file""", source_ref.atColumnNumber(node.col_offset), ) for import_desc in node.names: object_name, _local_name = import_desc.name, import_desc.asname _enableFutureFeature(node=node, object_name=object_name, source_ref=source_ref) # Remember it for checks to be applied once module is complete, e.g. if # they are all at module start. node.source_ref = source_ref _future_import_nodes.append(node) _future_specs = [] def pushFutureSpec(): _future_specs.append(FutureSpec()) def getFutureSpec(): return _future_specs[-1] def popFutureSpec(): del _future_specs[-1] def _enableFutureFeature(node, object_name, source_ref): future_spec = _future_specs[-1] if object_name == "unicode_literals": future_spec.enableUnicodeLiterals() elif object_name == "absolute_import": future_spec.enableAbsoluteImport() elif object_name == "division": future_spec.enableFutureDivision() elif object_name == "print_function": future_spec.enableFuturePrint() elif object_name == "barry_as_FLUFL" and python_version >= 0x300: future_spec.enableBarry() elif object_name == "generator_stop": future_spec.enableGeneratorStop() elif object_name == "braces": raiseSyntaxError("not a chance", source_ref.atColumnNumber(node.col_offset)) elif object_name in ("nested_scopes", "generators", "with_statement"): # These are enabled in all cases already. pass elif object_name == "annotations" and python_version >= 0x370: future_spec.enableFutureAnnotations() else: raiseSyntaxError( "future feature %s is not defined" % object_name, source_ref.atColumnNumber(node.col_offset), ) def buildImportFromNode(provider, node, source_ref): # "from .. import .." statements. This may trigger a star import, or # multiple names being looked up from the given module variable name. # This is pretty complex. # pylint: disable=too-many-branches,too-many-locals,too-many-statements module_name = node.module if node.module is not None else "" level = node.level # Use default level under some circumstances. if level == -1: level = None elif level == 0 and not _future_specs[-1].isAbsoluteImport(): level = None if level is not None: level_obj = makeConstantRefNode(level, source_ref, True) else: level_obj = None # Importing from "__future__" module may enable flags to the parser, # that we need to know about, handle that. if module_name == "__future__": _handleFutureImport(provider, node, source_ref) target_names = [] import_names = [] # Mapping imported "fromlist" to assigned "fromlist" if any, handling the # star case as well. for import_desc in node.names: object_name, local_name = import_desc.name, import_desc.asname if object_name == "*": target_names.append(None) assert local_name is None else: target_names.append(local_name if local_name is not None else object_name) import_names.append(object_name) # Star imports get special treatment. if None in target_names: # More than "*" is a syntax error in Python, need not care about this at # all, it's only allowed value for import list in this case. assert target_names == [None] # Python3 made it so that these can only occur on the module level, # so this a syntax error if not there. For Python2 it is OK to # occur everywhere though. if not provider.isCompiledPythonModule() and python_version >= 0x300: raiseSyntaxError( "import * only allowed at module level", source_ref.atColumnNumber(node.col_offset), ) if provider.isCompiledPythonModule(): import_globals = ExpressionBuiltinGlobals(source_ref) import_locals = ExpressionBuiltinGlobals(source_ref) else: import_globals = ExpressionBuiltinGlobals(source_ref) import_locals = makeConstantRefNode({}, source_ref, True) return StatementImportStar( target_scope=provider.getLocalsScope(), module_import=ExpressionBuiltinImport( name=makeConstantRefNode(module_name, source_ref, True), globals_arg=import_globals, locals_arg=import_locals, fromlist=makeConstantRefNode(("*",), source_ref, True), level=level_obj, source_ref=source_ref, ), source_ref=source_ref, ) else: if module_name == "__future__": imported_from_module = ExpressionImportModuleHard( module_name="__future__", source_ref=source_ref ) else: imported_from_module = ExpressionBuiltinImport( name=makeConstantRefNode(module_name, source_ref, True), globals_arg=ExpressionBuiltinGlobals(source_ref), locals_arg=makeConstantRefNode(None, source_ref, True), fromlist=makeConstantRefNode(tuple(import_names), source_ref, True), level=level_obj, source_ref=source_ref, ) # If we have multiple names to import, consider each. multi_names = len(target_names) > 1 statements = [] if multi_names: tmp_import_from = provider.allocateTempVariable( temp_scope=provider.allocateTempScope("import_from"), name="module" ) statements.append( StatementAssignmentVariable( variable=tmp_import_from, source=imported_from_module, source_ref=source_ref, ) ) imported_from_module = ExpressionTempVariableRef( variable=tmp_import_from, source_ref=source_ref ) import_statements = [] first = True for target_name, import_name in zip(target_names, import_names): # Make a clone of the variable reference, if we are going to use # another one. if not first: imported_from_module = imported_from_module.makeClone() first = False import_statements.append( StatementAssignmentVariableName( provider=provider, variable_name=mangleName(target_name, provider), source=ExpressionImportName( module=imported_from_module, import_name=import_name, level=0, source_ref=source_ref, ), source_ref=source_ref, ) ) # Release the temporary module value as well. if multi_names: statements.append( makeTryFinallyStatement( provider=provider, tried=import_statements, final=( StatementReleaseVariable( variable=tmp_import_from, source_ref=source_ref ), ), source_ref=source_ref, ) ) else: statements.extend(import_statements) # Note: Each import is sequential. It can succeed, and the failure of a # later one is not undoing previous ones. We can therefore have a # sequence of imports that each only import one thing therefore. return StatementsSequence( statements=mergeStatements(statements), source_ref=source_ref ) def buildImportModulesNode(provider, node, source_ref): # Import modules statement. As described in the Developer Manual, these # statements can be treated as several ones. import_names = [ (import_desc.name, import_desc.asname) for import_desc in node.names ] import_nodes = [] for import_desc in import_names: module_name, local_name = import_desc module_topname = module_name.split(".")[0] # Note: The "level" of import is influenced by the future absolute # imports. level = ( makeConstantRefNode(0, source_ref, True) if _future_specs[-1].isAbsoluteImport() else None ) import_node = ExpressionBuiltinImport( name=makeConstantRefNode(module_name, source_ref, True), globals_arg=ExpressionBuiltinGlobals(source_ref), locals_arg=makeConstantRefNode(None, source_ref, True), fromlist=makeConstantRefNode(None, source_ref, True), level=level, source_ref=source_ref, ) if local_name: # If is gets a local name, the real name must be used as a # temporary value only, being looked up recursively. for import_name in module_name.split(".")[1:]: import_node = ExpressionImportName( module=import_node, import_name=import_name, # TODO: Does level make sense at all, should be removed. level=0, source_ref=source_ref, ) # If a name was given, use the one provided, otherwise the import gives # the top level package name given for assignment of the imported # module. import_nodes.append( StatementAssignmentVariableName( provider=provider, variable_name=mangleName( local_name if local_name is not None else module_topname, provider ), source=import_node, source_ref=source_ref, ) ) # Note: Each import is sequential. It will potentially succeed, and the # failure of a later one is not changing that one bit . We can therefore # have a sequence of imports that only import one thing therefore. return makeStatementsSequenceOrStatement( statements=import_nodes, source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/tree/ReformulationMatchStatements.py0000600000372100037210000004010214166627112030743 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of Python3.10 match statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ import ast from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import ( ExpressionAttributeCheck, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinLenNodes import ExpressionBuiltinLen from nuitka.nodes.ComparisonNodes import makeComparisonExpression from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.SubscriptNodes import ( ExpressionSubscriptCheck, ExpressionSubscriptLookup, ) from nuitka.nodes.TypeMatchNodes import ( ExpressionMatchTypeCheckMapping, ExpressionMatchTypeCheckSequence, ) from nuitka.nodes.TypeNodes import ExpressionBuiltinIsinstance from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from .ReformulationBooleanExpressions import makeAndNode, makeOrNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import buildNode, buildStatementsNode, makeStatementsSequence def _makeMatchComparison(left, right, source_ref): if right.isExpressionConstantBoolRef() or right.isExpressionConstantNoneRef(): comparator = "Is" else: comparator = "Eq" return makeComparisonExpression( left=left, right=right, comparator=comparator, source_ref=source_ref, ) def _buildCaseBodyCode(provider, case, source_ref): guard_condition = buildNode( provider=provider, node=case.guard, source_ref=source_ref, allow_none=True, ) body_code = buildStatementsNode(provider, case.body, source_ref) return body_code, guard_condition def _buildMatchAs(provider, variable_name, source_value, source_ref): assert "." not in variable_name, variable_name assert "!" not in variable_name, variable_name return StatementAssignmentVariableName( provider=provider, variable_name=variable_name, source=source_value, source_ref=source_ref, ) def _buildMatchValue(provider, against, pattern, source_ref): if type(pattern) is ast.MatchValue: right = buildNode(provider, pattern.value, source_ref) else: right = makeConstantRefNode(constant=pattern.value, source_ref=source_ref) return _makeMatchComparison( left=against, right=right, source_ref=source_ref, ) def _buildMatchSequence(provider, pattern, against, source_ref): # Many cases due to recursion, pylint: disable=too-many-locals conditions = [ ExpressionMatchTypeCheckSequence( value=against.makeClone(), source_ref=source_ref, ) ] assignments = [] min_length = len( tuple( seq_pattern for seq_pattern in pattern.patterns if seq_pattern.__class__ is not ast.MatchStar ) ) if min_length: exact = all( seq_pattern.__class__ is not ast.MatchStar for seq_pattern in pattern.patterns ) # TODO: Could special case "1" with truth check. conditions.append( makeComparisonExpression( left=ExpressionBuiltinLen( value=against.makeClone(), source_ref=source_ref, ), right=makeConstantRefNode(constant=min_length, source_ref=source_ref), comparator="Eq" if exact else "GtE", source_ref=source_ref, ) ) star_pos = None count = seq_pattern = None for count, seq_pattern in enumerate(pattern.patterns): # offset from the start. if star_pos is None: offset = count else: # offset from the end. offset = -(len(pattern.patterns) - count) if seq_pattern.__class__ is ast.MatchStar: variable_name = seq_pattern.name if variable_name is not None: assert "." not in variable_name, variable_name assert "!" not in variable_name, variable_name star_pos = count # Last one if star_pos == len(pattern.patterns): slice_value = slice(count) else: slice_value = slice(count, -(len(pattern.patterns) - (count + 1))) assignments.append( StatementAssignmentVariableName( provider=provider, variable_name=variable_name, source=ExpressionSubscriptLookup( expression=against.makeClone(), subscript=makeConstantRefNode( constant=slice_value, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ) else: item_conditions, item_assignments = _buildMatch( provider=provider, pattern=seq_pattern, against=ExpressionSubscriptLookup( expression=against.makeClone(), subscript=makeConstantRefNode( constant=offset, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) if item_conditions: conditions.extend(item_conditions) if item_assignments: assignments.extend(item_assignments) return conditions, assignments def _buildMatchMapping(provider, pattern, against, source_ref): conditions = [ ExpressionMatchTypeCheckMapping( value=against.makeClone(), source_ref=source_ref, ) ] assignments = [] assert len(pattern.keys) == len(pattern.patterns), ast.dump(pattern) key = kwd_pattern = None for key, kwd_pattern in zip(pattern.keys, pattern.patterns): conditions.append( ExpressionSubscriptCheck( expression=against.makeClone(), subscript=makeConstantRefNode( constant=key.value, source_ref=source_ref ), source_ref=source_ref, ) ) item_against = ExpressionSubscriptLookup( expression=against.makeClone(), subscript=makeConstantRefNode(constant=key.value, source_ref=source_ref), source_ref=source_ref, ) item_conditions, item_assignments = _buildMatch( provider=provider, against=item_against, pattern=kwd_pattern, source_ref=source_ref, ) if item_conditions: conditions.extend(item_conditions) if item_assignments: assignments.extend(item_assignments) return conditions, assignments def _buildMatchClass(provider, pattern, against, source_ref): # TODO: What is that when set. assert not pattern.patterns cls_node = buildNode(provider, pattern.cls, source_ref) assert len(pattern.kwd_attrs) == len(pattern.kwd_patterns), ast.dump(pattern) conditions = [ ExpressionBuiltinIsinstance( instance=against.makeClone(), classes=cls_node, source_ref=source_ref, ) ] assignments = [] assert len(pattern.kwd_attrs) == len(pattern.kwd_patterns), ast.dump(pattern) for key, kwd_pattern in zip(pattern.kwd_attrs, pattern.kwd_patterns): conditions.append( ExpressionAttributeCheck( expression=against.makeClone(), attribute_name=key, source_ref=source_ref, ) ) item_conditions, item_assignments = _buildMatch( provider=provider, against=makeExpressionAttributeLookup( expression=against.makeClone(), attribute_name=key, source_ref=source_ref, ), pattern=kwd_pattern, source_ref=source_ref, ) if item_conditions: conditions.extend(item_conditions) if item_assignments: assignments.extend(item_assignments) return conditions, assignments def _buildMatch(provider, pattern, against, source_ref): if pattern.__class__ is ast.MatchOr: or_condition_list = [] for or_pattern in pattern.patterns: or_conditions, or_assignments = _buildMatch( provider=provider, pattern=or_pattern, against=against, source_ref=source_ref, ) assert not or_assignments or_condition_list.append( makeAndNode(values=or_conditions, source_ref=source_ref) ) condition = makeOrNode(values=or_condition_list, source_ref=source_ref) conditions = (condition,) assignments = None elif pattern.__class__ is ast.MatchClass: conditions, assignments = _buildMatchClass( provider=provider, pattern=pattern, against=against, source_ref=source_ref ) elif pattern.__class__ is ast.MatchMapping: conditions, assignments = _buildMatchMapping( provider=provider, pattern=pattern, against=against, source_ref=source_ref, ) elif pattern.__class__ is ast.MatchSequence: conditions, assignments = _buildMatchSequence( provider=provider, pattern=pattern, against=against, source_ref=source_ref, ) elif pattern.__class__ is ast.MatchAs: conditions = None # default match only current with or without a name assigned. TODO: This ought to only # happen once, Python raises it, we do not yet: SyntaxError: name capture 'var' makes # remaining patterns unreachable if pattern.name is None: # case _: # Assigns to nothing and should be last one in a match statement, anything # after that will be syntax error. assignments = None else: # case var: # Assigns to var and should be last one in a match statement, anything # after that will be syntax error. assignment = _buildMatchAs( provider=provider, variable_name=pattern.name, source_value=against, source_ref=source_ref, ) assignments = (assignment,) elif pattern.__class__ is ast.MatchValue or pattern.__class__ is ast.MatchSingleton: conditions = [ _buildMatchValue( provider=provider, against=against, pattern=pattern, source_ref=source_ref, ) ] assignments = None else: assert False, ast.dump(pattern) return conditions, assignments def _buildCase(provider, case, tmp_subject, source_ref): assert case.__class__ is ast.match_case, case pattern = case.pattern against = ExpressionTempVariableRef(variable=tmp_subject, source_ref=source_ref) conditions, assignments = _buildMatch( provider=provider, pattern=pattern, against=against, source_ref=source_ref, ) branch_code, guard = _buildCaseBodyCode(provider, case, source_ref) return (conditions, assignments, guard, branch_code) def buildMatchNode(provider, node, source_ref): """Python3.10 or higher, match statements.""" subject_node = buildNode(provider, node.subject, source_ref) temp_scope = provider.allocateTempScope("match_statement") # The value matched against, must be released in the end. tmp_subject = provider.allocateTempVariable(temp_scope, "subject") # Indicator variable, will end up with C bool type, and need not be released. tmp_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="indicator", temp_type="bool" ) cases = [] for case in node.cases: cases.append( _buildCase( provider=provider, case=case, tmp_subject=tmp_subject, source_ref=source_ref, ) ) case_statements = [] for case in cases: conditions, assignments, guard, branch_code = case # Set indicator variable at end of branch code, unless it's last branch # where there would be no usage of it. if case is not cases[-1]: branch_code = makeStatementsSequence( statements=( branch_code, StatementAssignmentVariable( variable=tmp_indicator_variable, source=makeConstantRefNode( constant=True, source_ref=source_ref ), source_ref=source_ref, ), ), allow_none=True, source_ref=source_ref, ) if guard is not None: branch_code = makeStatementConditional( condition=guard, yes_branch=branch_code, no_branch=None, source_ref=source_ref, ) del guard branch_code = makeStatementsSequence( statements=(assignments, branch_code), allow_none=True, source_ref=source_ref, ) del assignments if conditions is not None: branch_code = makeStatementConditional( condition=makeAndNode(values=conditions, source_ref=source_ref), yes_branch=branch_code, no_branch=None, source_ref=source_ref, ) del conditions if case is not cases[0]: statement = makeStatementConditional( condition=makeComparisonExpression( comparator="Is", left=ExpressionTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref ), right=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), yes_branch=branch_code, no_branch=None, source_ref=source_ref, ) else: statement = branch_code case_statements.append(statement) return makeStatementsSequence( statements=( StatementAssignmentVariable( variable=tmp_subject, source=subject_node, source_ref=subject_node.getSourceReference(), ), makeTryFinallyStatement( provider=provider, tried=case_statements, final=StatementReleaseVariable( variable=tmp_indicator_variable, source_ref=source_ref ), source_ref=source_ref, ), ), allow_none=False, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/tree/ReformulationComparisonExpressions.py0000600000372100037210000001430514166627112032222 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of comparison chain expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.ComparisonNodes import makeComparisonExpression from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.OperatorNodesUnary import ExpressionOperationNot from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, getKind, makeStatementsSequenceFromStatement, ) def _makeComparisonNode(left, right, comparator, source_ref): result = makeComparisonExpression(left, right, comparator, source_ref) result.setCompatibleSourceReference(source_ref=right.getCompatibleSourceReference()) return result def buildComparisonNode(provider, node, source_ref): assert len(node.comparators) == len(node.ops) # Comparisons are re-formulated as described in the Developer Manual. When # having multiple comparators, things require assignment expressions and # references of them to work properly. Then they can become normal "and" # code. # The operands are split out in two parts strangely. left = buildNode(provider, node.left, source_ref) rights = [ buildNode(provider, comparator, source_ref) for comparator in node.comparators ] comparators = [getKind(comparator) for comparator in node.ops] # Normal, and simple case, we only have one comparison, which is what our # node handles only. Then we can handle it if len(rights) == 1: return _makeComparisonNode( left=left, right=rights[0], # TODO: The terminology of Nuitka might be messed up here. comparator=comparators[0], source_ref=source_ref, ) return buildComplexComparisonNode(provider, left, rights, comparators, source_ref) def buildComplexComparisonNode(provider, left, rights, comparators, source_ref): # This is a bit complex, due to the many details, pylint: disable=too-many-locals outline_body = ExpressionOutlineBody( provider=provider, name="comparison_chain", source_ref=source_ref ) variables = [ outline_body.allocateTempVariable(temp_scope=None, name="operand_%d" % count) for count in range(2, len(rights) + 2) ] tmp_variable = outline_body.allocateTempVariable( temp_scope=None, name="comparison_result" ) def makeTempAssignment(count, value): return StatementAssignmentVariable( variable=variables[count], source=value, source_ref=source_ref ) def makeReleaseStatement(count): return StatementReleaseVariable( variable=variables[count], source_ref=source_ref ) def makeValueComparisonReturn(left, right, comparator): yield StatementAssignmentVariable( variable=tmp_variable, source=_makeComparisonNode( left=left, right=right, comparator=comparator, source_ref=source_ref ), source_ref=source_ref, ) yield makeStatementConditional( condition=ExpressionOperationNot( operand=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ) statements = [] final = [] for count, value in enumerate(rights): if value is not rights[-1]: statements.append(makeTempAssignment(count, value)) final.append(makeReleaseStatement(count)) right = ExpressionTempVariableRef( variable=variables[count], source_ref=source_ref ) else: right = value if count != 0: left = ExpressionTempVariableRef( variable=variables[count - 1], source_ref=source_ref ) comparator = comparators[count] if value is not rights[-1]: statements.extend(makeValueComparisonReturn(left, right, comparator)) else: statements.append( StatementReturn( expression=_makeComparisonNode( left=left, right=right, comparator=comparator, source_ref=source_ref, ), source_ref=source_ref, ) ) final.append( StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref) ) outline_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outline_body, tried=statements, final=final, source_ref=source_ref, ) ), ) return outline_body Nuitka-0.6.19.1/nuitka/tree/SourceReading.py0000600000372100037210000002006014166627112025623 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Read source code from files. This is tremendously more complex than one might think, due to encoding issues and version differences of Python versions. """ import os import re import sys from nuitka import Options, SourceCodeReferences from nuitka.__past__ import unicode from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version, python_version_str from nuitka.Tracing import general from nuitka.utils.FileOperations import putTextFileContents from nuitka.utils.Shebang import getShebangFromSource, parseShebang from nuitka.utils.Utils import getOS from .SyntaxErrors import raiseSyntaxError _fstrings_installed = False def _installFutureFStrings(): """Install fake UTF8 handle just as future-fstrings does. This unbreaks at least """ # Singleton, pylint: disable=global-statement global _fstrings_installed if _fstrings_installed: return # TODO: Not supporting anything before that. if python_version >= 0x360: import codecs # Play trick for of "future_strings" PyPI package support. It's not needed, # but some people use it even on newer Python. try: codecs.lookup("future-fstrings") except LookupError: import encodings utf8 = encodings.search_function("utf8") codec_map = {"future-fstrings": utf8, "future_fstrings": utf8} codecs.register(codec_map.get) else: try: import future_fstrings except ImportError: pass else: future_fstrings.register() _fstrings_installed = True def _readSourceCodeFromFilename3(source_filename): # Only using this for Python3, for Python2 it's too buggy. import tokenize _installFutureFStrings() with tokenize.open(source_filename) as source_file: return source_file.read() def _detectEncoding2(source_file): # Detect the encoding. encoding = "ascii" line1 = source_file.readline() if line1.startswith(b"\xef\xbb\xbf"): # BOM marker makes it clear. encoding = "utf-8" else: line1_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line1) if line1_match: encoding = line1_match.group(1) else: line2 = source_file.readline() line2_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line2) if line2_match: encoding = line2_match.group(1) source_file.seek(0) return encoding def _readSourceCodeFromFilename2(source_filename): _installFutureFStrings() # Detect the encoding, we do not know it, pylint: disable=unspecified-encoding with open(source_filename, "rU") as source_file: encoding = _detectEncoding2(source_file) source_code = source_file.read() # Try and detect SyntaxError from missing or wrong encodings. if type(source_code) is not unicode and encoding == "ascii": try: _source_code = source_code.decode(encoding) except UnicodeDecodeError as e: lines = source_code.split("\n") so_far = 0 for count, line in enumerate(lines): so_far += len(line) + 1 if so_far > e.args[2]: break else: # Cannot happen, decode error implies non-empty. count = -1 wrong_byte = re.search( "byte 0x([a-f0-9]{2}) in position", str(e) ).group(1) raiseSyntaxError( """\ Non-ASCII character '\\x%s' in file %s on line %d, but no encoding declared; \ see http://python.org/dev/peps/pep-0263/ for details""" % (wrong_byte, source_filename, count + 1), SourceCodeReferences.fromFilename(source_filename).atLineNumber( count + 1 ), display_line=False, ) return source_code def readSourceCodeFromFilename(module_name, source_filename): if python_version < 0x300: source_code = _readSourceCodeFromFilename2(source_filename) else: source_code = _readSourceCodeFromFilename3(source_filename) # Allow plugins to mess with source code. Test code calls this # without a module and doesn't want changes from plugins. if module_name is not None: source_code_modified = Plugins.onModuleSourceCode(module_name, source_code) else: source_code_modified = source_code if Options.shallPersistModifications() and source_code_modified != source_code: orig_source_filename = source_filename + ".orig" if not os.path.exists(orig_source_filename): putTextFileContents(filename=orig_source_filename, contents=source_code) putTextFileContents(filename=source_filename, contents=source_code_modified) return source_code_modified def checkPythonVersionFromCode(source_code): # There is a lot of cases to consider, pylint: disable=too-many-branches shebang = getShebangFromSource(source_code) if shebang is not None: binary, _args = parseShebang(shebang) if getOS() != "Windows": try: if os.path.samefile(sys.executable, binary): return True except OSError: # Might not exist pass basename = os.path.basename(binary) # Not sure if we should do that. if basename == "python": result = python_version < 0x300 elif basename == "python3": result = python_version >= 0x300 elif basename == "python2": result = python_version < 0x300 elif basename == "python2.7": result = python_version < 0x300 elif basename == "python2.6": result = python_version < 0x270 elif basename == "python3.2": result = 0x330 > python_version >= 0x300 elif basename == "python3.3": result = 0x340 > python_version >= 0x330 elif basename == "python3.4": result = 0x350 > python_version >= 0x340 elif basename == "python3.5": result = 0x360 > python_version >= 0x350 elif basename == "python3.6": result = 0x370 > python_version >= 0x360 elif basename == "python3.7": result = 0x380 > python_version >= 0x370 elif basename == "python3.8": result = 0x390 > python_version >= 0x380 elif basename == "python3.9": result = 0x3A0 > python_version >= 0x390 elif basename == "python3.10": result = 0x3B0 > python_version >= 0x3A0 else: result = None if result is False: general.sysexit( """\ The program you compiled wants to be run with: %s. Nuitka is currently running with Python version '%s', which seems to not match that. Nuitka cannot guess the Python version of your source code. You therefore might want to specify: '%s -m nuitka'. That will make use the correct Python version for Nuitka. """ % (shebang, python_version_str, binary) ) def readSourceLine(source_ref): import linecache return linecache.getline( filename=source_ref.getFilename(), lineno=source_ref.getLineNumber() ) Nuitka-0.6.19.1/nuitka/tree/TreeHelpers.py0000600000372100037210000005372314166627112025327 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Helper functions for parsing the AST nodes and building the Nuitka node tree. """ import __future__ import ast from nuitka import Constants, Options from nuitka.Errors import CodeTooComplexCode from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.CodeObjectSpecs import CodeObjectSpec from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTupleOrConstant from nuitka.nodes.DictionaryNodes import ( ExpressionKeyValuePair, makeExpressionMakeDict, ) from nuitka.nodes.ExceptionNodes import StatementReraiseException from nuitka.nodes.FrameNodes import ( StatementsFrameAsyncgen, StatementsFrameCoroutine, StatementsFrameFunction, StatementsFrameGenerator, StatementsFrameModule, ) from nuitka.nodes.NodeBases import NodeBase from nuitka.nodes.NodeMakingHelpers import mergeStatements from nuitka.nodes.StatementNodes import StatementsSequence from nuitka.PythonVersions import python_version from nuitka.Tracing import optimization_logger, printLine def dump(node): printLine(ast.dump(node)) def getKind(node): return node.__class__.__name__.rsplit(".", 1)[-1] def extractDocFromBody(node): body = node.body doc = None # Work around "ast.get_docstring" breakage. if body and getKind(body[0]) == "Expr": if getKind(body[0].value) == "Str": # python3.7 or earlier doc = body[0].value.s body = body[1:] elif getKind(body[0].value) == "Constant": # python3.8 # Only strings should be used, but all other constants can immediately be ignored, # it seems that e.g. Ellipsis is common. if type(body[0].value.value) is str: doc = body[0].value.value body = body[1:] if Options.hasPythonFlagNoDocstrings(): doc = None return body, doc def parseSourceCodeToAst(source_code, module_name, filename, line_offset): # Workaround: ast.parse cannot cope with some situations where a file is not # terminated by a new line. if not source_code.endswith("\n"): source_code = source_code + "\n" try: body = ast.parse(source_code, filename) except RuntimeError as e: if "maximum recursion depth" in e.args[0]: raise CodeTooComplexCode(module_name, filename) raise assert getKind(body) == "Module" if line_offset > 0: ast.increment_lineno(body, line_offset) return body def detectFunctionBodyKind(nodes, start_value=None): # This is a complex mess, following the scope means a lot of checks need # to be done. pylint: disable=too-many-branches,too-many-statements indications = set() if start_value is not None: indications.add(start_value) flags = set() def _checkCoroutine(field): """Check only for co-routine nature of the field and only update that.""" # TODO: This is clumsy code, trying to achieve what non-local does for # Python2 as well. old = set(indications) indications.clear() _check(field) if "Coroutine" in indications: old.add("Coroutine") indications.clear() indications.update(old) def _check(node): node_class = node.__class__ if node_class is ast.Yield: indications.add("Generator") elif python_version >= 0x300 and node_class is ast.YieldFrom: indications.add("Generator") elif python_version >= 0x350 and node_class in (ast.Await, ast.AsyncWith): indications.add("Coroutine") # Recurse to children, but do not cross scope boundary doing so. if node_class is ast.ClassDef: for name, field in ast.iter_fields(node): if name in ("name", "body"): pass elif name in ("bases", "decorator_list", "keywords"): for child in field: _check(child) elif name == "starargs": if field is not None: _check(field) elif name == "kwargs": if field is not None: _check(field) else: assert False, (name, field, ast.dump(node)) elif node_class in (ast.FunctionDef, ast.Lambda) or ( python_version >= 0x350 and node_class is ast.AsyncFunctionDef ): for name, field in ast.iter_fields(node): if name in ("name", "body"): pass elif name in ("bases", "decorator_list"): for child in field: _check(child) elif name == "args": for child in field.defaults: _check(child) if python_version >= 0x300: for child in node.args.kw_defaults: if child is not None: _check(child) for child in node.args.args: if child.annotation is not None: _check(child.annotation) elif name == "returns": if field is not None: _check(field) elif name == "type_comment": # Python3.8: We don't have structure here. assert field is None or type(field) is str else: assert False, (name, field, ast.dump(node)) elif node_class is ast.GeneratorExp: for name, field in ast.iter_fields(node): if name == "name": pass elif name in ("body", "comparators", "elt"): if python_version >= 0x370: _checkCoroutine(field) elif name == "generators": _check(field[0].iter) # New syntax in 3.7 allows these to be present in functions not # declared with "async def", so we need to check them, but # only if top level. if python_version >= 0x370 and node in nodes: for gen in field: if gen.is_async: indications.add("Coroutine") break if _checkCoroutine(gen): break else: assert False, (name, field, ast.dump(node)) elif node_class is ast.ListComp and python_version >= 0x300: for name, field in ast.iter_fields(node): if name in ("name", "body", "comparators"): pass elif name == "generators": _check(field[0].iter) elif name in ("body", "elt"): _check(field) else: assert False, (name, field, ast.dump(node)) elif python_version >= 0x270 and node_class is ast.SetComp: for name, field in ast.iter_fields(node): if name in ("name", "body", "comparators", "elt"): pass elif name == "generators": _check(field[0].iter) else: assert False, (name, field, ast.dump(node)) elif python_version >= 0x270 and node_class is ast.DictComp: for name, field in ast.iter_fields(node): if name in ("name", "body", "comparators", "key", "value"): pass elif name == "generators": _check(field[0].iter) else: assert False, (name, field, ast.dump(node)) elif python_version >= 0x370 and node_class is ast.comprehension: for name, field in ast.iter_fields(node): if name in ("name", "target"): pass elif name == "iter": # Top level comprehension iterators do not influence those. if node not in nodes: _check(field) elif name == "ifs": for child in field: _check(child) elif name == "is_async": if field: indications.add("Coroutine") else: assert False, (name, field, ast.dump(node)) elif node_class is ast.Name: if python_version >= 0x300 and node.id == "super": flags.add("has_super") elif python_version < 0x300 and node_class is ast.Exec: flags.add("has_exec") if node.globals is None: flags.add("has_unqualified_exec") for child in ast.iter_child_nodes(node): _check(child) elif python_version < 0x300 and node_class is ast.ImportFrom: for import_desc in node.names: if import_desc.name[0] == "*": flags.add("has_exec") for child in ast.iter_child_nodes(node): _check(child) else: for child in ast.iter_child_nodes(node): _check(child) for node in nodes: _check(node) if indications: if "Coroutine" in indications and "Generator" in indications: function_kind = "Asyncgen" else: # If we found something, make sure we agree on all clues. assert len(indications) == 1, indications function_kind = indications.pop() else: function_kind = "Function" return function_kind, flags build_nodes_args3 = None build_nodes_args2 = None build_nodes_args1 = None def setBuildingDispatchers(path_args3, path_args2, path_args1): # Using global here, as this is really a singleton, in the form of a module, # and this is to break the cyclic dependency it has, pylint: disable=global-statement global build_nodes_args3, build_nodes_args2, build_nodes_args1 build_nodes_args3 = path_args3 build_nodes_args2 = path_args2 build_nodes_args1 = path_args1 def buildNode(provider, node, source_ref, allow_none=False): if node is None and allow_none: return None try: kind = getKind(node) if hasattr(node, "lineno"): source_ref = source_ref.atLineNumber(node.lineno) if kind in build_nodes_args3: result = build_nodes_args3[kind]( provider=provider, node=node, source_ref=source_ref ) elif kind in build_nodes_args2: result = build_nodes_args2[kind](node=node, source_ref=source_ref) elif kind in build_nodes_args1: result = build_nodes_args1[kind](source_ref=source_ref) elif kind == "Pass": result = None else: assert False, ast.dump(node) if result is None and allow_none: return None assert isinstance(result, NodeBase), result return result except SyntaxError: raise except RuntimeError: # Very likely the stack overflow, which we will turn into too complex # code exception, don't warn about it with a code dump then. raise except KeyboardInterrupt: # User interrupting is not a problem with the source, but tell where # we got interrupted. optimization_logger.info("Interrupted at '%s'." % source_ref) raise except: optimization_logger.warning( "Problem at '%s' with %s." % (source_ref.getAsString(), ast.dump(node)) ) raise def buildNodeList(provider, nodes, source_ref, allow_none=False): if nodes is not None: result = [] for node in nodes: if hasattr(node, "lineno"): node_source_ref = source_ref.atLineNumber(node.lineno) else: node_source_ref = source_ref entry = buildNode(provider, node, node_source_ref, allow_none) if entry is not None: result.append(entry) return result else: return [] _host_node = None def buildAnnotationNode(provider, node, source_ref): if ( python_version >= 0x370 and provider.getParentModule().getFutureSpec().isFutureAnnotations() ): # Using global value for cache, to avoid creating it over and over, # avoiding the pylint: disable=global-statement global _host_node if _host_node is None: _host_node = ast.parse("x:1") _host_node.body[0].annotation = node r = compile( _host_node, "", "exec", __future__.CO_FUTURE_ANNOTATIONS, dont_inherit=True, ) # Using exec here, to compile the ast node tree back to string, # there is no accessible "ast.unparse", and this works as a hack # to convert our node to a string annotation, pylint: disable=exec-used m = {} exec(r, m) value = m["__annotations__"]["x"] if Options.is_debug and python_version >= 0x390: # TODO: In Python3.9+, we should only use ast.unparse assert value == ast.unparse(node) return makeConstantRefNode(constant=value, source_ref=source_ref) return buildNode(provider, node, source_ref) def makeModuleFrame(module, statements, source_ref): assert module.isCompiledPythonModule() if Options.is_fullcompat: code_name = "" else: if module.isMainModule(): code_name = "" else: code_name = "" % module.getFullName() return StatementsFrameModule( statements=statements, code_object=CodeObjectSpec( co_name=code_name, co_kind="Module", co_varnames=(), co_freevars=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=module.getFutureSpec(), ), source_ref=source_ref, ) def buildStatementsNode(provider, nodes, source_ref): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless # nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none=True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because # e.g. a global node generates not really a statement, or pass statements. if not statements: return None else: return StatementsSequence(statements=statements, source_ref=source_ref) def buildFrameNode(provider, nodes, code_object, source_ref): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless # nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none=True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because # e.g. a global node generates not really a statement, or pass statements. if not statements: return None if provider.isExpressionOutlineFunction(): provider = provider.getParentVariableProvider() if provider.isExpressionFunctionBody() or provider.isExpressionClassBody(): result = StatementsFrameFunction( statements=statements, code_object=code_object, source_ref=source_ref ) elif provider.isExpressionGeneratorObjectBody(): result = StatementsFrameGenerator( statements=statements, code_object=code_object, source_ref=source_ref ) elif provider.isExpressionCoroutineObjectBody(): result = StatementsFrameCoroutine( statements=statements, code_object=code_object, source_ref=source_ref ) elif provider.isExpressionAsyncgenObjectBody(): result = StatementsFrameAsyncgen( statements=statements, code_object=code_object, source_ref=source_ref ) else: assert False, provider return result def makeStatementsSequenceOrStatement(statements, source_ref): """Make a statement sequence, but only if more than one statement Useful for when we can unroll constructs already here, but are not sure if we actually did that. This avoids the branch or the pollution of doing it always. """ if len(statements) > 1: return StatementsSequence( statements=mergeStatements(statements), source_ref=source_ref ) else: return statements[0] def makeStatementsSequence(statements, allow_none, source_ref): if allow_none: statements = tuple( statement for statement in statements if statement is not None ) if statements: return StatementsSequence( statements=mergeStatements(statements, allow_none=allow_none), source_ref=source_ref, ) else: return None def makeStatementsSequenceFromStatement(statement): return StatementsSequence( statements=mergeStatements((statement,)), source_ref=statement.getSourceReference(), ) def makeStatementsSequenceFromStatements(*statements): assert statements assert None not in statements statements = mergeStatements(statements, allow_none=False) return StatementsSequence( statements=statements, source_ref=statements[0].getSourceReference() ) def makeDictCreationOrConstant2(keys, values, source_ref): # Create dictionary node. Tries to avoid it for constant values that are not # mutable. Keys are Python strings here. assert len(keys) == len(values) for value in values: if not value.isExpressionConstantRef(): constant = False break else: constant = True # Note: This would happen in optimization instead, but lets just do it # immediately to save some time. if constant: # Unless told otherwise, create the dictionary in its full size, so # that no growing occurs and the constant becomes as similar as possible # before being marshaled. result = makeConstantRefNode( constant=Constants.createConstantDict( keys=keys, values=[value.getCompileTimeConstant() for value in values] ), user_provided=True, source_ref=source_ref, ) else: result = makeExpressionMakeDict( pairs=[ ExpressionKeyValuePair( key=makeConstantRefNode( constant=key, source_ref=value.getSourceReference(), user_provided=True, ), value=value, source_ref=value.getSourceReference(), ) for key, value in zip(keys, values) ], source_ref=source_ref, ) if values: result.setCompatibleSourceReference( source_ref=values[-1].getCompatibleSourceReference() ) return result def getStatementsAppended(statement_sequence, statements): return makeStatementsSequence( statements=(statement_sequence, statements), allow_none=False, source_ref=statement_sequence.getSourceReference(), ) def getStatementsPrepended(statement_sequence, statements): return makeStatementsSequence( statements=(statements, statement_sequence), allow_none=False, source_ref=statement_sequence.getSourceReference(), ) def makeReraiseExceptionStatement(source_ref): return StatementReraiseException(source_ref=source_ref) def mangleName(name, owner): """Mangle names with leading "__" for usage in a class owner. Notes: The is the private name handling for Python classes. """ if not name.startswith("__") or name.endswith("__"): return name else: # The mangling of function variable names depends on being inside a # class. class_container = owner.getContainingClassDictCreation() if class_container is None: return name else: return "_%s%s" % (class_container.getName().lstrip("_"), name) def makeCallNode(called, *args, **kwargs): source_ref = args[-1] if len(args) > 1: args = makeExpressionMakeTupleOrConstant( elements=args[:-1], user_provided=True, source_ref=source_ref ) else: args = None if kwargs: kwargs = makeDictCreationOrConstant2( keys=tuple(kwargs.keys()), values=tuple(kwargs.values()), source_ref=source_ref, ) else: kwargs = None return makeExpressionCall( called=called, args=args, kw=kwargs, source_ref=source_ref ) build_contexts = [None] def pushBuildContext(value): build_contexts.append(value) def popBuildContext(): del build_contexts[-1] def getBuildContext(): return build_contexts[-1] Nuitka-0.6.19.1/nuitka/tree/ReformulationCallExpressions.py0000600000372100037210000002657214166627112030774 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of call expressions. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import StatementAssignmentVariable from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import ( makeExpressionMakeTuple, makeExpressionMakeTupleOrConstant, ) from nuitka.nodes.DictionaryNodes import ( makeExpressionMakeDictOrConstant, makeExpressionPairs, ) from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCall, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.PythonVersions import python_version from .ComplexCallHelperFunctions import ( getFunctionCallHelperDictionaryUnpacking, getFunctionCallHelperKeywordsStarDict, getFunctionCallHelperKeywordsStarList, getFunctionCallHelperKeywordsStarListStarDict, getFunctionCallHelperPosKeywordsStarDict, getFunctionCallHelperPosKeywordsStarList, getFunctionCallHelperPosKeywordsStarListStarDict, getFunctionCallHelperPosStarDict, getFunctionCallHelperPosStarList, getFunctionCallHelperPosStarListStarDict, getFunctionCallHelperStarDict, getFunctionCallHelperStarList, getFunctionCallHelperStarListStarDict, ) from .ReformulationDictionaryCreation import buildDictionaryUnpackingArgs from .ReformulationSequenceCreation import buildListUnpacking from .TreeHelpers import ( buildNode, buildNodeList, getKind, makeStatementsSequenceFromStatements, ) def buildCallNode(provider, node, source_ref): called = buildNode(provider, node.func, source_ref) if python_version >= 0x350: list_star_arg = None dict_star_arg = None positional_args = [] # For Python3.5 compatibility, the error handling with star argument last # is the old one, only with a starred argument before that, things use the # new unpacking code. for node_arg in node.args[:-1]: if getKind(node_arg) == "Starred": assert python_version >= 0x350 list_star_arg = buildListUnpacking(provider, node.args, source_ref) positional_args = [] break else: if node.args and getKind(node.args[-1]) == "Starred": assert python_version >= 0x350 list_star_arg = buildNode(provider, node.args[-1].value, source_ref) positional_args = buildNodeList(provider, node.args[:-1], source_ref) else: positional_args = buildNodeList(provider, node.args, source_ref) # Only the values of keyword pairs have a real source ref, and those only # really matter, so that makes sense. keys = [] values = [] for keyword in node.keywords[:-1]: if keyword.arg is None: assert python_version >= 0x350 outline_body = ExpressionOutlineBody( provider=provider, name="dict_unpacking_call", source_ref=source_ref ) tmp_called = outline_body.allocateTempVariable( temp_scope=None, name="called" ) helper_args = [ ExpressionTempVariableRef(variable=tmp_called, source_ref=source_ref), makeExpressionMakeTuple( elements=buildDictionaryUnpackingArgs( provider=provider, keys=(keyword.arg for keyword in node.keywords), values=(keyword.value for keyword in node.keywords), source_ref=source_ref, ), source_ref=source_ref, ), ] dict_star_arg = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getFunctionCallHelperDictionaryUnpacking(), source_ref=source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=helper_args, source_ref=source_ref, ) outline_body.setChild( "body", makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_called, source=called, source_ref=source_ref ), StatementReturn( expression=_makeCallNode( called=ExpressionTempVariableRef( variable=tmp_called, source_ref=source_ref ), positional_args=positional_args, keys=keys, values=values, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, source_ref=source_ref, ), source_ref=source_ref, ), ), ) return outline_body # For Python3.5 compatibility, the error handling with star argument last # is the old one, only with a starred argument before that, things use the # new unpacking code. if node.keywords and node.keywords[-1].arg is None: assert python_version >= 0x350 dict_star_arg = buildNode(provider, node.keywords[-1].value, source_ref) keywords = node.keywords[:-1] else: keywords = node.keywords for keyword in keywords: keys.append( makeConstantRefNode( constant=keyword.arg, source_ref=source_ref, user_provided=True ) ) values.append(buildNode(provider, keyword.value, source_ref)) if python_version < 0x350: list_star_arg = buildNode(provider, node.starargs, source_ref, True) dict_star_arg = buildNode(provider, node.kwargs, source_ref, True) return _makeCallNode( called=called, positional_args=positional_args, keys=keys, values=values, list_star_arg=list_star_arg, dict_star_arg=dict_star_arg, source_ref=source_ref, ) def _makeCallNode( called, positional_args, keys, values, list_star_arg, dict_star_arg, source_ref ): # Many variables, but only to cover the many complex call cases. if list_star_arg is None and dict_star_arg is None: result = makeExpressionCall( called=called, args=makeExpressionMakeTupleOrConstant( elements=positional_args, user_provided=True, source_ref=source_ref, ), kw=makeExpressionMakeDictOrConstant( makeExpressionPairs(keys=keys, values=values), user_provided=True, source_ref=source_ref, ), source_ref=source_ref, ) # Bug compatible line numbers before Python 3.8 if python_version < 0x380: if values: result.setCompatibleSourceReference( source_ref=values[-1].getCompatibleSourceReference() ) elif positional_args: result.setCompatibleSourceReference( source_ref=positional_args[-1].getCompatibleSourceReference() ) return result else: # Dispatch to complex helper function for each case. These do # re-formulation of complex calls according to Developer Manual. key = ( bool(positional_args), bool(keys), list_star_arg is not None, dict_star_arg is not None, ) table = { (True, True, True, False): getFunctionCallHelperPosKeywordsStarList, (True, False, True, False): getFunctionCallHelperPosStarList, (False, True, True, False): getFunctionCallHelperKeywordsStarList, (False, False, True, False): getFunctionCallHelperStarList, (True, True, False, True): getFunctionCallHelperPosKeywordsStarDict, (True, False, False, True): getFunctionCallHelperPosStarDict, (False, True, False, True): getFunctionCallHelperKeywordsStarDict, (False, False, False, True): getFunctionCallHelperStarDict, (True, True, True, True): getFunctionCallHelperPosKeywordsStarListStarDict, (True, False, True, True): getFunctionCallHelperPosStarListStarDict, (False, True, True, True): getFunctionCallHelperKeywordsStarListStarDict, (False, False, True, True): getFunctionCallHelperStarListStarDict, } get_helper = table[key] helper_args = [called] if positional_args: helper_args.append( makeExpressionMakeTupleOrConstant( elements=positional_args, user_provided=True, source_ref=source_ref, ) ) # Order of evaluation changed in Python3.5. if python_version >= 0x350 and list_star_arg is not None: helper_args.append(list_star_arg) if keys: helper_args.append( makeExpressionMakeDictOrConstant( pairs=makeExpressionPairs(keys=keys, values=values), user_provided=True, source_ref=source_ref, ) ) # Order of evaluation changed in Python3.5. if python_version < 0x350 and list_star_arg is not None: helper_args.append(list_star_arg) if dict_star_arg is not None: helper_args.append(dict_star_arg) result = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=get_helper(), source_ref=source_ref ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=helper_args, source_ref=source_ref, ) # Bug compatible line numbers before Python 3.8 if python_version < 0x380: result.setCompatibleSourceReference( source_ref=helper_args[-1].getCompatibleSourceReference() ) return result Nuitka-0.6.19.1/nuitka/tree/ReformulationAssignmentStatements.py0000600000372100037210000012126314166627112032027 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of assignment statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementAssignmentVariableName, StatementDelVariable, StatementDelVariableName, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import ( StatementAssignmentAttribute, StatementDelAttribute, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinIteratorNodes import ( ExpressionBuiltinIter1, ExpressionBuiltinIterForUnpack, StatementSpecialUnpackCheck, ) from nuitka.nodes.BuiltinLenNodes import ExpressionBuiltinLen from nuitka.nodes.BuiltinNextNodes import ExpressionSpecialUnpack from nuitka.nodes.BuiltinTypeNodes import ExpressionBuiltinList from nuitka.nodes.ComparisonNodes import makeComparisonExpression from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import ( ExpressionConstantEllipsisRef, makeConstantRefNode, ) from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTupleOrConstant from nuitka.nodes.ContainerOperationNodes import ExpressionListOperationPop from nuitka.nodes.NodeMakingHelpers import ( makeRaiseExceptionExpressionFromTemplate, ) from nuitka.nodes.OperatorNodes import ( makeBinaryOperationNode, makeExpressionOperationBinaryInplace, ) from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.SliceNodes import ( ExpressionSliceLookup, StatementAssignmentSlice, StatementDelSlice, makeExpressionBuiltinSlice, ) from nuitka.nodes.SubscriptNodes import ( ExpressionSubscriptLookup, StatementAssignmentSubscript, StatementDelSubscript, ) from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableLocalNameRef, ExpressionVariableNameRef, ) from nuitka.Options import hasPythonFlagNoAnnotations from nuitka.PythonVersions import python_version from .ReformulationImportStatements import getFutureSpec from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .SyntaxErrors import raiseSyntaxError from .TreeHelpers import ( buildAnnotationNode, buildNode, getKind, makeStatementsSequence, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, makeStatementsSequenceOrStatement, mangleName, ) def buildExtSliceNode(provider, node, source_ref): elements = [] for dim in node.slice.dims: dim_kind = getKind(dim) if dim_kind == "Slice": lower = buildNode(provider, dim.lower, source_ref, True) upper = buildNode(provider, dim.upper, source_ref, True) step = buildNode(provider, dim.step, source_ref, True) element = makeExpressionBuiltinSlice( start=lower, stop=upper, step=step, source_ref=source_ref ) elif dim_kind == "Ellipsis": element = ExpressionConstantEllipsisRef(source_ref=source_ref) elif dim_kind == "Index": element = buildNode( provider=provider, node=dim.value, source_ref=source_ref ) else: assert False, dim elements.append(element) return makeExpressionMakeTupleOrConstant( elements=elements, user_provided=True, source_ref=source_ref ) def buildAssignmentStatementsFromDecoded(provider, kind, detail, source, source_ref): # This is using many variable names on purpose, so as to give names to the # unpacked detail values, and has many branches due to the many cases # dealt with, pylint: disable=too-many-branches,too-many-locals,too-many-statements if kind == "Name": return StatementAssignmentVariableName( provider=provider, variable_name=detail, source=source, source_ref=source_ref, ) elif kind == "Attribute": lookup_source, attribute_name = detail return StatementAssignmentAttribute( expression=lookup_source, attribute_name=mangleName(attribute_name, provider), source=source, source_ref=source_ref, ) elif kind == "Subscript": subscribed, subscript = detail return StatementAssignmentSubscript( subscribed=subscribed, subscript=subscript, source=source, source_ref=source_ref, ) elif kind == "Slice": lookup_source, lower, upper = detail # For Python3 there is no slicing operation, this is always done # with subscript using a slice object. For Python2, it is only done # if no "step" is provided. use_sliceobj = python_version >= 0x300 if use_sliceobj: return StatementAssignmentSubscript( subscribed=lookup_source, source=source, subscript=makeExpressionBuiltinSlice( start=lower, stop=upper, step=None, source_ref=source_ref ), source_ref=source_ref, ) else: return StatementAssignmentSlice( expression=lookup_source, lower=lower, upper=upper, source=source, source_ref=source_ref, ) elif kind == "Tuple": temp_scope = provider.allocateTempScope("tuple_unpack") source_iter_var = provider.allocateTempVariable( temp_scope=temp_scope, name="source_iter" ) element_vars = [ provider.allocateTempVariable( temp_scope=temp_scope, name="element_%d" % (element_index + 1) ) for element_index in range(len(detail)) ] starred_list_var = None starred_index = None statements = [] for element_index, element in enumerate(detail): if element[0] == "Starred": if starred_index is not None: raiseSyntaxError( "two starred expressions in assignment" if python_version < 0x390 else "multiple starred expressions in assignment", source_ref.atColumnNumber(0), ) starred_index = element_index for element_index, element in enumerate(detail): element_var = element_vars[element_index] if starred_list_var is not None: statements.insert( starred_index + 1, StatementAssignmentVariable( variable=element_var, source=ExpressionListOperationPop( list_arg=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), ) elif element[0] != "Starred": statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), count=element_index + 1, expected=starred_index or len(detail), starred=starred_index is not None, source_ref=source_ref, ), source_ref=source_ref, ) ) else: assert starred_index == element_index starred_list_var = element_var statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionBuiltinList( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ) if starred_list_var is None: statements.append( StatementSpecialUnpackCheck( iterator=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), count=len(detail), source_ref=source_ref, ) ) else: statements.insert( starred_index + 1, makeStatementConditional( condition=makeComparisonExpression( comparator="Lt", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), right=makeConstantRefNode( constant=len(statements) - starred_index - 1, source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="ValueError", template="""\ not enough values to unpack (expected at least %d, got %%d)""" % (len(statements) - 1), template_args=makeBinaryOperationNode( operator="Add", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), right=makeConstantRefNode( constant=starred_index, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ).asStatement(), no_branch=None, source_ref=source_ref, ), ) if python_version >= 0x370: iter_creation_class = ExpressionBuiltinIterForUnpack else: iter_creation_class = ExpressionBuiltinIter1 statements = [ StatementAssignmentVariable( variable=source_iter_var, source=iter_creation_class(value=source, source_ref=source_ref), source_ref=source_ref, ), makeTryFinallyStatement( provider=provider, tried=statements, final=( StatementReleaseVariable( variable=source_iter_var, source_ref=source_ref ), ), source_ref=source_ref, ), ] # When all is done, copy over to the actual assignment targets, starred # or not makes no difference here anymore. for element_index, element in enumerate(detail): if element[0] == "Starred": element = element[1] element_var = element_vars[element_index] statements.append( buildAssignmentStatementsFromDecoded( provider=provider, kind=element[0], detail=element[1], source=ExpressionTempVariableRef( variable=element_var, source_ref=source_ref ), source_ref=source_ref, ) ) # Need to release temporary variables right after successful # usage. statements.append( StatementDelVariable( variable=element_var, tolerant=True, source_ref=source_ref ) ) final_statements = [] for element_var in element_vars: final_statements.append( StatementReleaseVariable(variable=element_var, source_ref=source_ref) ) return makeTryFinallyStatement( provider=provider, tried=statements, final=final_statements, source_ref=source_ref, ) elif kind == "Starred": raiseSyntaxError( "starred assignment target must be in a list or tuple", source_ref.atColumnNumber(0), ) else: assert False, (kind, source_ref, detail) def buildAssignmentStatements( provider, node, source, source_ref, allow_none=False, temp_provider=None ): if node is None and allow_none: return None if temp_provider is None: temp_provider = provider kind, detail = decodeAssignTarget( provider=provider, node=node, source_ref=source_ref ) return buildAssignmentStatementsFromDecoded( provider=provider, kind=kind, detail=detail, source=source, source_ref=source_ref, ) def decodeAssignTarget(provider, node, source_ref, allow_none=False): # Many cases to deal with, because of the different assign targets, # pylint: disable=too-many-branches,too-many-return-statements if node is None and allow_none: return None if type(node) is str: return "Name", mangleName(node, provider) kind = getKind(node) if hasattr(node, "ctx"): assert getKind(node.ctx) in ("Store", "Del") if kind == "Name": return kind, mangleName(node.id, provider) elif kind == "Attribute": return kind, (buildNode(provider, node.value, source_ref), node.attr) elif kind == "Subscript": slice_kind = getKind(node.slice) if slice_kind == "Index": return ( "Subscript", ( buildNode(provider, node.value, source_ref), buildNode(provider, node.slice.value, source_ref), ), ) elif slice_kind == "Slice": lower = buildNode(provider, node.slice.lower, source_ref, True) upper = buildNode(provider, node.slice.upper, source_ref, True) if node.slice.step is not None: step = buildNode(provider, node.slice.step, source_ref) return ( "Subscript", ( buildNode(provider, node.value, source_ref), makeExpressionBuiltinSlice( start=lower, stop=upper, step=step, source_ref=source_ref ), ), ) else: return ( "Slice", (buildNode(provider, node.value, source_ref), lower, upper), ) elif slice_kind == "ExtSlice": return ( "Subscript", ( buildNode(provider, node.value, source_ref), buildExtSliceNode(provider, node, source_ref), ), ) elif slice_kind == "Ellipsis": return ( "Subscript", ( buildNode(provider, node.value, source_ref), ExpressionConstantEllipsisRef(source_ref=source_ref), ), ) elif python_version >= 0x390: return ( "Subscript", ( buildNode(provider, node.value, source_ref), buildNode(provider, node.slice, source_ref), ), ) else: assert False, slice_kind elif kind in ("Tuple", "List"): return ( "Tuple", tuple( decodeAssignTarget( provider=provider, node=sub_node, source_ref=source_ref, allow_none=False, ) for sub_node in node.elts ), ) elif kind == "Starred": return ( "Starred", decodeAssignTarget( provider=provider, node=node.value, source_ref=source_ref, allow_none=False, ), ) else: assert False, (source_ref, kind) def buildAssignNode(provider, node, source_ref): assert len(node.targets) >= 1, source_ref # Evaluate the right hand side first, so it can get names provided # before the left hand side exists. source = buildNode(provider, node.value, source_ref) if len(node.targets) == 1: # Simple assignment case, one source, one target. return buildAssignmentStatements( provider=provider, node=node.targets[0], source=source, source_ref=source_ref, ) else: # Complex assignment case, one source, but multiple targets. We keep the # source in a temporary variable, and then assign from it multiple # times. temp_scope = provider.allocateTempScope("assign_unpack") tmp_source = provider.allocateTempVariable( temp_scope=temp_scope, name="assign_source" ) statements = [ StatementAssignmentVariable( variable=tmp_source, source=source, source_ref=source_ref ) ] for target in node.targets: statements.append( buildAssignmentStatements( provider=provider, node=target, source=ExpressionTempVariableRef( variable=tmp_source, source_ref=source_ref ), source_ref=source_ref, ) ) return makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable(variable=tmp_source, source_ref=source_ref), source_ref=source_ref, ) def buildAnnAssignNode(provider, node, source_ref): """Python3.6 annotation assignment.""" # There are many cases to deal with here. if provider.isCompiledPythonModule() or provider.isExpressionClassBody(): provider.markAsNeedsAnnotationsDictionary() # Evaluate the right hand side first, so it can get names provided # before the left hand side exists. statements = [] if node.value is not None: source = buildNode(provider, node.value, source_ref) statements.append( buildAssignmentStatements( provider=provider, node=node.target, source=source, source_ref=source_ref, ) ) # Only name referencing annotations are effective right now. if statements[-1].isStatementAssignmentVariableName(): variable_name = statements[-1].getVariableName() else: variable_name = None else: # Only name referencing annotations are effective right now. kind, detail = decodeAssignTarget( provider=provider, node=node.target, source_ref=source_ref ) if kind == "Name": variable_name = detail else: variable_name = None # Only annotations for modules and classes are really made, for functions # they are ignored like comments. if variable_name is not None: if not hasPythonFlagNoAnnotations() and ( provider.isExpressionClassBody() or provider.isCompiledPythonModule() ): annotation = buildAnnotationNode(provider, node.annotation, source_ref) # TODO: As CPython core considers this implementation detail, and it seems # mostly useless to support having this as a closure taken name after a # __del__ on annotations, we might do this except in full compat mode. It # will produce only noise for all annotations in classes otherwise. if python_version < 0x370: ref_class = ExpressionVariableLocalNameRef else: ref_class = ExpressionVariableNameRef statements.append( StatementAssignmentSubscript( subscribed=ref_class( provider=provider, variable_name="__annotations__", source_ref=source_ref, ), subscript=makeConstantRefNode( constant=variable_name, source_ref=source_ref ), source=annotation, source_ref=source_ref, ) ) else: # Functions or disabled. if node.simple: provider.getVariableForAssignment(variable_name) return makeStatementsSequence( statements=statements, allow_none=True, source_ref=source_ref ) def buildDeleteStatementFromDecoded(provider, kind, detail, source_ref): # This function is a case driven by returns, pylint: disable=too-many-return-statements if kind in ("Name", "Name_Exception"): # Note: Name_Exception is a "del" for exception handlers that doesn't # insist on the variable being defined, user code may do it too, and # that will be fine, so make that tolerant. return StatementDelVariableName( provider=provider, variable_name=detail, tolerant=kind == "Name_Exception", source_ref=source_ref, ) elif kind == "Attribute": lookup_source, attribute_name = detail return StatementDelAttribute( expression=lookup_source, attribute_name=mangleName(attribute_name, provider), source_ref=source_ref, ) elif kind == "Subscript": subscribed, subscript = detail return StatementDelSubscript( subscribed=subscribed, subscript=subscript, source_ref=source_ref ) elif kind == "Slice": lookup_source, lower, upper = detail use_sliceobj = python_version >= 0x300 if use_sliceobj: return StatementDelSubscript( subscribed=lookup_source, subscript=makeExpressionBuiltinSlice( start=lower, stop=upper, step=None, source_ref=source_ref ), source_ref=source_ref, ) else: return StatementDelSlice( expression=lookup_source, lower=lower, upper=upper, source_ref=source_ref, ) elif kind == "Tuple": result = [] for sub_node in detail: result.append( buildDeleteStatementFromDecoded( provider=provider, kind=sub_node[0], detail=sub_node[1], source_ref=source_ref, ) ) if result: return makeStatementsSequenceOrStatement( statements=result, source_ref=source_ref ) else: return None else: assert False, (kind, detail, source_ref) def buildDeleteNode(provider, node, source_ref): # Build "del" statements. # Note: Each delete is sequential. It can succeed, and the failure of a # later one does not prevent the former to succeed. We can therefore have a # simple sequence of "del" statements that each only delete one thing # therefore. In output tree "del" therefore only ever has single arguments. statements = [] for target in node.targets: kind, detail = decodeAssignTarget( provider=provider, node=target, source_ref=source_ref ) statements.append( buildDeleteStatementFromDecoded( provider=provider, kind=kind, detail=detail, source_ref=source_ref ) ) return makeStatementsSequenceOrStatement( statements=statements, source_ref=source_ref ) def _buildInplaceAssignVariableNode( provider, variable_name, operator, expression, source_ref ): inplace_node = makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionVariableNameRef( provider=provider, variable_name=variable_name, source_ref=source_ref ), right=expression, source_ref=source_ref, ) inplace_node.markAsInplaceSuspect() return ( StatementAssignmentVariableName( provider=provider, variable_name=variable_name, source=inplace_node, source_ref=source_ref, ), ) def _buildInplaceAssignAttributeNode( provider, lookup_source, attribute_name, operator, expression, source_ref ): temp_scope = provider.allocateTempScope("inplace_assign") tmp_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="value") # First assign the target value to a temporary variable. preserve_to_tmp = StatementAssignmentVariable( variable=tmp_variable, source=makeExpressionAttributeLookup( expression=lookup_source.makeClone(), attribute_name=attribute_name, source_ref=source_ref, ), source_ref=source_ref, ) # Second assign the in-place result to a temporary variable inplace_to_tmp = StatementAssignmentVariable( variable=tmp_variable, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), right=expression, source_ref=source_ref, ), source_ref=source_ref, ) # Third, copy it back. copy_back_from_tmp = StatementAssignmentAttribute( expression=lookup_source.makeClone(), attribute_name=attribute_name, source=ExpressionTempVariableRef(variable=tmp_variable, source_ref=source_ref), source_ref=source_ref, ) return ( preserve_to_tmp, # making sure the above temporary variable is deleted in any case. makeTryFinallyStatement( provider=provider, tried=(inplace_to_tmp, copy_back_from_tmp), final=StatementReleaseVariable( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), ) def _buildInplaceAssignSubscriptNode( provider, subscribed, subscript, tmp_variable1, tmp_variable2, tmp_variable3, operator, expression, source_ref, ): # First assign the subscribed value to a temporary variable. preserve_to_tmp1 = StatementAssignmentVariable( variable=tmp_variable1, source=subscribed, source_ref=source_ref ) # Second assign the subscript value to a temporary variable statements = ( StatementAssignmentVariable( variable=tmp_variable2, source=subscript, source_ref=source_ref ), StatementAssignmentVariable( variable=tmp_variable3, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_variable2, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable3, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef( variable=tmp_variable3, source_ref=source_ref ), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_variable2, source_ref=source_ref ), source=ExpressionTempVariableRef( variable=tmp_variable3, source_ref=source_ref ), source_ref=source_ref, ), ) return ( preserve_to_tmp1, makeTryFinallyStatement( provider=provider, tried=statements, final=( StatementReleaseVariable(variable=tmp_variable1, source_ref=source_ref), StatementReleaseVariable(variable=tmp_variable2, source_ref=source_ref), StatementReleaseVariable(variable=tmp_variable3, source_ref=source_ref), ), source_ref=source_ref, ), ) def _buildInplaceAssignSliceNode( provider, lookup_source, lower, upper, tmp_variable1, tmp_variable2, tmp_variable3, tmp_variable4, operator, expression, source_ref, ): # Due to the 3 inputs, which we need to also put into temporary variables, # there are too many variables here, but they are needed. # pylint: disable=too-many-locals # First assign the target value, lower and upper to temporary variables. copy_to_tmp = StatementAssignmentVariable( variable=tmp_variable1, source=lookup_source, source_ref=source_ref ) final_statements = [ StatementReleaseVariable(variable=tmp_variable1, source_ref=source_ref) ] statements = [] if lower is not None: statements.append( StatementAssignmentVariable( variable=tmp_variable2, source=lower, source_ref=source_ref ) ) final_statements.append( StatementReleaseVariable(variable=tmp_variable2, source_ref=source_ref) ) lower_ref1 = ExpressionTempVariableRef( variable=tmp_variable2, source_ref=source_ref ) lower_ref2 = ExpressionTempVariableRef( variable=tmp_variable2, source_ref=source_ref ) else: assert tmp_variable2 is None lower_ref1 = lower_ref2 = None if upper is not None: statements.append( StatementAssignmentVariable( variable=tmp_variable3, source=upper, source_ref=source_ref ) ) final_statements.append( StatementReleaseVariable(variable=tmp_variable3, source_ref=source_ref) ) upper_ref1 = ExpressionTempVariableRef( variable=tmp_variable3, source_ref=source_ref ) upper_ref2 = ExpressionTempVariableRef( variable=tmp_variable3, source_ref=source_ref ) else: assert tmp_variable3 is None upper_ref1 = upper_ref2 = None use_sliceobj = python_version >= 0x300 # Second assign the in-place result over the original value. if use_sliceobj: statements += ( StatementAssignmentVariable( variable=tmp_variable4, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), subscript=makeExpressionBuiltinSlice( start=lower_ref2, stop=upper_ref2, step=None, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable4, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef( variable=tmp_variable4, source_ref=source_ref ), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), subscript=makeExpressionBuiltinSlice( start=lower_ref1, stop=upper_ref1, step=None, source_ref=source_ref ), source=ExpressionTempVariableRef( variable=tmp_variable4, source_ref=source_ref ), source_ref=source_ref, ), ) else: statements += ( StatementAssignmentVariable( variable=tmp_variable4, source=ExpressionSliceLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), lower=lower_ref2, upper=upper_ref2, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable4, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef( variable=tmp_variable4, source_ref=source_ref ), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSlice( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref ), lower=lower_ref1, upper=upper_ref1, source=ExpressionTempVariableRef( variable=tmp_variable4, source_ref=source_ref ), source_ref=source_ref, ), ) final_statements.append( StatementReleaseVariable(variable=tmp_variable4, source_ref=source_ref) ) return ( copy_to_tmp, makeTryFinallyStatement( provider=provider, tried=statements, final=final_statements, source_ref=source_ref, ), ) def buildInplaceAssignNode(provider, node, source_ref): # There are many inplace assignment variables, and the detail is unpacked # into names, so we end up with a lot of variables, which is on purpose, # pylint: disable=too-many-locals operator = getKind(node.op) operator = "I" + operator if operator == "IDiv": operator = "ITrueDiv" if getFutureSpec().isFutureDivision() else "IOldDiv" expression = buildNode(provider, node.value, source_ref) kind, detail = decodeAssignTarget( provider=provider, node=node.target, source_ref=source_ref ) if kind == "Name": statements = _buildInplaceAssignVariableNode( provider=provider, variable_name=detail, operator=operator, expression=expression, source_ref=source_ref, ) elif kind == "Attribute": lookup_source, attribute_name = detail statements = _buildInplaceAssignAttributeNode( provider=provider, lookup_source=lookup_source, attribute_name=mangleName(attribute_name, provider), operator=operator, expression=expression, source_ref=source_ref, ) elif kind == "Subscript": subscribed, subscript = detail temp_scope = provider.allocateTempScope("inplace_assign_subscr") tmp_variable1 = provider.allocateTempVariable( temp_scope=temp_scope, name="target" ) tmp_variable2 = provider.allocateTempVariable( temp_scope=temp_scope, name="subscript" ) tmp_variable3 = provider.allocateTempVariable( temp_scope=temp_scope, name="value" ) statements = _buildInplaceAssignSubscriptNode( provider=provider, subscribed=subscribed, subscript=subscript, tmp_variable1=tmp_variable1, tmp_variable2=tmp_variable2, tmp_variable3=tmp_variable3, operator=operator, expression=expression, source_ref=source_ref, ) elif kind == "Slice": lookup_source, lower, upper = detail temp_scope = provider.allocateTempScope("inplace_assign_slice") tmp_variable1 = provider.allocateTempVariable( temp_scope=temp_scope, name="target" ) if lower is not None: tmp_variable2 = provider.allocateTempVariable( temp_scope=temp_scope, name="lower" ) else: tmp_variable2 = None if upper is not None: tmp_variable3 = provider.allocateTempVariable( temp_scope=temp_scope, name="upper" ) else: tmp_variable3 = None tmp_variable4 = provider.allocateTempVariable( temp_scope=temp_scope, name="value" ) statements = _buildInplaceAssignSliceNode( provider=provider, lookup_source=lookup_source, lower=lower, upper=upper, tmp_variable1=tmp_variable1, tmp_variable2=tmp_variable2, tmp_variable3=tmp_variable3, tmp_variable4=tmp_variable4, operator=operator, expression=expression, source_ref=source_ref, ) else: assert False, kind return makeStatementsSequenceFromStatements(*statements) def buildNamedExprNode(provider, node, source_ref): """Assignment expressions, Python3.8 or higher only.""" outline_body = ExpressionOutlineBody( provider=provider, name="assignment_expr", source_ref=source_ref ) tmp_value = outline_body.allocateTempVariable(temp_scope=None, name="value") value = buildNode(provider=provider, node=node.value, source_ref=source_ref) locals_owner = provider while locals_owner.isExpressionOutlineFunction(): locals_owner = locals_owner.getParentVariableProvider() variable_name = node.target.id if ( locals_owner.isExpressionGeneratorObjectBody() and locals_owner.name == "" ): locals_owner.addNonlocalsDeclaration( (variable_name,), user_provided=False, source_ref=source_ref ) statements = ( StatementAssignmentVariable( variable=tmp_value, source=value, source_ref=source_ref ), StatementAssignmentVariableName( provider=locals_owner, variable_name=variable_name, source=ExpressionTempVariableRef(variable=tmp_value, source_ref=source_ref), source_ref=source_ref, ), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_value, source_ref=source_ref ), source_ref=source_ref, ), ) outline_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable( variable=tmp_value, source_ref=source_ref ), source_ref=source_ref, ) ), ) return outline_body Nuitka-0.6.19.1/nuitka/tree/ReformulationForLoopStatements.py0000600000372100037210000001701014166627112031271 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reformulation of for loop statements. Consult the Developer Manual for information. TODO: Add ability to sync source code comments with Developer Manual sections. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.BuiltinIteratorNodes import ( ExpressionAsyncIter, ExpressionAsyncNext, ExpressionBuiltinIter1, ) from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import makeStatementConditional from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.StatementNodes import StatementsSequence from nuitka.nodes.VariableRefNodes import ExpressionTempVariableRef from nuitka.nodes.YieldNodes import ExpressionYieldFromWaitable from .ReformulationAssignmentStatements import buildAssignmentStatements from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( buildNode, buildStatementsNode, makeStatementsSequence, makeStatementsSequenceFromStatements, popBuildContext, pushBuildContext, ) def _buildForLoopNode(provider, node, sync, source_ref): # The for loop is re-formulated according to Developer Manual. An iterator # is created, and looped until it gives StopIteration. The else block is # taken if a for loop exits normally, i.e. because of iterator # exhaustion. We do this by introducing an indicator variable. # We handle async and sync both here, leading to cases, pylint: disable=too-many-locals source = buildNode(provider, node.iter, source_ref) # Temporary variables, we need one for the iterator, and one for the current # value. temp_scope = provider.allocateTempScope("for_loop") tmp_iter_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="for_iterator" ) tmp_value_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="iter_value" ) else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref, ) if else_block is not None: # Indicator variable, will end up with C bool type, and need not be released. tmp_break_indicator = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator", temp_type="bool" ) statements = [ StatementAssignmentVariable( variable=tmp_break_indicator, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ) ] else: statements = [] statements.append(StatementLoopBreak(source_ref=source_ref)) handler_body = makeStatementsSequence( statements=statements, allow_none=False, source_ref=source_ref ) if sync: next_node = ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref ), source_ref=source_ref, ) else: next_node = ExpressionYieldFromWaitable( expression=ExpressionAsyncNext( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) statements = ( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_value_variable, source=next_node, source_ref=source_ref ), exception_name="StopIteration" if sync else "StopAsyncIteration", handler_body=handler_body, source_ref=source_ref, ), buildAssignmentStatements( provider=provider, node=node.target, source=ExpressionTempVariableRef( variable=tmp_value_variable, source_ref=source_ref ), source_ref=source_ref, ), ) pushBuildContext("loop_body") statements += ( buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref), ) popBuildContext() loop_body = makeStatementsSequence( statements=statements, allow_none=True, source_ref=source_ref ) cleanup_statements = [ StatementReleaseVariable(variable=tmp_value_variable, source_ref=source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=source_ref), ] if else_block is not None: statements = [ StatementAssignmentVariable( variable=tmp_break_indicator, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ) ] else: statements = [] if sync: iter_source = ExpressionBuiltinIter1( value=source, source_ref=source.getSourceReference() ) else: iter_source = ExpressionYieldFromWaitable( expression=ExpressionAsyncIter( value=source, source_ref=source.getSourceReference() ), source_ref=source.getSourceReference(), ) statements += ( # First create the iterator and store it. StatementAssignmentVariable( variable=tmp_iter_variable, source=iter_source, source_ref=source_ref ), makeTryFinallyStatement( provider=provider, tried=StatementLoop(loop_body=loop_body, source_ref=source_ref), final=StatementsSequence( statements=cleanup_statements, source_ref=source_ref ), source_ref=source_ref, ), ) if else_block is not None: statements.append( makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref ), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=else_block, no_branch=None, source_ref=source_ref, ) ) return makeStatementsSequenceFromStatements(*statements) def buildForLoopNode(provider, node, source_ref): return _buildForLoopNode(provider, node, True, source_ref) def buildAsyncForLoopNode(provider, node, source_ref): return _buildForLoopNode(provider, node, False, source_ref) Nuitka-0.6.19.1/nuitka/tree/__init__.py0000600000372100037210000000150114166627112024627 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tree/VariableClosure.py0000600000372100037210000004651614166627112026171 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Variable closure taking. This is the completion of variable object completion. The variables were not immediately resolved to be bound to actual scopes, but are only now. Only after this is executed, variable reference nodes can be considered complete. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementDelVariable, StatementReleaseVariable, ) from nuitka.nodes.FunctionNodes import MaybeLocalVariableUsage from nuitka.nodes.LocalsDictNodes import ( ExpressionLocalsVariableRef, ExpressionLocalsVariableRefOrFallback, StatementLocalsDictOperationDel, StatementLocalsDictOperationSet, ) from nuitka.nodes.NodeMakingHelpers import ( makeConstantReplacementNode, mergeStatements, ) from nuitka.nodes.OperatorNodes import makeExpressionOperationBinaryInplace from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, makeExpressionVariableRef, ) from nuitka.PythonVersions import ( getErrorMessageExecWithNestedFunction, python_version, ) from nuitka.Variables import isSharedAmongScopes, releaseSharedScopeInformation from .Operations import VisitorNoopMixin, visitTree from .ReformulationFunctionStatements import addFunctionVariableReleases from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .SyntaxErrors import raiseSyntaxError # Note: We do the variable scope assignment, as an extra step from tree # building, because tree building creates the tree without any consideration of # evaluation order. And the ordered way these visitors are entered, will ensure # this order. # The main complexity is that there are two ways of visiting. One where variable # lookups are to be done immediately, and one where it is delayed. This is # basically class vs. function scope handling. class VariableClosureLookupVisitorPhase1(VisitorNoopMixin): """Variable closure phase 1: Find assignments and early closure references. In class context, a reference to a variable must be obeyed immediately, so that "variable = variable" takes first "variable" as a closure and then adds a new local "variable" to override it from there on. For the not early closure case of a function, this will not be done and only assignments shall add local variables, and references will be ignored until phase 2. """ @staticmethod def _handleNonLocal(node): # Take closure variables for non-local declarations. for ( non_local_names, user_provided, source_ref, ) in node.consumeNonlocalDeclarations(): for non_local_name in non_local_names: variable = node.takeVariableForClosure(variable_name=non_local_name) node.getLocalsScope().registerClosureVariable(variable) if variable.isModuleVariable() and user_provided: raiseSyntaxError( "no binding for nonlocal '%s' found" % (non_local_name), source_ref, ) variable.addVariableUser(node) @staticmethod def _handleQualnameSetup(node): if node.qualname_setup is not None: provider = node.getParentVariableProvider() if node.isExpressionClassBody(): class_variable_name, qualname_assign = node.qualname_setup if provider.hasProvidedVariable(class_variable_name): class_variable = provider.getVariableForReference( class_variable_name ) if class_variable.isModuleVariable(): qualname_node = qualname_assign.subnode_source new_node = makeConstantReplacementNode( constant=class_variable.getName(), node=qualname_node, user_provided=True, ) parent = qualname_node.parent qualname_node.finalize() parent.replaceChild(qualname_node, new_node) node.qualname_provider = node.getParentModule() else: if provider.hasProvidedVariable(node.qualname_setup): function_variable = provider.getVariableForReference( node.qualname_setup ) if function_variable.isModuleVariable(): node.qualname_provider = node.getParentModule() # TODO: Actually for nested global classes, this approach # may not work, as their "qualname" will be wrong. In that # case a dedicated node for "qualname" references might be # needed. node.qualname_setup = None @staticmethod def _shouldUseLocalsDict(provider, variable_name): return provider.isExpressionClassBody() and ( not provider.hasProvidedVariable(variable_name) or provider.getProvidedVariable(variable_name).getOwner() is provider ) def onLeaveNode(self, node): if node.isStatementAssignmentVariableName(): variable_name = node.getVariableName() provider = node.provider # Classes always assign to locals dictionary except for closure # variables taken. if self._shouldUseLocalsDict(provider, variable_name): if node.subnode_source.isExpressionOperationInplace(): temp_scope = provider.allocateTempScope("class_inplace") tmp_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="value" ) statements = mergeStatements( statements=( StatementAssignmentVariable( variable=tmp_variable, source=node.subnode_source.subnode_left, source_ref=node.source_ref, ), makeTryFinallyStatement( provider=provider, tried=( StatementAssignmentVariable( variable=tmp_variable, source=makeExpressionOperationBinaryInplace( left=ExpressionTempVariableRef( variable=tmp_variable, source_ref=node.source_ref, ), right=node.subnode_source.subnode_right, operator=node.subnode_source.getOperator(), source_ref=node.source_ref, ), source_ref=node.source_ref, ), StatementLocalsDictOperationSet( locals_scope=provider.getLocalsScope(), variable_name=variable_name, value=ExpressionTempVariableRef( variable=tmp_variable, source_ref=node.source_ref, ), source_ref=node.source_ref, ), ), final=StatementReleaseVariable( variable=tmp_variable, source_ref=node.source_ref ), source_ref=node.source_ref, ), ) ) node.parent.replaceStatement(node, statements) else: new_node = StatementLocalsDictOperationSet( locals_scope=provider.getLocalsScope(), variable_name=variable_name, value=node.subnode_source, source_ref=node.source_ref, ) node.parent.replaceChild(node, new_node) else: variable = provider.getVariableForAssignment( variable_name=variable_name ) new_node = StatementAssignmentVariable( variable=variable, source=node.subnode_source, source_ref=node.source_ref, ) variable.addVariableUser(provider) node.parent.replaceChild(node, new_node) del node.parent del node.provider elif node.isStatementDelVariableName(): variable_name = node.getVariableName() provider = node.provider if self._shouldUseLocalsDict(provider, variable_name): # Classes always assign to locals dictionary except for closure # variables taken. new_node = StatementLocalsDictOperationDel( locals_scope=provider.getLocalsScope(), variable_name=variable_name, tolerant=node.tolerant, source_ref=node.source_ref, ) else: variable = provider.getVariableForAssignment( variable_name=variable_name ) new_node = StatementDelVariable( variable=variable, tolerant=node.tolerant, source_ref=node.source_ref, ) variable.addVariableUser(provider) parent = node.parent node.finalize() parent.replaceChild(node, new_node) def onEnterNode(self, node): # Mighty complex code with lots of branches, but we aim to get rid of it. # pylint: disable=too-many-branches if node.isExpressionVariableNameRef(): provider = node.provider if provider.isExpressionClassBody(): if node.needsFallback(): variable = provider.getVariableForReference( variable_name=node.getVariableName() ) new_node = ExpressionLocalsVariableRefOrFallback( locals_scope=provider.getLocalsScope(), variable_name=node.getVariableName(), fallback=makeExpressionVariableRef( variable=variable, locals_scope=provider.getLocalsScope(), source_ref=node.source_ref, ), source_ref=node.source_ref, ) variable.addVariableUser(provider) else: new_node = ExpressionLocalsVariableRef( locals_scope=provider.getLocalsScope(), variable_name=node.getVariableName(), source_ref=node.source_ref, ) parent = node.parent node.finalize() parent.replaceChild(node, new_node) elif node.isExpressionTempVariableRef(): if node.getVariable().getOwner() != node.getParentVariableProvider(): node.getParentVariableProvider().addClosureVariable(node.getVariable()) elif node.isExpressionGeneratorObjectBody(): if python_version >= 0x300: self._handleNonLocal(node) # Only Python3.4 or later allows for generators to have qualname. if python_version >= 0x340: self._handleQualnameSetup(node) elif node.isExpressionCoroutineObjectBody(): self._handleNonLocal(node) self._handleQualnameSetup(node) elif node.isExpressionAsyncgenObjectBody(): self._handleNonLocal(node) self._handleQualnameSetup(node) elif node.isExpressionClassBody(): if python_version >= 0x300: self._handleNonLocal(node) # Python3.4 allows for class declarations to be made global, even # after they were declared, so we need to fix this up. if python_version >= 0x340: self._handleQualnameSetup(node) elif node.isExpressionFunctionBody(): if python_version >= 0x300: self._handleNonLocal(node) # Python 3.4 allows for class declarations to be made global, even # after they were declared, so we need to fix this up. if python_version >= 0x340: self._handleQualnameSetup(node) # Check if continue and break are properly in loops. If not, raise a # syntax error. elif node.isStatementLoopBreak() or node.isStatementLoopContinue(): current = node while True: current = current.getParent() if current.isStatementLoop(): break if current.isParentVariableProvider(): if node.isStatementLoopContinue(): message = "'continue' not properly in loop" else: message = "'break' outside loop" raiseSyntaxError(message, node.getSourceReference()) class VariableClosureLookupVisitorPhase2(VisitorNoopMixin): """Variable closure phase 2: Find assignments and references. In class context, a reference to a variable must be obeyed immediately, so that "variable = variable" takes first "variable" as a closure and then adds a new local "variable" to override it from there on. So, assignments for early closure, accesses will already have a variable set now, the others, only in this phase. """ @staticmethod def _attachVariable(node, provider): # print "Late reference", node.getVariableName(), "for", provider, "caused at", node, "of", node.getParent() variable_name = node.getVariableName() variable = provider.getVariableForReference(variable_name=variable_name) # Need to catch functions with "exec" and closure variables not allowed. if python_version < 0x300 and provider.isExpressionFunctionBodyBase(): was_taken = provider.hasTakenVariable(variable_name) if not was_taken and variable.getOwner() is not provider: parent_provider = provider.getParentVariableProvider() while parent_provider.isExpressionClassBody(): parent_provider = parent_provider.getParentVariableProvider() if ( parent_provider.isExpressionFunctionBody() and parent_provider.isUnqualifiedExec() ): raiseSyntaxError( getErrorMessageExecWithNestedFunction() % parent_provider.getName(), node.getSourceReference(), display_line=False, # Wrong line anyway ) return variable def onEnterNode(self, node): if node.isExpressionVariableNameRef(): provider = node.provider try: variable = self._attachVariable(node, provider) except MaybeLocalVariableUsage: variable_name = node.getVariableName() new_node = ExpressionLocalsVariableRefOrFallback( locals_scope=provider.getLocalsScope(), variable_name=variable_name, fallback=makeExpressionVariableRef( variable=node.getParentModule().getVariableForReference( variable_name ), locals_scope=provider.getLocalsScope(), source_ref=node.source_ref, ), source_ref=node.source_ref, ) else: new_node = makeExpressionVariableRef( variable=variable, locals_scope=provider.getLocalsScope(), source_ref=node.source_ref, ) variable.addVariableUser(provider) parent = node.parent node.finalize() parent.replaceChild(node, new_node) class VariableClosureLookupVisitorPhase3(VisitorNoopMixin): """Variable closure phase 3: Find errors and complete frame variables. In this phase, we can do some fix-ups and find errors. We might e.g. detect that a "del" was executed on a shared variable, which is not allowed for Python 2.x, so it must be caught. The parsing wouldn't do that. Also, frame objects for functions should learn their variable names. """ def onEnterNode(self, node): if python_version < 0x300 and node.isStatementDelVariable(): variable = node.getVariable() if not variable.isModuleVariable() and isSharedAmongScopes(variable): raiseSyntaxError( """\ can not delete variable '%s' referenced in nested scope""" % (variable.getName()), node.getSourceReference(), ) elif node.isStatementsFrame(): node.updateLocalNames() elif node.isExpressionFunctionBodyBase(): addFunctionVariableReleases(node) # Python3 is influenced by the mere use of a variable named as # "super". So we need to prepare ability to take closure. if node.hasFlag("has_super"): if not node.hasVariableName("__class__"): class_var = node.takeVariableForClosure("__class__") class_var.addVariableUser(node) node.getLocalsScope().registerClosureVariable(class_var) while node != class_var.getOwner(): node = node.getParentVariableProvider() node.getLocalsScope().registerClosureVariable(class_var) def completeVariableClosures(tree): visitors = ( VariableClosureLookupVisitorPhase1(), VariableClosureLookupVisitorPhase2(), VariableClosureLookupVisitorPhase3(), ) for visitor in visitors: visitTree(tree, visitor) # Only used to detect syntax errors. releaseSharedScopeInformation(tree) Nuitka-0.6.19.1/nuitka/tree/SyntaxErrors.py0000600000372100037210000000742314166627112025564 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Handling of syntax errors. Format SyntaxError/IndentationError exception for output, as well as raise it for the given source code reference. """ from nuitka.PythonVersions import python_version def formatOutput(e): if len(e.args) > 1: if python_version < 0x3A0: reason, (filename, lineno, colno, message) = e.args else: # TODO: For Python3.10 there is more information here, use it probably end information. reason, (filename, lineno, colno, message, _lineno2, _colno2) = e.args if message is None and colno is not None: colno = None if lineno is not None and lineno == 0: lineno = 1 else: (reason,) = e.args filename = None lineno = None colno = None message = None # On CPython3.4 at least, this attribute appears to override reason for # SyntaxErrors at least. if hasattr(e, "msg"): reason = e.msg if colno is not None and ( not e.__class__ is IndentationError or python_version < 0x390 ): colno = colno - len(message) + len(message.lstrip()) return """\ File "%s", line %d %s %s^ %s: %s""" % ( filename, lineno, message.strip(), " " * (colno - 1) if colno is not None else "", e.__class__.__name__, reason, ) elif message is not None: return """\ File "%s", line %d %s %s: %s""" % ( filename, lineno, message.strip(), e.__class__.__name__, reason, ) elif filename is not None: return """\ File "%s", line %s %s: %s""" % ( filename, lineno, e.__class__.__name__, reason, ) else: return """\ %s: %s""" % ( e.__class__.__name__, reason, ) def raiseSyntaxError(reason, source_ref, display_file=True, display_line=True): col_offset = source_ref.getColumnNumber() def readSource(): # Cyclic dependency. from .SourceReading import readSourceLine return readSourceLine(source_ref) # Special case being asked to display. if display_file and display_line: source_line = readSource() raise SyntaxError( reason, ( source_ref.getFilename(), source_ref.getLineNumber(), col_offset, source_line, ), ) # Special case given source reference. if source_ref is not None: if display_line: source_line = readSource() else: source_line = None exc = SyntaxError( reason, ( source_ref.getFilename(), source_ref.getLineNumber(), col_offset, source_line, ), ) exc = SyntaxError(reason, (None, None, None, None)) exc.generated_by_nuitka = True raise exc Nuitka-0.6.19.1/nuitka/tree/InternalModule.py0000600000372100037210000000501414166627112026015 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Internal module This is a container for helper functions that are shared across modules. It may not exist, and is treated specially in code generation. This avoids to own these functions to a random module. TODO: Clarify by renaming that the top module is now used, and these are merely helpers to do it. """ from nuitka.ModuleRegistry import getRootTopModule from nuitka.nodes.FunctionNodes import ( ExpressionFunctionPureBody, ExpressionFunctionPureInlineConstBody, ) from nuitka.SourceCodeReferences import fromFilename internal_source_ref = fromFilename("internal").atInternal() def once_decorator(func): """Cache result of a function call without arguments. Used for all internal function accesses to become a singleton. Note: This doesn't much specific anymore, but we are not having this often enough to warrant re-use or generalization. """ func.cached_value = None def replacement(): if func.cached_value is None: func.cached_value = func() return func.cached_value return replacement @once_decorator def getInternalModule(): """Get the singleton internal module.""" return getRootTopModule() def makeInternalHelperFunctionBody(name, parameters, inline_const_args=False): if inline_const_args: node_class = ExpressionFunctionPureInlineConstBody else: node_class = ExpressionFunctionPureBody result = node_class( provider=getInternalModule(), name=name, code_object=None, doc=None, parameters=parameters, flags=None, auto_release=None, source_ref=internal_source_ref, ) for variable in parameters.getAllVariables(): result.removeVariableReleases(variable) return result Nuitka-0.6.19.1/nuitka/tree/ComplexCallHelperFunctions.py0000600000372100037210000022441314166627112030335 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module is providing helper functions for complex call re-formulations. One for each type of call. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.AttributeNodes import ( ExpressionAttributeCheck, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinDictNodes import ExpressionBuiltinDict from nuitka.nodes.BuiltinIteratorNodes import ExpressionBuiltinIter1 from nuitka.nodes.BuiltinNextNodes import ExpressionBuiltinNext1 from nuitka.nodes.BuiltinRefNodes import ( ExpressionBuiltinAnonymousRef, makeExpressionBuiltinTypeRef, ) from nuitka.nodes.BuiltinTypeNodes import ExpressionBuiltinTuple from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.ComparisonNodes import ( ExpressionComparisonIn, ExpressionComparisonIsNot, ) from nuitka.nodes.ConditionalNodes import ( ExpressionConditionalOr, makeStatementConditional, ) from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTuple from nuitka.nodes.DictionaryNodes import StatementDictOperationSetKeyValue from nuitka.nodes.ExceptionNodes import ( ExpressionBuiltinMakeException, StatementRaiseException, ) from nuitka.nodes.FunctionAttributeNodes import ExpressionFunctionErrorStr from nuitka.nodes.FunctionNodes import ( ExpressionFunctionCall, ExpressionFunctionCreation, ExpressionFunctionRef, ) from nuitka.nodes.LoopNodes import StatementLoop, StatementLoopBreak from nuitka.nodes.OperatorNodes import makeBinaryOperationNode from nuitka.nodes.ReturnNodes import StatementReturn from nuitka.nodes.SubscriptNodes import ( ExpressionSubscriptLookup, StatementAssignmentSubscript, ) from nuitka.nodes.TypeNodes import ( ExpressionBuiltinIsinstance, ExpressionBuiltinType1, ) from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableRef, ) from nuitka.PythonVersions import ( getComplexCallSequenceErrorTemplate, python_version, ) from nuitka.specs.ParameterSpecs import ParameterSpec from .InternalModule import ( internal_source_ref, makeInternalHelperFunctionBody, once_decorator, ) from .ReformulationTryExceptStatements import makeTryExceptSingleHandlerNode from .ReformulationTryFinallyStatements import makeTryFinallyStatement from .TreeHelpers import ( makeCallNode, makeStatementsSequenceFromStatement, makeStatementsSequenceFromStatements, ) # TODO: Consider using ExpressionOutlineNodes for at least some of these # or their own helpers. def orderArgs(*args): if python_version >= 0x350: def weight(arg): result = args.index(arg) if arg == "kw": result += 1.5 elif arg == "star_arg_list": result -= 1.5 return result return tuple(sorted(args, key=weight)) return args def _makeNameAttributeLookup(node, attribute_name="__name__"): return makeExpressionAttributeLookup( expression=node, attribute_name=attribute_name, source_ref=internal_source_ref ) @once_decorator def getCallableNameDescBody(): helper_name = "get_callable_name_desc" # Equivalent of: # # Note: The "called_type" is a temporary variable. # # called_type = type(BuiltinFunctionType) # # if ininstance( called, (FunctionType, MethodType, BuiltinFunctionType) ): # return called.__name__ # elif python_version < 0x3 and isinstance(called, ClassType): # return called_type.__name__ + " constructor" # elif python_version < 0x3 and isinstance(called, InstanceType): # return called_type.__name__ + " instance" # else: # return called_type.__name__ + " object" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called",), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") if python_version < 0x390: function_name = makeBinaryOperationNode( operator="Add", left=_makeNameAttributeLookup( node=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), attribute_name="__name__", ), right=makeConstantRefNode( constant="()", source_ref=internal_source_ref, user_provided=True, ), source_ref=internal_source_ref, ) else: # TODO: Make it usable for pre-Python 3.9 too. function_name = ExpressionFunctionErrorStr( value=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ) functions_case = makeStatementsSequenceFromStatement( statement=( StatementReturn( expression=function_name, source_ref=internal_source_ref, ) ) ) if python_version >= 0x390: result.setChild("body", functions_case) return result no_branch = StatementReturn( expression=makeBinaryOperationNode( operator="Add", right=makeConstantRefNode( constant=" object", source_ref=internal_source_ref, user_provided=True ), left=_makeNameAttributeLookup( ExpressionBuiltinType1( value=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ) ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) if python_version < 0x300: instance_case = StatementReturn( expression=makeBinaryOperationNode( operator="Add", right=makeConstantRefNode( constant=" instance", source_ref=internal_source_ref, user_provided=True, ), left=_makeNameAttributeLookup( _makeNameAttributeLookup( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), attribute_name="__class__", ) ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) no_branch = makeStatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), classes=ExpressionBuiltinAnonymousRef( builtin_name="instance", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=instance_case, no_branch=no_branch, source_ref=internal_source_ref, ) class_case = StatementReturn( expression=makeBinaryOperationNode( operator="Add", right=makeConstantRefNode( constant=" constructor", source_ref=internal_source_ref, user_provided=True, ), left=_makeNameAttributeLookup( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ) ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) no_branch = makeStatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), classes=ExpressionBuiltinAnonymousRef( builtin_name="classobj", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=class_case, no_branch=no_branch, source_ref=internal_source_ref, ) if python_version < 0x300: normal_cases = ("function", "builtin_function_or_method", "instancemethod") else: normal_cases = ("function", "builtin_function_or_method") result.setChild( "body", makeStatementsSequenceFromStatement( statement=makeStatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), classes=makeExpressionMakeTuple( elements=tuple( ExpressionBuiltinAnonymousRef( builtin_name=builtin_name, source_ref=internal_source_ref, ) for builtin_name in normal_cases ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), yes_branch=functions_case, no_branch=no_branch, source_ref=internal_source_ref, ) ), ) return result def makeStarListArgumentErrorRaise(called_variable, star_list_variable): return StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=( makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant=getComplexCallSequenceErrorTemplate(), source_ref=internal_source_ref, user_provided=True, ), right=makeExpressionMakeTuple( elements=( ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getCallableNameDescBody(), source_ref=internal_source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=internal_source_ref, ), values=( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), _makeNameAttributeLookup( ExpressionBuiltinType1( value=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ), ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref, ) def _makeStarListArgumentToTupleStatement(called_variable, star_list_variable): if python_version >= 0x350: non_tuple_code = makeStatementConditional( condition=ExpressionConditionalOr( left=ExpressionAttributeCheck( expression=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref ), attribute_name="__iter__", source_ref=internal_source_ref, ), right=ExpressionAttributeCheck( expression=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref ), attribute_name="__getitem__", source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), yes_branch=StatementAssignmentVariable( variable=star_list_variable, source=ExpressionBuiltinTuple( value=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), no_branch=makeStarListArgumentErrorRaise( called_variable=called_variable, star_list_variable=star_list_variable ), source_ref=internal_source_ref, ) else: non_tuple_code = makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=star_list_variable, source=ExpressionBuiltinTuple( value=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="TypeError", handler_body=makeStarListArgumentErrorRaise( called_variable=called_variable, star_list_variable=star_list_variable ), source_ref=internal_source_ref, ) return makeStatementConditional( condition=ExpressionComparisonIsNot( left=ExpressionBuiltinType1( value=ExpressionVariableRef( variable=star_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), right=makeExpressionBuiltinTypeRef( builtin_name="tuple", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=non_tuple_code, no_branch=None, source_ref=internal_source_ref, ) def _makeRaiseExceptionMustBeMapping(called_variable, star_dict_variable): return StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=( makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant="""\ %s argument after ** must be a mapping, not %s""", source_ref=internal_source_ref, user_provided=True, ), right=makeExpressionMakeTuple( elements=( ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getCallableNameDescBody(), source_ref=internal_source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=internal_source_ref, ), values=( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), _makeNameAttributeLookup( ExpressionBuiltinType1( value=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ), ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref, ) def _makeIteratingLoopStatement(tmp_iter_variable, tmp_item_variable, statements): loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), *statements ) return StatementLoop(loop_body=loop_body, source_ref=internal_source_ref) def _makeStarDictArgumentToDictStatement(result, called_variable, star_dict_variable): temp_scope = result.allocateTempScope("mapping") tmp_dict_variable = result.allocateTempVariable(temp_scope, "dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_keys_variable = result.allocateTempVariable(temp_scope, "keys") tmp_key_variable = result.allocateTempVariable(temp_scope, "key") loop_body = [] if python_version >= 0x380: loop_body.append( makeStatementConditional( condition=ExpressionComparisonIn( left=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=tmp_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=_makeRaiseDuplicationItem( called_variable=called_variable, tmp_key_variable=tmp_key_variable ), no_branch=None, source_ref=internal_source_ref, ) ) loop_body.append( StatementAssignmentSubscript( subscribed=ExpressionTempVariableRef( variable=tmp_dict_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source=ExpressionSubscriptLookup( expression=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) mapping_case = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_keys_variable, source=makeCallNode( _makeNameAttributeLookup( ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), attribute_name="keys", ), internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="AttributeError", handler_body=_makeRaiseExceptionMustBeMapping( called_variable=called_variable, star_dict_variable=star_dict_variable ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionTempVariableRef( variable=tmp_keys_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_dict_variable, source=makeConstantRefNode( constant={}, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ), _makeIteratingLoopStatement( tmp_iter_variable=tmp_iter_variable, tmp_item_variable=tmp_key_variable, statements=loop_body, ), StatementAssignmentVariable( variable=star_dict_variable, source=ExpressionTempVariableRef( variable=tmp_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), ) tried = makeStatementConditional( condition=ExpressionComparisonIsNot( left=ExpressionBuiltinType1( value=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), right=makeExpressionBuiltinTypeRef( builtin_name="dict", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=mapping_case, no_branch=None, source_ref=internal_source_ref, ) final = ( StatementReleaseVariable( variable=tmp_dict_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_keys_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_key_variable, source_ref=internal_source_ref ), ) return makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref ) def _makeRaiseNoStringItem(called_variable): if python_version < 0x390: raise_arg = makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant="%s keywords must be strings", source_ref=internal_source_ref, user_provided=True, ), right=ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getCallableNameDescBody(), source_ref=internal_source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=internal_source_ref, ), values=( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) else: raise_arg = makeConstantRefNode( constant="keywords must be strings", source_ref=internal_source_ref, user_provided=True, ) return StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=(raise_arg,), source_ref=internal_source_ref, ), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref, ) def _makeRaiseDuplicationItem(called_variable, tmp_key_variable): return StatementRaiseException( exception_type=ExpressionBuiltinMakeException( exception_name="TypeError", args=( makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant="""\ %s got multiple values for keyword argument '%s'""", source_ref=internal_source_ref, user_provided=True, ), right=makeExpressionMakeTuple( elements=( ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getCallableNameDescBody(), source_ref=internal_source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=internal_source_ref, ), values=( ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ), source_ref=internal_source_ref, ), exception_value=None, exception_trace=None, exception_cause=None, source_ref=internal_source_ref, ) def _makeStarDictArgumentMergeToKwStatement( result, called_variable, kw_variable, star_dict_variable ): # This is plain terribly complex, pylint: disable=too-many-locals temp_scope = result.allocateTempScope("dict") tmp_dict_variable = result.allocateTempVariable(temp_scope, "dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_keys_variable = result.allocateTempVariable(temp_scope, "keys") tmp_key_variable = result.allocateTempVariable(temp_scope, "key_xxx") final = [ StatementReleaseVariable( variable=tmp_dict_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_keys_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_key_variable, source_ref=internal_source_ref ), ] mapping_loop_body = ( makeStatementConditional( condition=ExpressionComparisonIn( left=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=_makeRaiseDuplicationItem( called_variable=called_variable, tmp_key_variable=tmp_key_variable ), no_branch=None, source_ref=internal_source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source=ExpressionSubscriptLookup( expression=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) mapping_case = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_keys_variable, source=makeCallNode( _makeNameAttributeLookup( ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), attribute_name="keys", ), internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="AttributeError", handler_body=_makeRaiseExceptionMustBeMapping( called_variable=called_variable, star_dict_variable=star_dict_variable ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionTempVariableRef( variable=tmp_keys_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_dict_variable, source=makeConstantRefNode( constant={}, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ), _makeIteratingLoopStatement( tmp_iter_variable=tmp_iter_variable, tmp_item_variable=tmp_key_variable, statements=mapping_loop_body, ), ) temp_scope = result.allocateTempScope("dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "item") tmp_key_variable = result.allocateTempVariable(temp_scope, "key") final += ( StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_key_variable, source_ref=internal_source_ref ), ) dict_loop_body = ( StatementAssignmentVariable( variable=tmp_key_variable, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), subscript=makeConstantRefNode( constant=0, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionComparisonIn( left=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=_makeRaiseDuplicationItem( called_variable=called_variable, tmp_key_variable=tmp_key_variable ), no_branch=None, source_ref=internal_source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), subscript=makeConstantRefNode( constant=1, source_ref=internal_source_ref, user_provided=True ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) dict_case = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=kw_variable, source=ExpressionBuiltinDict( pos_arg=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), pairs=(), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=makeCallNode( _makeNameAttributeLookup( ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), attribute_name="iteritems" if python_version < 0x300 else "items", ), internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), _makeIteratingLoopStatement( tmp_iter_variable=tmp_iter_variable, tmp_item_variable=tmp_item_variable, statements=dict_loop_body, ), ) dict_case = makeStatementConditional( condition=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), yes_branch=dict_case, no_branch=None, source_ref=internal_source_ref, ) tried = makeStatementConditional( condition=ExpressionComparisonIsNot( left=ExpressionBuiltinType1( value=ExpressionVariableRef( variable=star_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), right=makeExpressionBuiltinTypeRef( builtin_name="dict", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=mapping_case, no_branch=dict_case, source_ref=internal_source_ref, ) return makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref ) @once_decorator def getFunctionCallHelperStarList(): helper_name = "complex_call_helper_star_list" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_list, tuple): # try: # star_arg_list = tuple(star_arg_list) # except TypeError: # raise TypeError, "%s argument after * must be a sequence, not %s" % ( # get_callable_name_desc(function), # type(star_arg_list).__name__ # ) # # return called(*star_arg_list) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "star_arg_list"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) body = makeStatementsSequenceFromStatements( _makeStarListArgumentToTupleStatement( called_variable=called_variable, star_list_variable=star_arg_list_variable ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperKeywordsStarList(): helper_name = "complex_call_helper_keywords_star_list" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_list, tuple): # try: # star_arg_list = tuple(star_arg_list) # except TypeError: # raise TypeError, "%s argument after * must be a sequence, not %s" % ( # get_callable_name_desc(function), # type(star_arg_list).__name__ # ) # # return called(*star_arg_list) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=orderArgs("called", "kw", "star_arg_list"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) body = makeStatementsSequenceFromStatements( _makeStarListArgumentToTupleStatement( called_variable=called_variable, star_list_variable=star_arg_list_variable ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosStarList(): helper_name = "complex_call_helper_pos_star_list" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_list, tuple): # try: # star_arg_list = tuple(star_arg_list) # except TypeError: # raise TypeError, "%s argument after * must be a sequence, not %s" % ( # get_callable_name_desc(function), # type(star_arg_list).__name__ # ) # # return called(*star_arg_list) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "args", "star_arg_list"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) body = makeStatementsSequenceFromStatements( _makeStarListArgumentToTupleStatement( called_variable=called_variable, star_list_variable=star_arg_list_variable ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=makeBinaryOperationNode( operator="Add", left=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosKeywordsStarList(): helper_name = "complex_call_helper_pos_keywords_star_list" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_list, tuple): # try: # star_arg_list = tuple(star_arg_list) # except TypeError: # raise TypeError, "%s argument after * must be a sequence, not %s" % ( # get_callable_name_desc(function), # type(star_arg_list).__name__ # ) # # return called(*star_arg_list) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=orderArgs("called", "args", "kw", "star_arg_list"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) body = makeStatementsSequenceFromStatements( _makeStarListArgumentToTupleStatement( called_variable=called_variable, star_list_variable=star_arg_list_variable ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=makeBinaryOperationNode( operator="Add", left=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperStarDict(): helper_name = "complex_call_helper_star_dict" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_dict, dict): # try: # tmp_keys = star_arg_dict.keys() # except AttributeError: # raise TypeError, ""%s argument after ** must be a mapping, not %s" % ( # get_callable_name_desc(function), # type(star_arg_dict).__name__ # ) # # tmp_iter = iter(keys) # tmp_dict = {} # # while 1: # try: # tmp_key = tmp_iter.next() # except StopIteration: # break # # tmp_dict[tmp_key] = star_dict_arg[tmp_key] # # star_arg_dict = new # # return called(**star_arg_dict) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) body = makeStatementsSequenceFromStatements( _makeStarDictArgumentToDictStatement( result=result, called_variable=called_variable, star_dict_variable=star_arg_dict_variable, ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=None, kw=ExpressionVariableRef( variable=star_arg_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosStarDict(): helper_name = "complex_call_helper_pos_star_dict" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. # # if not isinstance(star_arg_dict, dict): # try: # tmp_keys = star_arg_dict.keys() # except AttributeError: # raise TypeError, ""%s argument after ** must be a mapping, not %s" % ( # get_callable_name_desc(function), # type(star_arg_dict).__name__ # ) # # tmp_iter = iter(keys) # tmp_dict = {} # # while 1: # try: # tmp_key = tmp_iter.next() # except StopIteration: # break # # tmp_dict[tmp_key] = star_dict_arg[tmp_key] # # star_arg_dict = new # # return called(args, **star_arg_dict) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "args", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) body = makeStatementsSequenceFromStatements( _makeStarDictArgumentToDictStatement( result=result, called_variable=called_variable, star_dict_variable=star_arg_dict_variable, ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), kw=ExpressionVariableRef( variable=star_arg_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperKeywordsStarDict(): helper_name = "complex_call_helper_keywords_star_dict" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. One goal is to avoid copying "kw" unless really # necessary, and to take the slow route only for non-dictionaries. # # if not isinstance(star_arg_dict, dict): # try: # tmp_keys = star_arg_dict.keys() # except AttributeError: # raise TypeError, ""%s argument after ** must be a mapping, not %s" % ( # get_callable_name_desc(function), # type(star_arg_dict).__name__ # ) # # if keys: # kw = dict(kw) # # tmp_iter = iter(keys) # tmp_dict = {} # # while 1: # try: # tmp_key = tmp_iter.next() # except StopIteration: # break # # if tmp_key in kw: # raise TypeError, "%s got multiple values for keyword argument '%s'" % ( # get_callable_name_desc(function), # tmp_key # ) # # kw[tmp_key] = star_dict_arg[tmp_key) # # elif star_arg_dict: # tmp_iter = star_arg_dict.iteritems() # # kw = dict(kw) # while 1: # try: # tmp_key, tmp_value = tmp_iter.next() # except StopIteration: # break # # if tmp_key in kw: # raise TypeError, "%s got multiple values for keyword argument '%s'" % ( # get_callable_name_desc(function), # tmp_key # ) # # kw[tmp_key] = tmp_value # # return called(**kw) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "kw", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) body = makeStatementsSequenceFromStatements( _makeStarDictArgumentMergeToKwStatement( result=result, called_variable=called_variable, kw_variable=kw_variable, star_dict_variable=star_arg_dict_variable, ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=None, kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosKeywordsStarDict(): helper_name = "complex_call_helper_pos_keywords_star_dict" # Equivalent of: # # Note: Call in here is not the same, as it can go without checks directly # to PyObject_Call. One goal is to avoid copying "kw" unless really # necessary, and to take the slow route only for non-dictionaries. # # if not isinstance(star_arg_dict, dict): # try: # tmp_keys = star_arg_dict.keys() # except AttributeError: # raise TypeError, ""%s argument after ** must be a mapping, not %s" % ( # get_callable_name_desc(function), # type(star_arg_dict).__name__ # ) # # if keys: # kw = dict(kw) # # tmp_iter = iter(keys) # tmp_dict = {} # # while 1: # try: # tmp_key = tmp_iter.next() # except StopIteration: # break # # if tmp_key in kw: # raise TypeError, "%s got multiple values for keyword argument '%s'" % ( # get_callable_name_desc(function), # tmp_key # ) # # kw[tmp_key] = star_dict_arg[tmp_key] # # elif star_arg_dict: # tmp_iter = star_arg_dict.iteritems() # # kw = dict(kw) # while 1: # try: # tmp_key, tmp_value = tmp_iter.next() # except StopIteration: # break # # if tmp_key in kw: # raise TypeError, "%s got multiple values for keyword argument '%s'" % ( # get_callable_name_desc(function), # tmp_key # ) # # kw[tmp_key] = tmp_value # # return called(**kw ) # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "args", "kw", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) body = makeStatementsSequenceFromStatements( _makeStarDictArgumentMergeToKwStatement( result=result, called_variable=called_variable, kw_variable=kw_variable, star_dict_variable=star_arg_dict_variable, ), StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild("body", body) return result def getDoubleStarArgsConversion( result, called_variable, kw_variable, star_arg_list_variable, star_arg_dict_variable ): statements = [] if kw_variable is not None: statements.append( _makeStarDictArgumentMergeToKwStatement( result=result, called_variable=called_variable, kw_variable=kw_variable, star_dict_variable=star_arg_dict_variable, ) ) else: statements.append( _makeStarDictArgumentToDictStatement( result=result, called_variable=called_variable, star_dict_variable=star_arg_dict_variable, ) ) statements.append( _makeStarListArgumentToTupleStatement( called_variable=called_variable, star_list_variable=star_arg_list_variable ) ) return statements @once_decorator def getFunctionCallHelperStarListStarDict(): helper_name = "complex_call_helper_star_list_star_dict" # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "star_arg_list", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) statements = getDoubleStarArgsConversion( result=result, called_variable=called_variable, star_arg_list_variable=star_arg_list_variable, kw_variable=None, star_arg_dict_variable=star_arg_dict_variable, ) statements.append( StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), kw=ExpressionVariableRef( variable=star_arg_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) body = makeStatementsSequenceFromStatements(*statements) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosStarListStarDict(): helper_name = "complex_call_helper_pos_star_list_star_dict" # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called", "args", "star_arg_list", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) statements = getDoubleStarArgsConversion( result=result, called_variable=called_variable, star_arg_list_variable=star_arg_list_variable, kw_variable=None, star_arg_dict_variable=star_arg_dict_variable, ) if python_version >= 0x360: statements.reverse() statements.append( StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=makeBinaryOperationNode( operator="Add", left=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), kw=ExpressionVariableRef( variable=star_arg_dict_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) body = makeStatementsSequenceFromStatements(*statements) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperKeywordsStarListStarDict(): helper_name = "complex_call_helper_keywords_star_list_star_dict" # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=orderArgs("called", "kw", "star_arg_list", "star_arg_dict"), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) statements = getDoubleStarArgsConversion( result=result, called_variable=called_variable, star_arg_list_variable=star_arg_list_variable, kw_variable=kw_variable, star_arg_dict_variable=star_arg_dict_variable, ) statements.append( StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) body = makeStatementsSequenceFromStatements(*statements) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperPosKeywordsStarListStarDict(): helper_name = "complex_call_helper_pos_keywords_star_list_star_dict" # Only need to check if the star argument value is a sequence and then # convert to tuple. result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=orderArgs( "called", "args", "kw", "star_arg_list", "star_arg_dict" ), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) called_variable = result.getVariableForAssignment(variable_name="called") args_variable = result.getVariableForAssignment(variable_name="args") kw_variable = result.getVariableForAssignment(variable_name="kw") star_arg_list_variable = result.getVariableForAssignment( variable_name="star_arg_list" ) star_arg_dict_variable = result.getVariableForAssignment( variable_name="star_arg_dict" ) statements = getDoubleStarArgsConversion( result=result, called_variable=called_variable, star_arg_list_variable=star_arg_list_variable, kw_variable=kw_variable, star_arg_dict_variable=star_arg_dict_variable, ) if python_version >= 0x360: statements.reverse() statements.append( StatementReturn( expression=makeExpressionCall( called=ExpressionVariableRef( variable=called_variable, source_ref=internal_source_ref ), args=makeBinaryOperationNode( operator="Add", left=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), right=ExpressionVariableRef( variable=star_arg_list_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), kw=ExpressionVariableRef( variable=kw_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) ) body = makeStatementsSequenceFromStatements(*statements) result.setChild("body", body) return result @once_decorator def getFunctionCallHelperDictionaryUnpacking(): helper_name = "complex_call_helper_dict_unpacking_checks" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("called",), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ps_pos_only_args=(), ), ) args_variable = result.getVariableForAssignment(variable_name="args") called_variable = result.getVariableForAssignment(variable_name="called") temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "dict") tmp_iter_variable = result.allocateTempVariable(temp_scope, "dicts_iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "args_item") tmp_iter2_variable = result.allocateTempVariable(temp_scope, "dict_iter") tmp_key_variable = result.allocateTempVariable(temp_scope, "dict_key") update_body = ( makeStatementConditional( condition=ExpressionComparisonIsNot( left=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), right=makeExpressionBuiltinTypeRef( builtin_name="str", source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=_makeRaiseNoStringItem(called_variable=called_variable), no_branch=None, source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionComparisonIn( left=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), right=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=_makeRaiseDuplicationItem( called_variable=called_variable, tmp_key_variable=tmp_key_variable ), no_branch=None, source_ref=internal_source_ref, ), StatementDictOperationSetKeyValue( dict_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), key=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), value=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), subscript=ExpressionTempVariableRef( variable=tmp_key_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) loop_body = ( makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter2_variable, source=ExpressionBuiltinIter1( value=makeCallNode( _makeNameAttributeLookup( ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref, ), attribute_name="keys", ), internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), _makeIteratingLoopStatement( tmp_iter_variable=tmp_iter2_variable, tmp_item_variable=tmp_key_variable, statements=update_body, ), ), exception_name="AttributeError", handler_body=_makeRaiseExceptionMustBeMapping( called_variable=called_variable, star_dict_variable=tmp_item_variable ), source_ref=internal_source_ref, ), ) final = ( StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter2_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_key_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant={}, source_ref=internal_source_ref), source_ref=internal_source_ref, ), _makeIteratingLoopStatement( tmp_iter_variable=tmp_iter_variable, tmp_item_variable=tmp_item_variable, statements=loop_body, ), StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), ) body = makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ) result.setChild("body", body) return result Nuitka-0.6.19.1/nuitka/Reports.py0000600000372100037210000000323014166627112023570 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Collection of information for Report and their writing. """ from nuitka import TreeXML from nuitka.ModuleRegistry import getDoneModules, getModuleInclusionInfos from nuitka.Tracing import general from nuitka.utils.FileOperations import putTextFileContents def writeCompilationReport(report_filename): active_modules_info = getModuleInclusionInfos() root = TreeXML.Element("nuitka-compilation-report") for module in getDoneModules(): active_module_info = active_modules_info[module] root.append( TreeXML.Element( "module", name=module.getFullName(), kind=module.__class__.__name__, reason=active_module_info.reason, ) ) putTextFileContents(filename=report_filename, contents=TreeXML.toString(root)) general.info("Compilation report in file %r." % report_filename) Nuitka-0.6.19.1/nuitka/pgo/0000700000372100037210000000000014167275622022353 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/pgo/PGO.py0000600000372100037210000001106114166627112023345 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Python level PGO handling in Nuitka.""" import os import struct from nuitka.__past__ import xrange from nuitka.Options import getPythonPgoUnseenModulePolicy from nuitka.Tracing import pgo_logger _pgo_active = False _pgo_strings = None _module_entries = {} _module_exits = {} def _readCString(input_file): return b"".join(iter(lambda: input_file.read(1), b"\0")) def _readCIntValue(input_file): return struct.unpack("i", input_file.read(4))[0] def _readStringValue(input_file): return _pgo_strings[_readCIntValue(input_file)] def readPGOInputFile(input_filename): """Read PGO information produced by a PGO run.""" # Using global here, as this is really a singleton, in the form of a module, # pylint: disable=global-statement global _pgo_strings, _pgo_active with open(input_filename, "rb") as input_file: header = input_file.read(7) if header != "KAY.PGO": pgo_logger.sysexit( "Error, file '%s' is not a valid PGO input for this version of Nuitka." % input_filename ) input_file.seek(-7, os.SEEK_END) header = input_file.read(7) if header != "YAK.PGO": pgo_logger.sysexit( "Error, file '%s' was not completed correctly." % input_filename ) input_file.seek(-8 - 7, os.SEEK_END) count, offset = struct.unpack("ii", input_file.read(8)) input_file.seek(offset, os.SEEK_SET) _pgo_strings = [None] * count for i in xrange(count): _pgo_strings[i] = _readCString(input_file) input_file.seek(7, os.SEEK_SET) while True: # Which probe is it. probe_name = _readStringValue(input_file) if probe_name == "ModuleEnter": module_name = _readStringValue(input_file) arg = _readCIntValue(input_file) _module_entries[module_name] = arg elif probe_name == "ModuleExit": module_name = _readStringValue(input_file) had_error = _readCIntValue(input_file) != 0 _module_exits[module_name] = had_error elif probe_name == "END": break else: pgo_logger.sysexit( "Error, unknown problem '%s' encountered." % probe_name ) _pgo_active = True def decideInclusionFromPGO(module_name, module_kind): """Decide module inclusion based on PGO input. At this point, PGO can decide the inclusion to not be done. It will ask to include things it has seen at run time, and that won't be a problem, but it will ask to exclude modules not seen entered at runtime, the decision for bytecode is same as inclusion, but the demotion is done later, after first compiling it. Caching might save compile time a second time around once the cache is populated, but care must be taken for that to not cause inclusions that are not used. """ # Only if we had input of course. if not _pgo_active: return None # At this time, we do not yet detect the loading of extension modules, # but of course we could and should do that. if module_kind == "shlib": return None if module_name in _module_entries: return True unseen_module_policy = getPythonPgoUnseenModulePolicy() if unseen_module_policy == "exclude": return False else: return None def decideCompilationFromPGO(module_name): # Only if we had input of course. if not _pgo_active: return None # TODO: Could become more complicated. unseen_module_policy = getPythonPgoUnseenModulePolicy() if module_name not in _module_entries and unseen_module_policy == "bytecode": return "bytecode" else: return None Nuitka-0.6.19.1/nuitka/pgo/__init__.py0000600000372100037210000000150114166627112024455 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/OptionParsing.py0000600000372100037210000012474514166627112024745 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Command line options of Nuitka. These provide only the optparse options to use, and the mechanic to actually do it, but updating and checking module "nuitka.Options" values is not in the scope, to make sure it can be used without. Note: This is using "optparse", because "argparse" is only Python 2.7 and higher, and we still support Python 2.6 due to the RHELs still being used, and despite the long deprecation, it's in every later release. """ import os import re import sys from optparse import SUPPRESS_HELP, OptionGroup, OptionParser from nuitka.PythonFlavors import ( isAnacondaPython, isApplePython, isDebianPackagePython, isMSYS2MingwPython, isNuitkaPython, isPyenvPython, isWinPython, ) from nuitka.utils.FileOperations import getFileContentByLine from nuitka.utils.Utils import ( getArchitecture, getLinuxDistribution, getOS, getWindowsRelease, isLinux, isPosixWindows, ) from nuitka.Version import getCommercialVersion, getNuitkaVersion # Indicator if we were called as "nuitka-run" in which case we assume some # other defaults and work a bit different with parameters. is_nuitka_run = os.path.basename(sys.argv[0]).lower().endswith("-run") if not is_nuitka_run: usage = "usage: %prog [--module] [--run] [options] main_module.py" else: usage = "usage: %prog [options] main_module.py" def _getPythonFlavor(): # return driven, pylint: disable=too-many-return-statements if isNuitkaPython(): return "Nuitka Python" elif isAnacondaPython(): return "Anaconda Python" elif isWinPython(): return "WinPython" elif isDebianPackagePython(): return "Debian Python" elif isApplePython(): return "Apple Python" elif isPyenvPython(): return "pyenv" elif isPosixWindows(): return "MSYS2 Posix" elif isMSYS2MingwPython(): return "MSYS2 MinGW" else: return "Unknown" def _getVersionInformationValues(): # TODO: Might be nice if we could delay version information computation # until it's actually used. yield getNuitkaVersion() yield "Commercial: %s" % getCommercialVersion() yield "Python: %s" % sys.version.split("\n", 1)[0] yield "Flavor: %s" % _getPythonFlavor() yield "Executable: %s" % sys.executable yield "OS: %s" % getOS() yield "Arch: %s" % getArchitecture() if isLinux(): yield "Distribution: %s %s" % getLinuxDistribution() if getOS() == "Windows": yield "WindowsRelease: %s" % getWindowsRelease() parser = OptionParser( usage=usage, version="\n".join(_getVersionInformationValues()), ) parser.add_option( "--module", action="store_false", dest="executable", default=True, help="""\ Create an extension module executable instead of a program. Defaults to off.""", ) parser.add_option( "--standalone", action="store_true", dest="is_standalone", default=False, help="""\ Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "--follow-imports". You may also want to use "--python-flag=no_site" to avoid the "site.py" module, which can save a lot of code dependencies. Defaults to off.""", ) parser.add_option( "--no-standalone", action="store_false", dest="is_standalone", default=False, help=SUPPRESS_HELP, ) parser.add_option( "--onefile", action="store_true", dest="is_onefile", default=False, help="""\ On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to off.""", ) parser.add_option( "--no-onefile", action="store_false", dest="is_onefile", default=False, help=SUPPRESS_HELP, ) if os.name == "nt": parser.add_option( "--python-arch", action="store", dest="python_arch", choices=("x86", "x86_64"), default=None, help="""\ Architecture of Python to use. One of "x86" or "x86_64". Defaults to what you run Nuitka with (currently "%s").""" % (getArchitecture()), ) parser.add_option( "--python-debug", action="store_true", dest="python_debug", default=None, help="""\ Use debug version or not. Default uses what you are using to run Nuitka, most likely a non-debug version.""", ) parser.add_option( "--python-flag", action="append", dest="python_flags", metavar="FLAG", default=[], help="""\ Python flags to use. Default is what you are using to run Nuitka, this enforces a specific mode. These are options that also exist to standard Python executable. Currently supported: "-S" (alias "no_site"), "static_hashes" (do not use hash randomization), "no_warnings" (do not give Python runtime warnings), "-O" (alias "no_asserts"), "no_docstrings" (do not use docstrings), and "-m". Default empty.""", ) parser.add_option( "--python-for-scons", action="store", dest="python_scons", metavar="PATH", default=None, help="""\ If using Python3.3 or Python3.4, provide the path of a Python binary to use for Scons. Otherwise Nuitka can use what you run Nuitka with or a "scons" binary that is found in PATH, or a Python installation from Windows registry.""", ) parser.add_option( "--warn-implicit-exceptions", action="store_true", dest="warn_implicit_exceptions", default=False, help="""\ Enable warnings for implicit exceptions detected at compile time.""", ) parser.add_option( "--warn-unusual-code", action="store_true", dest="warn_unusual_code", default=False, help="""\ Enable warnings for unusual code detected at compile time.""", ) parser.add_option( "--assume-yes-for-downloads", action="store_true", dest="assume_yes_for_downloads", default=False, help="""\ Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "" is used. For compatibility reasons, the "__file__" value will always have ".py" suffix independent of what it really is.""", ) parser.add_option_group(codegen_group) output_group = OptionGroup(parser, "Output choices") output_group.add_option( "-o", action="store", dest="output_filename", metavar="FILENAME", default=None, help="""\ Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '%s' on this platform. """ % "" + (".exe" if getOS() == "Windows" else ".bin"), ) output_group.add_option( "--output-dir", action="store", dest="output_dir", metavar="DIRECTORY", default="", help="""\ Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. """, ) output_group.add_option( "--remove-output", action="store_true", dest="remove_build", default=False, help="""\ Removes the build directory after producing the module or exe file. Defaults to off.""", ) output_group.add_option( "--no-pyi-file", action="store_false", dest="pyi_file", default=True, help="""\ Do not create a ".pyi" file for extension modules created by Nuitka. This is used to detect implicit imports. Defaults to off.""", ) parser.add_option_group(output_group) debug_group = OptionGroup(parser, "Debug features") debug_group.add_option( "--debug", action="store_true", dest="debug", default=False, help="""\ Executing all self checks possible to find errors in Nuitka, do not use for production. Defaults to off.""", ) debug_group.add_option( "--unstripped", action="store_true", dest="unstripped", default=False, help="""\ Keep debug info in the resulting object file for better debugger interaction. Defaults to off.""", ) debug_group.add_option( "--profile", action="store_true", dest="profile", default=False, help="""\ Enable vmprof based profiling of time spent. Not working currently. Defaults to off.""", ) debug_group.add_option( "--internal-graph", action="store_true", dest="graph", default=False, help="""\ Create graph of optimization process internals, do not use for whole programs, but only for small test cases. Defaults to off.""", ) debug_group.add_option( "--trace-execution", action="store_true", dest="trace_execution", default=False, help="""\ Traced execution output, output the line of code before executing it. Defaults to off.""", ) debug_group.add_option( "--recompile-c-only", action="store_true", dest="recompile_c_only", default=False, help="""\ This is not incremental compilation, but for Nuitka development only. Takes existing files and simply compile them as C again. Allows compiling edited C files for quick debugging changes to the generated source, e.g. to see if code is passed by, values output, etc, Defaults to off. Depends on compiling Python source to determine which files it should look at.""", ) debug_group.add_option( "--generate-c-only", action="store_true", dest="generate_c_only", default=False, help="""\ Generate only C source code, and do not compile it to binary or module. This is for debugging and code coverage analysis that doesn't waste CPU. Defaults to off. Do not think you can use this directly.""", ) debug_group.add_option( "--experimental", action="append", dest="experimental", metavar="FLAG", default=[], help="""\ Use features declared as 'experimental'. May have no effect if no experimental features are present in the code. Uses secret tags (check source) per experimented feature.""", ) debug_group.add_option( "--explain-imports", action="store_true", dest="explain_imports", default=False, help=SUPPRESS_HELP, ) debug_group.add_option( "--low-memory", action="store_true", dest="low_memory", default=False, help="""\ Attempt to use less memory, by forking less C compilation jobs and using options that use less memory. For use on embedded machines. Use this in case of out of memory problems. Defaults to off.""", ) if os.name == "nt": debug_group.add_option( "--disable-dll-dependency-cache", action="store_true", dest="no_dependency_cache", default=False, help="""\ Disable the dependency walker cache. Will result in much longer times to create the distribution folder, but might be used in case the cache is suspect to cause errors. """, ) debug_group.add_option( "--force-dll-dependency-cache-update", action="store_true", dest="update_dependency_cache", default=False, help="""\ For an update of the dependency walker cache. Will result in much longer times to create the distribution folder, but might be used in case the cache is suspect to cause errors or known to need an update. """, ) # This is for testing framework, "coverage.py" hates to loose the process. And # we can use it to make sure it's not done unknowingly. parser.add_option( "--must-not-re-execute", action="store_false", dest="allow_reexecute", default=True, help=SUPPRESS_HELP, ) parser.add_option_group(debug_group) c_compiler_group = OptionGroup(parser, "Backend C compiler choice") c_compiler_group.add_option( "--clang", action="store_true", dest="clang", default=False, help="""\ Enforce the use of clang. On Windows this requires a working Visual Studio version to piggy back on. Defaults to off.""", ) c_compiler_group.add_option( "--mingw64", action="store_true", dest="mingw64", default=False, help="""\ Enforce the use of MinGW64 on Windows. Defaults to off.""", ) c_compiler_group.add_option( "--msvc", action="store", dest="msvc_version", default=None, help="""\ Enforce the use of specific MSVC version on Windows. Allowed values are e.g. "14.2" (MSVC 2019), specify an illegal value for a list of installed compilers, or use "latest". Notice that only latest MSVC is really supported, and you can use "latest" to enforce that. Defaults to MSVC on Windows being used if installed, otherwise MinGW64.""", ) c_compiler_group.add_option( "-j", "--jobs", action="store", dest="jobs", metavar="N", default=None, help="""\ Specify the allowed number of parallel C compiler jobs. Defaults to the system CPU count.""", ) c_compiler_group.add_option( "--lto", action="store", dest="lto", metavar="choice", default="auto", choices=("yes", "no", "auto"), help="""\ Use link time optimizations (MSVC, gcc, clang). Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto".""", ) c_compiler_group.add_option( "--static-libpython", action="store", dest="static_libpython", metavar="choice", default="auto", choices=("yes", "no", "auto"), help="""\ Use static link library of Python. Allowed values are "yes", "no", and "auto" (when it's known to work). Defaults to "auto".""", ) c_compiler_group.add_option( "--disable-ccache", action="store_true", dest="disable_ccache", default=False, help="""\ Do not attempt to use ccache (gcc, clang, etc.) or clcache (MSVC, clangcl).""", ) parser.add_option_group(c_compiler_group) pgo_group = OptionGroup(parser, "PGO compilation choices") pgo_group.add_option( "--pgo", action="store_true", dest="is_c_pgo", default=False, help="""\ Enables C level profile guided optimization (PGO), by executing a dedicated build first for a profiling run, and then using the result to feedback into the C compilation. Note: This is experimental and not working with standalone modes of Nuitka yet. Defaults to off.""", ) pgo_group.add_option( "--pgo-python", action="store_true", dest="is_python_pgo", default=False, help=SUPPRESS_HELP, ) pgo_group.add_option( "--pgo-python-input", action="store", dest="python_pgo_input", default=None, help=SUPPRESS_HELP, ) pgo_group.add_option( "--pgo-python-policy-unused-module", action="store", dest="python_pgo_policy_unused_module", choices=("include", "exclude", "bytecode"), default="include", help=SUPPRESS_HELP, ) pgo_group.add_option( "--pgo-args", action="store", dest="pgo_args", default="", help="""\ Arguments to be passed in case of profile guided optimization. These are passed to the special built executable during the PGO profiling run. Default empty.""", ) pgo_group.add_option( "--pgo-executable", action="store", dest="pgo_executable", default=None, help="""\ Command to execute when collecting profile information. Use this only, if you need to launch it through a script that prepares it to run. Default use created program.""", ) parser.add_option_group(pgo_group) tracing_group = OptionGroup(parser, "Tracing features") tracing_group.add_option( "--quiet", action="store_true", dest="quiet", default=False, help="""\ Disable all information outputs, but show warnings. Defaults to off.""", ) tracing_group.add_option( "--show-scons", action="store_true", dest="show_scons", default=False, help="""\ Operate Scons in non-quiet mode, showing the executed commands. Defaults to off.""", ) tracing_group.add_option( "--show-progress", action="store_true", dest="show_progress", default=False, help="""Provide progress information and statistics. Defaults to off.""", ) tracing_group.add_option( "--no-progressbar", action="store_false", dest="progress_bar", default=True, help="""Disable progress bar outputs (if tqdm is installed). Defaults to off.""", ) tracing_group.add_option( "--show-memory", action="store_true", dest="show_memory", default=False, help="""Provide memory information and statistics. Defaults to off.""", ) tracing_group.add_option( "--show-modules", action="store_true", dest="show_inclusion", default=False, help="""\ Provide information for included modules and DLLs Defaults to off.""", ) tracing_group.add_option( "--show-modules-output", action="store", dest="show_inclusion_output", metavar="PATH", default=None, help="""\ Where to output --show-modules, should be a filename. Default is standard output.""", ) tracing_group.add_option( "--report", action="store", dest="compilation_report_filename", default=None, help="""\ Report module inclusion in an XML output file. Default is off.""", ) tracing_group.add_option( "--verbose", action="store_true", dest="verbose", default=False, help="""\ Output details of actions taken, esp. in optimizations. Can become a lot. Defaults to off.""", ) tracing_group.add_option( "--verbose-output", action="store", dest="verbose_output", metavar="PATH", default=None, help="""\ Where to output --verbose, should be a filename. Default is standard output.""", ) parser.add_option_group(tracing_group) windows_group = OptionGroup(parser, "Windows specific controls") windows_group.add_option( "--windows-dependency-tool", action="store", dest="dependency_tool", default=None, help=SUPPRESS_HELP, ) windows_group.add_option( "--windows-disable-console", action="store_true", dest="disable_console", default=False, help="""\ When compiling for Windows, disable the console window. Defaults to off.""", ) windows_group.add_option( "--windows-icon-from-ico", action="append", dest="icon_path", metavar="ICON_PATH", default=[], help="""\ Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with # where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored.""", ) windows_group.add_option( "--windows-icon-from-exe", action="store", dest="icon_exe_path", metavar="ICON_EXE_PATH", default=None, help="Copy executable icons from this existing executable (Windows only).", ) windows_group.add_option( "--onefile-windows-splash-screen-image", action="store", dest="splash_screen_image", default=None, help="""\ When compiling for Windows and onefile, show this while loading the application. Defaults to off.""", ) windows_group.add_option( "--windows-uac-admin", action="store_true", dest="windows_uac_admin", metavar="WINDOWS_UAC_ADMIN", default=False, help="Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off.", ) windows_group.add_option( "--windows-uac-uiaccess", action="store_true", dest="windows_uac_uiaccess", metavar="WINDOWS_UAC_UIACCESS", default=False, help="""\ Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off.""", ) windows_group.add_option( "--windows-company-name", action="store", dest="windows_company_name", metavar="WINDOWS_COMPANY_NAME", default=None, help="""\ Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused.""", ) windows_group.add_option( "--windows-product-name", action="store", dest="windows_product_name", metavar="WINDOWS_PRODUCT_NAME", default=None, help="""\ Name of the product to use in Windows Version information. Defaults to base filename of the binary.""", ) windows_group.add_option( "--windows-file-version", action="store", dest="windows_file_version", metavar="WINDOWS_FILE_VERSION", default=None, help="""\ File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused.""", ) windows_group.add_option( "--windows-product-version", action="store", dest="windows_product_version", metavar="WINDOWS_PRODUCT_VERSION", default=None, help="""\ Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused.""", ) windows_group.add_option( "--windows-file-description", action="store", dest="windows_file_description", metavar="WINDOWS_FILE_DESCRIPTION", default=None, help="""\ Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense.""", ) windows_group.add_option( "--windows-onefile-tempdir", "--onefile-tempdir", action="store_true", dest="is_onefile_tempdir", metavar="ONEFILE_TEMPDIR", default=False, help=SUPPRESS_HELP, ) windows_group.add_option( "--windows-onefile-tempdir-spec", action="store", dest="onefile_tempdir_spec", metavar="ONEFILE_TEMPDIR_SPEC", default=None, help="""\ Use this as a temporary folder. Defaults to '%TEMP%\\onefile_%PID%_%TIME%', i.e. system temporary directory.""", ) windows_group.add_option( "--windows-force-stdout-spec", action="store", dest="force_stdout_spec", metavar="WINDOWS_FORCE_STDOUT_SPEC", default=None, help="""\ Force standard output of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. '%PROGRAM%.out.txt', i.e. file near your program.""", ) windows_group.add_option( "--windows-force-stderr-spec", action="store", dest="force_stderr_spec", metavar="WINDOWS_FORCE_STDERR_SPEC", default=None, help="""\ Force standard error of the program to go to this location. Useful for programs with disabled console and programs using the Windows Services Plugin of Nuitka. Defaults to not active, use e.g. '%PROGRAM%.err.txt', i.e. file near your program.""", ) parser.add_option_group(windows_group) macos_group = OptionGroup(parser, "macOS specific controls") macos_group.add_option( "--macos-onefile-icon", action="append", dest="icon_path", metavar="ICON_PATH", default=[], help="Add executable icon for binary to use. Can be given only one time. Defaults to Python icon if available.", ) macos_group.add_option( "--macos-disable-console", action="store_true", dest="disable_console", default=False, help="""\ When compiling for macOS, disable the console window and create a GUI application. Defaults to off.""", ) macos_group.add_option( "--macos-create-app-bundle", action="store_true", dest="macos_create_bundle", default=False, help="""\ When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console.Defaults to off.""", ) macos_group.add_option( "--macos-signed-app-name", action="store", dest="macos_signed_app_name", metavar="MACOS_SIGNED_APP_NAME", default=None, help="""\ Name of the application to use for macOS signing. Follow com.yourcompany.appname naming results for best results, as these have to be globally unique, and will grant protected API accesses.""", ) macos_group.add_option( "--macos-app-name", action="store", dest="macos_app_name", metavar="MACOS_APP_NAME", default=None, help="""\ Name of the product to use in macOS bundle information. Defaults to base filename of the binary.""", ) macos_group.add_option( "--macos-app-version", action="store", dest="macos_app_version", metavar="MACOS_APP_VERSION", default=None, help="""\ Product version to use in macOS bundle information. Defaults to 1.0 if not given.""", ) parser.add_option_group(macos_group) linux_group = OptionGroup(parser, "Linux specific controls") linux_group.add_option( "--linux-onefile-icon", action="append", dest="icon_path", metavar="ICON_PATH", default=[], help="Add executable icon for onefile binary to use. Can be given only one time. Defaults to Python icon if available.", ) parser.add_option_group(linux_group) plugin_group = OptionGroup(parser, "Plugin control") plugin_group.add_option( "--enable-plugin", "--plugin-enable", action="append", dest="plugins_enabled", metavar="PLUGIN_NAME", default=[], help="""\ Enabled plugins. Must be plug-in names. Use --plugin-list to query the full list and exit. Default empty.""", ) plugin_group.add_option( "--disable-plugin", "--plugin-disable", action="append", dest="plugins_disabled", metavar="PLUGIN_NAME", default=[], help="""\ Disabled plugins. Must be plug-in names. Use --plugin-list to query the full list and exit. Default empty.""", ) plugin_group.add_option( "--plugin-no-detection", action="store_false", dest="detect_missing_plugins", default=True, help="""\ Plugins can detect if they might be used, and the you can disable the warning via "--disable-plugin=plugin-that-warned", or you can use this option to disable the mechanism entirely, which also speeds up compilation slightly of course as this detection code is run in vain once you are certain of which plugins to use. Defaults to off.""", ) plugin_group.add_option( "--plugin-list", action="store_true", dest="list_plugins", default=False, help="""\ Show list of all available plugins and exit. Defaults to off.""", ) parser.add_option_group(plugin_group) plugin_group.add_option( "--user-plugin", action="append", dest="user_plugins", metavar="PATH", default=[], help="The file name of user plugin. Can be given multiple times. Default empty.", ) plugin_group.add_option( "--persist-source-changes", action="store_true", dest="persist_source_changes", default=False, help="""\ Write source changes to original Python files. Use with care. May need permissions, best for use in a virtualenv to debug if plugin code changes work with standard Python or to benefit from bloat removal even with pure Python. Default False.""", ) def _considerPluginOptions(logger): # Cyclic dependency on plugins during parsing of command line. from nuitka.plugins.Plugins import ( addPluginCommandLineOptions, addUserPluginCommandLineOptions, ) for arg in sys.argv[1:]: if arg.startswith(("--enable-plugin=", "--plugin-enable=")): plugin_names = arg[16:] if "=" in plugin_names: logger.sysexit( "Error, plugin options format changed. Use '--enable-plugin=%s --help' to know new options." % plugin_names.split("=", 1)[0] ) addPluginCommandLineOptions( parser=parser, plugin_names=plugin_names.split(","), data_files_tags=data_files_tags, ) if arg.startswith("--user-plugin="): plugin_name = arg[14:] if "=" in plugin_name: logger.sysexit( "Error, plugin options format changed. Use '--user-plugin=%s --help' to know new options." % plugin_name.split("=", 1)[0] ) addUserPluginCommandLineOptions( parser=parser, filename=plugin_name, data_files_tags=data_files_tags ) def _expandProjectArg(arg, filename_arg, for_eval): def wrap(value): if for_eval: return repr(value) else: return value values = { "OS": wrap(getOS()), "Arch": wrap(getArchitecture()), "Flavor": wrap(_getPythonFlavor()), "Version": getNuitkaVersion(), "Commercial": wrap(getCommercialVersion()), "MAIN_DIRECTORY": wrap(os.path.dirname(filename_arg) or "."), } if isLinux(): dist_info = getLinuxDistribution() else: dist_info = "N/A", "0" values["Linux_Distribution_Name"] = dist_info[0] values["Linux_Distribution_Version"] = dist_info[1] if getOS() == "Windows": values["WindowsRelease"] = getWindowsRelease() arg = arg.format(**values) return arg def _getProjectOptions(logger, filename_arg, module_mode): # Complex stuff, pylint: disable=too-many-branches,too-many-locals if os.path.isdir(filename_arg): if module_mode: filename_arg = os.path.join(filename_arg, "__init__.py") else: filename_arg = os.path.join(filename_arg, "__main__.py") # The file specified may not exist, let the later parts of Nuitka handle this. try: contents_by_line = getFileContentByLine(filename_arg, "rb") except (OSError, IOError): return def sysexit(count, message): logger.sysexit("%s:%d %s" % (filename_arg, count + 1, message)) execute_block = True expect_block = False cond_level = -1 for count, line in enumerate(contents_by_line): match = re.match(b"^\\s*#(\\s+)nuitka-project(.*?):(.*)", line) if match: level, command, arg = match.groups() level = len(level) arg = arg.rstrip() # Check for empty conditional blocks. if expect_block and level <= cond_level: sysexit( count, "Error, 'nuitka-project-if' is expected to be followed by block start.", ) expect_block = False if level <= cond_level: execute_block = True if level > cond_level and not execute_block: continue if str is not bytes: command = command.decode("utf8") arg = arg.decode("utf8") if command == "-if": if not arg.endswith(":"): sysexit( count, "Error, 'nuitka-project-if' needs to start a block with a colon at line end.", ) arg = arg[:-1] expanded = _expandProjectArg(arg, filename_arg, for_eval=True) r = eval( # We allow the user to run any code, pylint: disable=eval-used expanded ) # Likely mistakes, e.g. with "in" tests. if r is not True and r is not False: sys.exit( "Error, 'nuitka-project-if' condition %r (%r) does not yield boolean result %r" % (arg, expanded, r) ) execute_block = r expect_block = True cond_level = level elif command == "": arg = re.sub(r"""^([\w-]*=)(['"])(.*)\2$""", r"\1\3", arg.lstrip()) if not arg: continue yield _expandProjectArg(arg, filename_arg, for_eval=False) else: assert False, (command, line) def parseOptions(logger): # Pretty complex code, having a small options parser and many details as # well as integrating with plugins and run modes, pylint: disable=too-many-branches # First, isolate the first non-option arguments. extra_args = [] if is_nuitka_run: count = 0 for count, arg in enumerate(sys.argv): if count == 0: continue if arg[0] != "-": filename_arg = arg[0] break # Treat "--" as a terminator. if arg == "--": count += 1 break if count > 0: extra_args = sys.argv[count + 1 :] sys.argv = sys.argv[0 : count + 1] filename_arg = None for count, arg in enumerate(sys.argv): if count == 0: continue if arg[0] != "-": filename_arg = arg break if filename_arg is not None: sys.argv = ( [sys.argv[0]] + list(_getProjectOptions(logger, filename_arg, "--module" in sys.argv[1:])) + sys.argv[1:] ) # Next, lets activate plugins early, so they can inject more options to the parser. _considerPluginOptions(logger) options, positional_args = parser.parse_args() if options.list_plugins: from nuitka.plugins.Plugins import listPlugins listPlugins() sys.exit(0) if not positional_args: parser.print_help() logger.sysexit( """ Error, need positional argument with python module or main program.""" ) if not options.immediate_execution and len(positional_args) > 1: parser.print_help() logger.sysexit( """ Error, specify only one positional argument unless "--run" is specified to pass them to the compiled program execution.""" ) return is_nuitka_run, options, positional_args, extra_args Nuitka-0.6.19.1/nuitka/OutputDirectories.py0000600000372100037210000001015514166627112025633 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Directories and paths to for output of Nuitka. There are two major outputs, the build directory *.build and for standalone mode, the *.dist folder. A bunch of functions here are supposed to get path resolution from this. """ import os from nuitka import Options from nuitka.utils.FileOperations import makePath from nuitka.utils.Importing import getSharedLibrarySuffix from nuitka.utils.Utils import getOS, isWin32Windows _main_module = None def setMainModule(main_module): """Call this before using other methods of this module.""" # Technically required. assert main_module.isCompiledPythonModule() # Singleton and to avoid passing this one all the time, pylint: disable=global-statement global _main_module _main_module = main_module def getSourceDirectoryPath(onefile=False): """Return path inside the build directory.""" # Distinct build folders for oneline mode. if onefile: suffix = ".onefile-build" else: suffix = ".build" result = Options.getOutputPath( path=os.path.basename(getTreeFilenameWithSuffix(_main_module, suffix)) ) makePath(result) return result def getStandaloneDistSuffix(): """Suffix to use for standalone distribition folder.""" if Options.shallCreateAppBundle(): return ".app" else: return ".dist" def getStandaloneDirectoryPath(): result = Options.getOutputPath( path=os.path.basename( getTreeFilenameWithSuffix(_main_module, getStandaloneDistSuffix()) ) ) if Options.shallCreateAppBundle(): result = os.path.join(result, "Contents", "MacOS") return result def getResultBasepath(onefile=False): if Options.isStandaloneMode() and not onefile: return os.path.join( getStandaloneDirectoryPath(), os.path.basename(getTreeFilenameWithSuffix(_main_module, "")), ) else: return Options.getOutputPath( path=os.path.basename(getTreeFilenameWithSuffix(_main_module, "")) ) def getResultFullpath(onefile): """Get the final output binary result full path.""" result = getResultBasepath(onefile=onefile) if Options.shallMakeModule(): result += getSharedLibrarySuffix(preferred=True) else: output_filename = Options.getOutputFilename() if Options.isOnefileMode() and output_filename is not None: if onefile: result = output_filename else: result = os.path.join( getStandaloneDirectoryPath(), os.path.basename(output_filename), ) elif output_filename is not None: result = output_filename elif getOS() == "Windows": result += ".exe" elif not Options.isStandaloneMode() or onefile: result += ".bin" return result def getResultRunFilename(onefile): result = getResultFullpath(onefile=onefile) if isWin32Windows() and Options.shallTreatUninstalledPython(): result = getResultBasepath(onefile=onefile) + ".cmd" return result def getTreeFilenameWithSuffix(module, suffix): return module.getOutputFilename() + suffix def getPgoRunExecutable(): return Options.getPgoExecutable() or getResultRunFilename(onefile=False) def getPgoRunInputFilename(): return getPgoRunExecutable() + ".nuitka-pgo" Nuitka-0.6.19.1/nuitka/codegen/0000700000372100037210000000000014167275622023172 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/codegen/Reports.py0000600000372100037210000000551314166627112025202 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Reports about code generation. Initially this is about missing optimization only, but it should expand into real stuff. """ from nuitka.containers.odict import OrderedDict from nuitka.containers.oset import OrderedSet from nuitka.Tracing import codegen_logger, optimization_logger _missing_helpers = OrderedDict() _missing_operations = OrderedSet() _missing_trust = OrderedDict() _error_for_missing = False # _error_for_missing = True def doMissingOptimizationReport(): for helper, source_refs in _missing_helpers.items(): message = "Missing C helper code variant, used fallback: %s at %s" % ( ",".join(source_ref.getAsString() for source_ref in source_refs), helper, ) if _error_for_missing: codegen_logger.warning(message) else: codegen_logger.info(message) for desc in _missing_operations: message = "Missing optimization, used fallback: %s" % (desc,) if _error_for_missing: optimization_logger.warning(message) else: optimization_logger.info(message) for desc, source_refs in _missing_trust.items(): message = desc[0] % desc[1:] message += " at %s" % ",".join( source_ref.getAsString() for source_ref in source_refs ) if _error_for_missing: optimization_logger.warning(message) else: optimization_logger.info(message) def onMissingHelper(helper_name, source_ref): if source_ref: if helper_name not in _missing_helpers: _missing_helpers[helper_name] = [] _missing_helpers[helper_name].append(source_ref) def onMissingOperation(operation, left, right): # Avoid the circular dependency on tshape_uninit from StandardShapes. if right.__class__.__name__ != "ShapeTypeUninit": _missing_operations.add((operation, left, right)) def onMissingTrust(operation, source_ref, *args): key = (operation,) + args if key not in _missing_trust: _missing_trust[key] = OrderedSet() _missing_trust[key].add(source_ref) Nuitka-0.6.19.1/nuitka/codegen/RaisingCodes.py0000600000372100037210000003130214166627112026111 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for implicit and explicit exception raises. Exceptions from other operations are consider ErrorCodes domain. """ from nuitka import Options from .CodeHelpers import ( generateChildExpressionsCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getFrameVariableTypeDescriptionCode from .LabelCodes import getGotoCode from .LineNumberCodes import ( emitErrorLineNumberUpdateCode, getErrorLineNumberUpdateCode, ) from .PythonAPICodes import getReferenceExportCode def generateReraiseCode(statement, emit, context): with context.withCurrentSourceCodeReference( value=statement.getCompatibleSourceReference() ): getReRaiseExceptionCode(emit=emit, context=context) def generateRaiseCode(statement, emit, context): exception_type = statement.subnode_exception_type exception_value = statement.subnode_exception_value exception_tb = statement.subnode_exception_trace exception_cause = statement.subnode_exception_cause # Exception cause is only possible with simple raise form. if exception_cause is not None: assert exception_type is not None assert exception_value is None assert exception_tb is None raise_type_name = context.allocateTempName("raise_type") generateExpressionCode( to_name=raise_type_name, expression=exception_type, emit=emit, context=context, ) raise_cause_name = context.allocateTempName("raise_cause") generateExpressionCode( to_name=raise_cause_name, expression=exception_cause, emit=emit, context=context, ) with context.withCurrentSourceCodeReference( exception_cause.getSourceReference() ): _getRaiseExceptionWithCauseCode( raise_type_name=raise_type_name, raise_cause_name=raise_cause_name, emit=emit, context=context, ) elif exception_type is None: assert False, statement elif exception_value is None and exception_tb is None: raise_type_name = context.allocateTempName("raise_type") generateExpressionCode( to_name=raise_type_name, expression=exception_type, emit=emit, context=context, ) with context.withCurrentSourceCodeReference( value=exception_type.getCompatibleSourceReference() ): _getRaiseExceptionWithTypeCode( raise_type_name=raise_type_name, emit=emit, context=context ) elif exception_tb is None: raise_type_name = context.allocateTempName("raise_type") generateExpressionCode( to_name=raise_type_name, expression=exception_type, emit=emit, context=context, ) raise_value_name = context.allocateTempName("raise_value") generateExpressionCode( to_name=raise_value_name, expression=exception_value, emit=emit, context=context, ) with context.withCurrentSourceCodeReference( exception_value.getCompatibleSourceReference() ): _getRaiseExceptionWithValueCode( raise_type_name=raise_type_name, raise_value_name=raise_value_name, implicit=statement.isStatementRaiseExceptionImplicit(), emit=emit, context=context, ) else: raise_type_name = context.allocateTempName("raise_type") generateExpressionCode( to_name=raise_type_name, expression=exception_type, emit=emit, context=context, ) raise_value_name = context.allocateTempName("raise_value") generateExpressionCode( to_name=raise_value_name, expression=exception_value, emit=emit, context=context, ) raise_tb_name = context.allocateTempName("raise_tb") generateExpressionCode( to_name=raise_tb_name, expression=exception_tb, emit=emit, context=context ) with context.withCurrentSourceCodeReference(exception_tb.getSourceReference()): _getRaiseExceptionWithTracebackCode( raise_type_name=raise_type_name, raise_value_name=raise_value_name, raise_tb_name=raise_tb_name, emit=emit, context=context, ) def generateRaiseExpressionCode(to_name, expression, emit, context): arg_names = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # Missed optimization opportunity, please report it, this should not # normally happen. We are supposed to propagate this upwards. if Options.is_debug: # TODO: Need to optimize ExpressionLocalsVariableRefOrFallback once we know # it handles cases where the value is not in locals dict properly. parent = expression.parent assert ( parent.isExpressionSideEffects() or parent.isExpressionConditional() or parent.isExpressionLocalsVariableRefOrFallback() ), (expression, expression.parent, expression.asXmlText()) with withObjectCodeTemporaryAssignment( to_name, "raise_exception_result", expression, emit, context ) as value_name: # That's how we indicate exception to the surrounding world. emit("%s = NULL;" % value_name) _getRaiseExceptionWithValueCode( raise_type_name=arg_names[0], raise_value_name=arg_names[1], implicit=True, emit=emit, context=context, ) def getReRaiseExceptionCode(emit, context): ( exception_type, exception_value, exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() keeper_variables = context.getExceptionKeeperVariables() if keeper_variables[0] is None: emit( """\ %(bool_res_name)s = RERAISE_EXCEPTION(&%(exception_type)s, &%(exception_value)s, &%(exception_tb)s); if (unlikely(%(bool_res_name)s == false)) { %(update_code)s } """ % { "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "bool_res_name": context.getBoolResName(), "update_code": getErrorLineNumberUpdateCode(context), } ) frame_handle = context.getFrameHandle() if frame_handle: emit( """\ if (%(exception_tb)s && %(exception_tb)s->tb_frame == &%(frame_identifier)s->m_frame) \ %(frame_identifier)s->m_frame.f_lineno = %(exception_tb)s->tb_lineno;""" % { "exception_tb": exception_tb, "frame_identifier": context.getFrameHandle(), } ) emit(getFrameVariableTypeDescriptionCode(context)) else: ( keeper_type, keeper_value, keeper_tb, keeper_lineno, ) = context.getExceptionKeeperVariables() emit( """\ // Re-raise. %(exception_type)s = %(keeper_type)s; %(exception_value)s = %(keeper_value)s; %(exception_tb)s = %(keeper_tb)s; %(exception_lineno)s = %(keeper_lineno)s; """ % { "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "exception_lineno": exception_lineno, "keeper_type": keeper_type, "keeper_value": keeper_value, "keeper_tb": keeper_tb, "keeper_lineno": keeper_lineno, } ) getGotoCode(context.getExceptionEscape(), emit) def _getRaiseExceptionWithCauseCode(raise_type_name, raise_cause_name, emit, context): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit("%s = %s;" % (exception_type, raise_type_name)) getReferenceExportCode(raise_type_name, emit, context) emit("%s = NULL;" % exception_value) getReferenceExportCode(raise_cause_name, emit, context) emitErrorLineNumberUpdateCode(emit, context) emit( "RAISE_EXCEPTION_WITH_CAUSE(&%s, &%s, &%s, %s);" % (exception_type, exception_value, exception_tb, raise_cause_name) ) emit(getFrameVariableTypeDescriptionCode(context)) getGotoCode(context.getExceptionEscape(), emit) if context.needsCleanup(raise_type_name): context.removeCleanupTempName(raise_type_name) if context.needsCleanup(raise_cause_name): context.removeCleanupTempName(raise_cause_name) def _getRaiseExceptionWithTypeCode(raise_type_name, emit, context): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit("%s = %s;" % (exception_type, raise_type_name)) getReferenceExportCode(raise_type_name, emit, context) emitErrorLineNumberUpdateCode(emit, context) emit( "RAISE_EXCEPTION_WITH_TYPE(&%s, &%s, &%s);" % (exception_type, exception_value, exception_tb) ) emit(getFrameVariableTypeDescriptionCode(context)) getGotoCode(context.getExceptionEscape(), emit) if context.needsCleanup(raise_type_name): context.removeCleanupTempName(raise_type_name) def _getRaiseExceptionWithValueCode( raise_type_name, raise_value_name, implicit, emit, context ): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit("%s = %s;" % (exception_type, raise_type_name)) getReferenceExportCode(raise_type_name, emit, context) emit("%s = %s;" % (exception_value, raise_value_name)) getReferenceExportCode(raise_value_name, emit, context) emitErrorLineNumberUpdateCode(emit, context) emit( "RAISE_EXCEPTION_%s(&%s, &%s, &%s);" % ( ("IMPLICIT" if implicit else "WITH_VALUE"), exception_type, exception_value, exception_tb, ) ) emit(getFrameVariableTypeDescriptionCode(context)) getGotoCode(context.getExceptionEscape(), emit) if context.needsCleanup(raise_type_name): context.removeCleanupTempName(raise_type_name) if context.needsCleanup(raise_value_name): context.removeCleanupTempName(raise_value_name) def _getRaiseExceptionWithTracebackCode( raise_type_name, raise_value_name, raise_tb_name, emit, context ): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit("%s = %s;" % (exception_type, raise_type_name)) getReferenceExportCode(raise_type_name, emit, context) emit("%s = %s;" % (exception_value, raise_value_name)) getReferenceExportCode(raise_value_name, emit, context) emit("%s = (PyTracebackObject *)%s;" % (exception_tb, raise_tb_name)) getReferenceExportCode(raise_tb_name, emit, context) emit( "RAISE_EXCEPTION_WITH_TRACEBACK( &%s, &%s, &%s);" % (exception_type, exception_value, exception_tb) ) # If anything is wrong, that will be used. emitErrorLineNumberUpdateCode(emit, context) emit(getFrameVariableTypeDescriptionCode(context)) getGotoCode(context.getExceptionEscape(), emit) if context.needsCleanup(raise_type_name): context.removeCleanupTempName(raise_type_name) if context.needsCleanup(raise_value_name): context.removeCleanupTempName(raise_value_name) if context.needsCleanup(raise_tb_name): context.removeCleanupTempName(raise_tb_name) Nuitka-0.6.19.1/nuitka/codegen/ExpressionCodes.py0000600000372100037210000000405514166627112026661 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Expression codes, side effects, or statements that are an unused expression. When you write "f()", i.e. you don't use the return value, that is an expression only statement. """ from .CodeHelpers import generateExpressionCode from .ErrorCodes import getReleaseCode def generateExpressionOnlyCode(statement, emit, context): return getStatementOnlyCode( value=statement.subnode_expression, emit=emit, context=context ) def getStatementOnlyCode(value, emit, context): tmp_name = context.allocateTempName( base_name="unused", type_name="nuitka_void", unique=True ) tmp_name.maybe_unused = True generateExpressionCode( expression=value, to_name=tmp_name, emit=emit, context=context ) # An error of the expression is dealt inside of this, not necessary here, # but we have to release non-error value if it has a reference. getReleaseCode(release_name=tmp_name, emit=emit, context=context) def generateSideEffectsCode(to_name, expression, emit, context): for side_effect in expression.subnode_side_effects: getStatementOnlyCode(value=side_effect, emit=emit, context=context) generateExpressionCode( to_name=to_name, expression=expression.subnode_expression, emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/CallCodes.py0000600000372100037210000010417214166627112025376 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for calls. The different kinds of calls get dedicated code. Most notable, calls with only positional arguments, are attempted through helpers that might be able to execute them without creating the argument dictionary at all. """ from nuitka.Constants import isMutable from nuitka.utils.Jinja2 import getTemplateC from .CodeHelpers import ( generateChildExpressionCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitCode from .LineNumberCodes import emitLineNumberUpdateCode from .templates.CodeTemplatesModules import ( template_header_guard, template_helper_impl_decl, ) def _generateCallCodePosOnly( to_name, expression, called_name, called_attribute_name, emit, context ): # We have many variants for this to deal with, pylint: disable=too-many-branches assert called_name is not None # TODO: Not yet specialized for method calls. # assert called_attribute_name is None call_args = expression.subnode_args if call_args is None or call_args.isExpressionConstantRef(): context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) if call_args is not None: call_args_value = call_args.getCompileTimeConstant() else: call_args_value = () assert type(call_args_value) is tuple if call_args is not None and call_args.isMutable(): call_arg_names = [] for call_arg_element in call_args_value: call_arg_name = context.allocateTempName("call_arg_element") call_arg_name.getCType().emitAssignmentCodeFromConstant( to_name=call_arg_name, constant=call_arg_element, may_escape=True, emit=emit, context=context, ) call_arg_names.append(call_arg_name) if called_attribute_name is None: getCallCodePosArgsQuick( to_name=to_name, called_name=called_name, arg_names=call_arg_names, expression=expression, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: _getInstanceCallCodePosArgsQuick( to_name=to_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, arg_names=call_arg_names, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) elif call_args_value: if called_attribute_name is None: _getCallCodeFromTuple( to_name=to_name, called_name=called_name, expression=expression, args_value=call_args_value, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: _getInstanceCallCodeFromTuple( to_name=to_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, arg_tuple=context.getConstantCode(constant=call_args_value), arg_size=len(call_args_value), needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: if called_attribute_name is None: getCallCodeNoArgs( to_name=to_name, called_name=called_name, expression=expression, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: _getInstanceCallCodeNoArgs( to_name=to_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) elif call_args.isExpressionMakeTuple(): call_arg_names = [] for call_arg_element in call_args.subnode_elements: call_arg_name = generateChildExpressionCode( child_name=call_args.getChildName() + "_element", expression=call_arg_element, emit=emit, context=context, ) call_arg_names.append(call_arg_name) if called_attribute_name is None: getCallCodePosArgsQuick( to_name=to_name, called_name=called_name, expression=expression, arg_names=call_arg_names, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: _getInstanceCallCodePosArgsQuick( to_name=to_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, arg_names=call_arg_names, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: args_name = generateChildExpressionCode( expression=call_args, emit=emit, context=context ) context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) if called_attribute_name is None: _getCallCodePosArgs( to_name=to_name, called_name=called_name, expression=expression, args_name=args_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) else: _getInstanceCallCodePosArgs( to_name=to_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, args_name=args_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) def _generateCallCodeKwSplitFromConstant( to_name, expression, call_kw, called_name, called_attribute_name, emit, context ): assert called_name is not None # TODO: Not yet specialized for method calls. assert called_attribute_name is None kw_items = tuple(call_kw.getCompileTimeConstant().items()) values = tuple(item[1] for item in kw_items) kw_names = tuple(item[0] for item in kw_items) if isMutable(values): args_kwsplit_name = context.allocateTempName("call_args_kwsplit") args_kwsplit_name.getCType().emitAssignmentCodeFromConstant( to_name=args_kwsplit_name, constant=values, may_escape=True, emit=emit, context=context, ) split_name = args_kwsplit_name else: args_kwsplit_name = context.getConstantCode(values) split_name = None emitLineNumberUpdateCode(expression, emit, context) emit( """%s = CALL_FUNCTION_WITH_NO_ARGS_KWSPLIT(%s, &PyTuple_GET_ITEM(%s, 0), %s);""" % ( to_name, called_name, args_kwsplit_name, context.getConstantCode(kw_names), ) ) getErrorExitCode( check_name=to_name, release_names=(called_name, split_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _generateCallCodeKwSplit( to_name, expression, call_kw, called_name, called_attribute_name, emit, context ): assert called_name is not None # TODO: Not yet specialized for method calls. assert called_attribute_name is None context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) kw_names = [] dict_value_names = [] for count, pair in enumerate(call_kw.subnode_pairs): kw_names.append(pair.subnode_key.getCompileTimeConstant()) dict_value_name = context.allocateTempName("kw_call_value_%d" % count) generateExpressionCode( to_name=dict_value_name, expression=pair.subnode_value, emit=emit, context=context, allow_none=False, ) dict_value_names.append(dict_value_name) emitLineNumberUpdateCode(expression, emit, context) emit( """\ { PyObject *kw_values[%(kw_size)d] = {%(kw_value_names)s}; %(to_name)s = CALL_FUNCTION_WITH_NO_ARGS_KWSPLIT(%(called_name)s, kw_values, %(kw_names)s); } """ % { "to_name": to_name, "kw_value_names": ", ".join( str(dict_value_name) for dict_value_name in dict_value_names ), "kw_size": len(call_kw.subnode_pairs), "called_name": called_name, "kw_names": context.getConstantCode(tuple(kw_names)), } ) getErrorExitCode( check_name=to_name, release_names=(called_name,) + tuple(dict_value_names), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _generateCallCodeKwDict( to_name, expression, call_kw, called_name, called_attribute_name, emit, context ): assert called_name is not None # TODO: Not yet specialized for method calls. assert called_attribute_name is None context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) kw_dict_name = context.allocateTempName("kw_dict") generateExpressionCode( to_name=kw_dict_name, expression=call_kw, emit=emit, context=context, allow_none=False, ) emitLineNumberUpdateCode(expression, emit, context) emit( """\ %(to_name)s = CALL_FUNCTION_WITH_KEYARGS(%(called_name)s, %(kw_dict_name)s); """ % { "to_name": to_name, "kw_dict_name": kw_dict_name, "called_name": called_name, } ) getErrorExitCode( check_name=to_name, release_names=(called_name, kw_dict_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def generateCallCode(to_name, expression, emit, context): # There is a whole lot of different cases, for each of which, we create # optimized code, constant, with and without positional or keyword arguments # each, so there is lots of branches involved. called = expression.subnode_called call_kw = expression.subnode_kwargs call_args = expression.subnode_args # TODO: Make this work for all cases. Currently, the method calls that do # a combined lookup and call, do a re-ordering of things, and therefore it # must be disabled until this is solved. if ( called.isExpressionAttributeLookup() and not called.isExpressionAttributeLookupSpecial() and called.getAttributeName() not in ("__class__", "__dict__") and ( call_args is None or not call_args.mayHaveSideEffects() or not called.mayHaveSideEffects() ) and call_kw is None ): called_name = context.allocateTempName("called_instance") generateExpressionCode( to_name=called_name, expression=called.subnode_expression, emit=emit, context=context, ) called_attribute_name = context.getConstantCode( constant=called.getAttributeName() ) else: called_attribute_name = None called_name = generateChildExpressionCode( expression=called, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "call_result", expression, emit, context ) as result_name: if call_kw is None or call_kw.isExpressionConstantDictEmptyRef(): _generateCallCodePosOnly( to_name=result_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, emit=emit, context=context, ) else: call_args = expression.subnode_args if call_args is None or call_args.isExpressionConstantTupleEmptyRef(): if call_kw.isExpressionConstantDictRef(): # Optimization should have turned that into a raise exception. assert call_kw.isMappingWithConstantStringKeys() _generateCallCodeKwSplitFromConstant( to_name=result_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, call_kw=call_kw, emit=emit, context=context, ) elif ( call_kw.isExpressionMakeDict() and call_kw.isMappingWithConstantStringKeys() ): _generateCallCodeKwSplit( to_name=result_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, call_kw=call_kw, emit=emit, context=context, ) else: # TODO: Still a very slow path. _generateCallCodeKwDict( to_name=result_name, called_name=called_name, called_attribute_name=called_attribute_name, expression=expression, call_kw=call_kw, emit=emit, context=context, ) else: if ( call_kw.isExpressionConstantDictRef() and call_args.isExpressionConstantTupleRef() ): # Both are constant, merge values into one tuple and pass it on. _getCallCodePosConstantKeywordConstArgs( to_name=result_name, called_name=called_name, expression=expression, call_args=call_args, call_kw=call_kw, emit=emit, context=context, ) elif ( call_kw.isExpressionMakeDict() and call_args.isExpressionConstantTupleRef() ): # Only positional args are constant, create tuple and split keyword values. _getCallCodePosConstKeywordVariableArgs( to_name=result_name, called_name=called_name, expression=expression, call_args=call_args, call_kw=call_kw, emit=emit, context=context, ) elif ( call_kw.isExpressionMakeDict() and call_args.isExpressionMakeTuple() ): # None are constant, pass as args array split keyword values. _getCallCodePosVariableKeywordVariableArgs( to_name=result_name, called_name=called_name, expression=expression, call_args=call_args, call_kw=call_kw, emit=emit, context=context, ) else: # Otherwise, pass as tuple and dict call_args_name = generateChildExpressionCode( expression=call_args, emit=emit, context=context ) call_kw_name = generateChildExpressionCode( expression=call_kw, emit=emit, context=context ) context.setCurrentSourceCodeReference( expression.getCompatibleSourceReference() ) _getCallCodePosKeywordArgs( to_name=result_name, called_name=called_name, expression=expression, call_args_name=call_args_name, call_kw_name=call_kw_name, emit=emit, context=context, ) def getCallCodeNoArgs(to_name, called_name, expression, needs_check, emit, context): emitLineNumberUpdateCode(expression, emit, context) emit("%s = CALL_FUNCTION_NO_ARGS(%s);" % (to_name, called_name)) getErrorExitCode( check_name=to_name, release_name=called_name, emit=emit, needs_check=needs_check, context=context, ) context.addCleanupTempName(to_name) def _getInstanceCallCodeNoArgs( to_name, called_name, called_attribute_name, expression, needs_check, emit, context ): emitLineNumberUpdateCode(expression, emit, context) emit( "%s = CALL_METHOD_NO_ARGS(%s, %s);" % (to_name, called_name, called_attribute_name) ) getErrorExitCode( check_name=to_name, release_names=(called_name, called_attribute_name), emit=emit, needs_check=needs_check, context=context, ) context.addCleanupTempName(to_name) quick_calls_used = set() quick_tuple_calls_used = set() quick_instance_calls_used = set() quick_mixed_calls_used = set() def _getInstanceCallCodePosArgsQuick( to_name, called_name, called_attribute_name, expression, arg_names, needs_check, emit, context, ): arg_size = len(arg_names) # For 0 arguments, NOARGS is supposed to be used. assert arg_size > 0 emitLineNumberUpdateCode(expression, emit, context) # For one argument, we have a dedicated helper function that might # be more efficient. if arg_size == 1: emit( """%s = CALL_METHOD_WITH_SINGLE_ARG(%s, %s, %s);""" % (to_name, called_name, called_attribute_name, arg_names[0]) ) else: quick_instance_calls_used.add(arg_size) emit( """\ { PyObject *call_args[] = {%(call_args)s}; %(to_name)s = CALL_METHOD_WITH_ARGS%(arg_size)d( %(called_name)s, %(called_attribute_name)s, call_args ); } """ % { "call_args": ", ".join(str(arg_name) for arg_name in arg_names), "to_name": to_name, "arg_size": arg_size, "called_name": called_name, "called_attribute_name": called_attribute_name, } ) getErrorExitCode( check_name=to_name, release_names=[called_name] + arg_names, needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def getCallCodePosArgsQuick( to_name, called_name, arg_names, expression, needs_check, emit, context ): arg_size = len(arg_names) # For 0 arguments, NOARGS is supposed to be used. assert arg_size > 0 emitLineNumberUpdateCode(expression, emit, context) # For one argument, we have a dedicated helper function that might # be more efficient. if arg_size == 1: emit( """%s = CALL_FUNCTION_WITH_SINGLE_ARG(%s, %s);""" % (to_name, called_name, arg_names[0]) ) else: quick_calls_used.add(arg_size) emit( """\ { PyObject *call_args[] = {%s}; %s = CALL_FUNCTION_WITH_ARGS%d(%s, call_args); } """ % ( ", ".join(str(arg_name) for arg_name in arg_names), to_name, arg_size, called_name, ) ) getErrorExitCode( check_name=to_name, release_names=[called_name] + arg_names, needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getInstanceCallCodeFromTuple( to_name, called_name, called_attribute_name, expression, arg_tuple, arg_size, needs_check, emit, context, ): quick_instance_calls_used.add(arg_size) # For 0 arguments, NOARGS is supposed to be used. assert arg_size > 0 emitLineNumberUpdateCode(expression, emit, context) if arg_size == 1: template = """\ %(to_name)s = CALL_METHOD_WITH_SINGLE_ARG( %(called_name)s, %(called_attribute_name)s, PyTuple_GET_ITEM(%(arg_tuple)s, 0) ); """ else: template = """\ %(to_name)s = CALL_METHOD_WITH_ARGS%(arg_size)d( %(called_name)s, %(called_attribute_name)s, &PyTuple_GET_ITEM(%(arg_tuple)s, 0) ); """ emit( template % { "to_name": to_name, "arg_size": arg_size, "called_name": called_name, "called_attribute_name": called_attribute_name, "arg_tuple": arg_tuple, } ) getErrorExitCode( check_name=to_name, release_names=(called_name, called_attribute_name), needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodeFromTuple( to_name, called_name, expression, args_value, needs_check, emit, context ): arg_size = len(args_value) # For 0 arguments, NOARGS is supposed to be used. assert arg_size > 0 emitLineNumberUpdateCode(expression, emit, context) # We create a tuple for the call, as this can be prepared and might have to be # recreated for cases, e.g. when calling C functions, so this is a good way of # having them. if isMutable(args_value): arg_tuple_name = context.allocateTempName("call_args_kwsplit") arg_tuple_name.getCType().emitAssignmentCodeFromConstant( to_name=arg_tuple_name, constant=args_value, may_escape=True, emit=emit, context=context, ) args_name = arg_tuple_name else: arg_tuple_name = context.getConstantCode(constant=args_value) args_name = None quick_tuple_calls_used.add(arg_size) emit( """\ %s = CALL_FUNCTION_WITH_POSARGS%d(%s, %s); """ % (to_name, arg_size, called_name, arg_tuple_name) ) getErrorExitCode( check_name=to_name, release_names=(called_name, args_name), needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getInstanceCallCodePosArgs( to_name, called_name, called_attribute_name, expression, args_name, needs_check, emit, context, ): emitLineNumberUpdateCode(expression, emit, context) emit( "%s = CALL_METHOD_WITH_POSARGS(%s, %s, %s);" % (to_name, called_name, called_attribute_name, args_name) ) getErrorExitCode( check_name=to_name, release_names=(called_name, args_name), needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodePosArgs( to_name, called_name, expression, args_name, needs_check, emit, context ): emitLineNumberUpdateCode(expression, emit, context) emit("%s = CALL_FUNCTION_WITH_POSARGS(%s, %s);" % (to_name, called_name, args_name)) getErrorExitCode( check_name=to_name, release_names=(called_name, args_name), needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodePosConstKeywordVariableArgs( to_name, called_name, expression, call_args, call_kw, emit, context ): # More details, pylint: disable=too-many-locals args = call_args.getCompileTimeConstant() kw_names = [] dict_value_names = [] for count, pair in enumerate(call_kw.subnode_pairs): kw_names.append(pair.subnode_key.getCompileTimeConstant()) dict_value_name = context.allocateTempName("kw_call_value_%d" % count) generateExpressionCode( to_name=dict_value_name, expression=pair.subnode_value, emit=emit, context=context, allow_none=False, ) dict_value_names.append(dict_value_name) args_count = len(args) quick_mixed_calls_used.add((args_count, True, True)) if isMutable(args): args_value_name = context.allocateTempName("call_posargs_values") args_value_name.getCType().emitAssignmentCodeFromConstant( to_name=args_value_name, constant=args, may_escape=True, emit=emit, context=context, ) args_name = args_value_name else: args_value_name = context.getConstantCode(args) args_name = None emitLineNumberUpdateCode(expression, emit, context) emit( """\ { PyObject *kw_values[%(kw_size)d] = {%(kw_values)s}; %(to_name)s = CALL_FUNCTION_WITH_POSARGS%(args_count)d_KWSPLIT(%(called_name)s, %(pos_args)s, kw_values, %(kw_names)s); } """ % { "to_name": to_name, "kw_values": ", ".join( str(dict_value_name) for dict_value_name in dict_value_names ), "kw_size": len(call_kw.subnode_pairs), "pos_args": args_value_name, "args_count": args_count, "called_name": called_name, "kw_names": context.getConstantCode(tuple(kw_names)), } ) getErrorExitCode( check_name=to_name, release_names=(called_name, args_name) + tuple(dict_value_names), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodePosVariableKeywordVariableArgs( to_name, called_name, expression, call_args, call_kw, emit, context ): # More details, pylint: disable=too-many-locals kw_names = [] call_arg_names = [] for count, call_arg_element in enumerate(call_args.subnode_elements): call_arg_name = context.allocateTempName("kw_call_arg_value_%d" % count) generateExpressionCode( to_name=call_arg_name, expression=call_arg_element, emit=emit, context=context, ) call_arg_names.append(call_arg_name) dict_value_names = [] for count, pair in enumerate(call_kw.subnode_pairs): kw_names.append(pair.subnode_key.getCompileTimeConstant()) dict_value_name = context.allocateTempName("kw_call_dict_value_%d" % count) generateExpressionCode( to_name=dict_value_name, expression=pair.subnode_value, emit=emit, context=context, allow_none=False, ) dict_value_names.append(dict_value_name) args_count = len(call_args.subnode_elements) quick_mixed_calls_used.add((args_count, False, True)) emitLineNumberUpdateCode(expression, emit, context) emit( """\ { PyObject *args[] = {%(call_arg_names)s}; PyObject *kw_values[%(kw_size)d] = {%(kw_value_names)s}; %(to_name)s = CALL_FUNCTION_WITH_ARGS%(args_count)d_KWSPLIT(%(called_name)s, args, kw_values, %(kw_names)s); } """ % { "to_name": to_name, "call_arg_names": ", ".join( str(call_arg_name) for call_arg_name in call_arg_names ), "kw_value_names": ", ".join( str(dict_value_name) for dict_value_name in dict_value_names ), "kw_size": len(call_kw.subnode_pairs), "args_count": args_count, "called_name": called_name, "kw_names": context.getConstantCode(tuple(kw_names)), } ) getErrorExitCode( check_name=to_name, release_names=(called_name,) + tuple(call_arg_names) + tuple(dict_value_names), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodePosConstantKeywordConstArgs( to_name, called_name, expression, call_args, call_kw, emit, context ): kw_items = tuple(call_kw.getCompileTimeConstant().items()) args = call_args.getCompileTimeConstant() values = args + tuple(item[1] for item in kw_items) kw_names = tuple(item[0] for item in kw_items) arg_size = len(args) quick_mixed_calls_used.add((arg_size, False, False)) if isMutable(values): args_values_name = context.allocateTempName("call_args_values") args_values_name.getCType().emitAssignmentCodeFromConstant( to_name=args_values_name, constant=values, may_escape=True, emit=emit, context=context, ) vector_name = args_values_name else: args_values_name = context.getConstantCode(values) vector_name = None emitLineNumberUpdateCode(expression, emit, context) emit( """%s = CALL_FUNCTION_WITH_ARGS%d_VECTORCALL(%s, &PyTuple_GET_ITEM(%s, 0), %s);""" % ( to_name, arg_size, called_name, args_values_name, context.getConstantCode(kw_names), ) ) getErrorExitCode( check_name=to_name, release_names=(called_name, vector_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getCallCodePosKeywordArgs( to_name, called_name, expression, call_args_name, call_kw_name, emit, context ): emitLineNumberUpdateCode(expression, emit, context) emit( "%s = CALL_FUNCTION(%s, %s, %s);" % (to_name, called_name, call_args_name, call_kw_name) ) getErrorExitCode( check_name=to_name, release_names=(called_name, call_args_name, call_kw_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) max_quick_call = 10 def getQuickCallCode(args_count, has_tuple_arg): template = getTemplateC("nuitka.codegen", "CodeTemplateCallsPositional.c.j2") return template.render(args_count=args_count, has_tuple_arg=has_tuple_arg) def getQuickMethodCallCode(args_count): template = getTemplateC("nuitka.codegen", "CodeTemplateCallsMethodPositional.c.j2") return template.render(args_count=args_count) def getQuickMixedCallCode(args_count, has_tuple_arg, has_dict_values): template = getTemplateC("nuitka.codegen", "CodeTemplateCallsMixed.c.j2") return template.render( args_count=args_count, has_tuple_arg=has_tuple_arg, has_dict_values=has_dict_values, ) def getQuickMethodDescrCallCode(args_count): template = getTemplateC( "nuitka.codegen", "CodeTemplateCallsPositionalMethodDescr.c.j2" ) return template.render( args_count=args_count, ) def getTemplateCodeDeclaredFunction(code): return "extern " + code.strip().splitlines()[0].strip().replace(" {", ";").replace( " {", ";" ).replace("static ", "").replace("inline ", "").replace( "HEDLEY_NEVER_INLINE ", "" ).replace( "__BINARY", "BINARY" ).replace( "_BINARY", "BINARY" ) def getCallsCode(): header_codes = [] body_codes = [] body_codes.append(template_helper_impl_decl % {}) for quick_call_used in sorted(quick_calls_used.union(quick_instance_calls_used)): if quick_call_used <= max_quick_call: continue code = getQuickCallCode(args_count=quick_call_used, has_tuple_arg=False) body_codes.append(code) header_codes.append(getTemplateCodeDeclaredFunction(code)) for quick_tuple_call_used in sorted(quick_tuple_calls_used): if quick_tuple_call_used <= max_quick_call: continue code = getQuickCallCode(args_count=quick_tuple_call_used, has_tuple_arg=True) body_codes.append(code) header_codes.append(getTemplateCodeDeclaredFunction(code)) for quick_mixed_call_used, has_tuple_arg, has_dict_values in sorted( quick_mixed_calls_used ): if quick_mixed_call_used <= max_quick_call: continue code = getQuickMixedCallCode( args_count=quick_mixed_call_used, has_tuple_arg=has_tuple_arg, has_dict_values=has_dict_values, ) body_codes.append(code) header_codes.append(getTemplateCodeDeclaredFunction(code)) for quick_instance_call_used in sorted(quick_instance_calls_used): if quick_instance_call_used <= max_quick_call: continue code = getQuickMethodCallCode(args_count=quick_instance_call_used) body_codes.append(code) header_codes.append(getTemplateCodeDeclaredFunction(code)) return ( template_header_guard % { "header_guard_name": "__NUITKA_CALLS_H__", "header_body": "\n".join(header_codes), }, "\n".join(body_codes), ) Nuitka-0.6.19.1/nuitka/codegen/SliceCodes.py0000600000372100037210000003354114166627112025563 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for slicing. This is about slice lookups, assignments, and deletions. There is also a special case, for using index values instead of objects. The slice objects are also created here, and can be used for indexing. """ from nuitka import Options from nuitka.PythonVersions import python_version from .CodeHelpers import ( generateChildExpressionsCode, generateExpressionCode, generateExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode from .IndexCodes import ( getIndexCode, getIndexValueCode, getMaxIndexCode, getMinIndexCode, ) def _isSmallNumberConstant(node): if node.isNumberConstant(): value = node.getCompileTimeConstant() return abs(int(value)) < 2 ** 63 - 1 else: return False def _generateSliceRangeIdentifier(lower, upper, scope, emit, context): lower_name = context.allocateTempName(scope + "slicedel_index_lower", "Py_ssize_t") upper_name = context.allocateTempName(scope + "_index_upper", "Py_ssize_t") if lower is None: getMinIndexCode(to_name=lower_name, emit=emit) elif lower.isExpressionConstantRef() and _isSmallNumberConstant(lower): getIndexValueCode( to_name=lower_name, value=int(lower.getCompileTimeConstant()), emit=emit ) else: value_name = context.allocateTempName(scope + "_lower_index_value") generateExpressionCode( to_name=value_name, expression=lower, emit=emit, context=context ) getIndexCode( to_name=lower_name, value_name=value_name, emit=emit, context=context ) if upper is None: getMaxIndexCode(to_name=upper_name, emit=emit) elif upper.isExpressionConstantRef() and _isSmallNumberConstant(upper): getIndexValueCode( to_name=upper_name, value=int(upper.getCompileTimeConstant()), emit=emit ) else: value_name = context.allocateTempName(scope + "_upper_index_value") generateExpressionCode( to_name=value_name, expression=upper, emit=emit, context=context ) getIndexCode( to_name=upper_name, value_name=value_name, emit=emit, context=context ) return lower_name, upper_name def _decideSlicing(lower, upper): return (lower is None or lower.isIndexable()) and ( upper is None or upper.isIndexable() ) def generateSliceLookupCode(to_name, expression, emit, context): assert python_version < 0x300 lower = expression.subnode_lower upper = expression.subnode_upper if _decideSlicing(lower, upper): lower_name, upper_name = _generateSliceRangeIdentifier( lower=lower, upper=upper, scope="slice", emit=emit, context=context ) source_name = context.allocateTempName("slice_source") generateExpressionCode( to_name=source_name, expression=expression.subnode_expression, emit=emit, context=context, ) with withObjectCodeTemporaryAssignment( to_name, "slice_result", expression, emit, context ) as result_name: _getSliceLookupIndexesCode( to_name=result_name, source_name=source_name, lower_name=lower_name, upper_name=upper_name, emit=emit, context=context, ) else: source_name, lower_name, upper_name = generateExpressionsCode( names=("slice_source", "slice_lower", "slice_upper"), expressions=( expression.subnode_expression, expression.subnode_lower, expression.subnode_upper, ), emit=emit, context=context, ) with withObjectCodeTemporaryAssignment( to_name, "slice_result", expression, emit, context ) as result_name: _getSliceLookupCode( to_name=result_name, source_name=source_name, lower_name=lower_name, upper_name=upper_name, emit=emit, context=context, ) def generateAssignmentSliceCode(statement, emit, context): assert python_version < 0x300 lookup_source = statement.subnode_expression lower = statement.subnode_lower upper = statement.subnode_upper value = statement.subnode_source value_name = context.allocateTempName("sliceass_value") generateExpressionCode( to_name=value_name, expression=value, emit=emit, context=context ) target_name = context.allocateTempName("sliceass_target") generateExpressionCode( to_name=target_name, expression=lookup_source, emit=emit, context=context ) if _decideSlicing(lower, upper): lower_name, upper_name = _generateSliceRangeIdentifier( lower=lower, upper=upper, scope="sliceass", emit=emit, context=context ) with context.withCurrentSourceCodeReference( value.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): _getSliceAssignmentIndexesCode( target_name=target_name, lower_name=lower_name, upper_name=upper_name, value_name=value_name, emit=emit, context=context, ) else: lower_name, upper_name = generateExpressionsCode( names=("sliceass_lower", "sliceass_upper"), expressions=(lower, upper), emit=emit, context=context, ) with context.withCurrentSourceCodeReference( value.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): _getSliceAssignmentCode( target_name=target_name, upper_name=upper_name, lower_name=lower_name, value_name=value_name, emit=emit, context=context, ) def generateDelSliceCode(statement, emit, context): assert python_version < 0x300 target = statement.subnode_expression lower = statement.subnode_lower upper = statement.subnode_upper target_name = context.allocateTempName("slicedel_target") generateExpressionCode( to_name=target_name, expression=target, emit=emit, context=context ) if _decideSlicing(lower, upper): lower_name, upper_name = _generateSliceRangeIdentifier( lower=lower, upper=upper, scope="slicedel", emit=emit, context=context ) with context.withCurrentSourceCodeReference( (upper or lower or statement).getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): _getSliceDelIndexesCode( target_name=target_name, lower_name=lower_name, upper_name=upper_name, emit=emit, context=context, ) else: lower_name, upper_name = generateExpressionsCode( names=("slicedel_lower", "slicedel_upper"), expressions=(lower, upper), emit=emit, context=context, ) with context.withCurrentSourceCodeReference( (upper or lower or target).getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): _getSliceDelCode( target_name=target_name, lower_name=lower_name, upper_name=upper_name, emit=emit, context=context, ) def generateBuiltinSlice3Code(to_name, expression, emit, context): lower_name, upper_name, step_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "sliceobj_value", expression, emit, context ) as result_name: emit( "%s = MAKE_SLICEOBJ3(%s, %s, %s);" % ( result_name, lower_name if lower_name is not None else "Py_None", upper_name if upper_name is not None else "Py_None", step_name if step_name is not None else "Py_None", ) ) getErrorExitCode( check_name=result_name, release_names=(lower_name, upper_name, step_name), needs_check=False, # Note: Cannot fail emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateBuiltinSlice2Code(to_name, expression, emit, context): lower_name, upper_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "sliceobj_value", expression, emit, context ) as result_name: emit( "%s = MAKE_SLICEOBJ2(%s, %s);" % ( result_name, lower_name if lower_name is not None else "Py_None", upper_name if upper_name is not None else "Py_None", ) ) getErrorExitCode( check_name=result_name, release_names=(lower_name, upper_name), needs_check=False, # Note: Cannot fail emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateBuiltinSlice1Code(to_name, expression, emit, context): (upper_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "sliceobj_value", expression, emit, context ) as result_name: emit( "%s = MAKE_SLICEOBJ1(%s);" % ( result_name, upper_name if upper_name is not None else "Py_None", ) ) getErrorExitCode( check_name=result_name, release_name=upper_name, needs_check=False, # Note: Cannot fail emit=emit, context=context, ) context.addCleanupTempName(result_name) def _getSliceLookupCode(to_name, source_name, lower_name, upper_name, emit, context): emit( "%s = LOOKUP_SLICE(%s, %s, %s);" % ( to_name, source_name, lower_name if lower_name is not None else "Py_None", upper_name if upper_name is not None else "Py_None", ) ) getErrorExitCode( check_name=to_name, release_names=(source_name, lower_name, upper_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getSliceLookupIndexesCode( to_name, lower_name, upper_name, source_name, emit, context ): emit( "%s = LOOKUP_INDEX_SLICE(%s, %s, %s);" % (to_name, source_name, lower_name, upper_name) ) getErrorExitCode( check_name=to_name, release_name=source_name, emit=emit, context=context ) context.addCleanupTempName(to_name) def _getSliceAssignmentIndexesCode( target_name, lower_name, upper_name, value_name, emit, context ): res_name = context.getBoolResName() emit( "%s = SET_INDEX_SLICE(%s, %s, %s, %s);" % (res_name, target_name, lower_name, upper_name, value_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(value_name, target_name), emit=emit, context=context, ) def _getSliceAssignmentCode( target_name, lower_name, upper_name, value_name, emit, context ): res_name = context.getBoolResName() emit( "%s = SET_SLICE(%s, %s, %s, %s);" % ( res_name, target_name, lower_name if lower_name is not None else "Py_None", upper_name if upper_name is not None else "Py_None", value_name, ) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(target_name, lower_name, upper_name, value_name), emit=emit, context=context, ) def _getSliceDelIndexesCode(target_name, lower_name, upper_name, emit, context): res_name = context.getBoolResName() emit( "%s = DEL_INDEX_SLICE(%s, %s, %s);" % (res_name, target_name, lower_name, upper_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_name=target_name, emit=emit, context=context, ) def _getSliceDelCode(target_name, lower_name, upper_name, emit, context): res_name = context.getBoolResName() emit( "%s = DEL_SLICE(%s, %s, %s);" % ( res_name, target_name, lower_name if lower_name is not None else "Py_None", upper_name if upper_name is not None else "Py_None", ) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(target_name, lower_name, upper_name), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/AsyncgenCodes.py0000600000372100037210000001431214166627112026266 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with compiled asyncgen objects. """ from .CodeHelpers import generateStatementSequenceCode from .Emission import SourceCodeCollector from .FunctionCodes import ( finalizeFunctionLocalVariables, getClosureCopyCode, getFunctionCreationArgs, getFunctionQualnameObj, setupFunctionLocalVariables, ) from .Indentation import indented from .ModuleCodes import getModuleAccessCode from .templates.CodeTemplatesAsyncgens import ( template_asyncgen_exception_exit, template_asyncgen_noexception_exit, template_asyncgen_object_body, template_asyncgen_object_maker_template, template_asyncgen_return_exit, template_make_asyncgen, ) from .YieldCodes import getYieldReturnDispatchCode def _getAsyncgenMakerIdentifier(function_identifier): return "MAKE_ASYNCGEN_" + function_identifier def getAsyncgenObjectDeclCode(function_identifier, closure_variables): asyncgen_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_asyncgen_object_maker_template % { "asyncgen_maker_identifier": _getAsyncgenMakerIdentifier(function_identifier), "asyncgen_creation_args": ", ".join(asyncgen_creation_args), } def getAsyncgenObjectCode( context, function_identifier, closure_variables, user_variables, outline_variables, temp_variables, needs_exception_exit, needs_generator_return, ): # A bit of details going on here, pylint: disable=too-many-locals setupFunctionLocalVariables( context=context, parameters=None, closure_variables=closure_variables, user_variables=user_variables + outline_variables, temp_variables=temp_variables, ) function_codes = SourceCodeCollector() asyncgen_object_body = context.getOwner() generateStatementSequenceCode( statement_sequence=asyncgen_object_body.subnode_body, allow_none=True, emit=function_codes, context=context, ) function_cleanup = finalizeFunctionLocalVariables(context) if needs_exception_exit: ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() generator_exit = template_asyncgen_exception_exit % { "function_cleanup": indented(function_cleanup), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, } else: generator_exit = template_asyncgen_noexception_exit % { "function_cleanup": indented(function_cleanup) } if needs_generator_return: generator_exit += template_asyncgen_return_exit % {} function_locals = context.variable_storage.makeCFunctionLevelDeclarations() local_type_decl = context.variable_storage.makeCStructLevelDeclarations() function_locals += context.variable_storage.makeCStructInits() if local_type_decl: heap_declaration = """\ struct %(function_identifier)s_locals *asyncgen_heap = \ (struct %(function_identifier)s_locals *)asyncgen->m_heap_storage;""" % { "function_identifier": function_identifier } else: heap_declaration = "" asyncgen_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_asyncgen_object_body % { "function_identifier": function_identifier, "function_body": indented(function_codes.codes), "heap_declaration": indented(heap_declaration), "function_local_types": indented(local_type_decl), "function_var_inits": indented(function_locals), "function_dispatch": indented(getYieldReturnDispatchCode(context)), "asyncgen_maker_identifier": _getAsyncgenMakerIdentifier(function_identifier), "asyncgen_creation_args": ", ".join(asyncgen_creation_args), "asyncgen_exit": generator_exit, "asyncgen_module": getModuleAccessCode(context), "asyncgen_name_obj": context.getConstantCode( constant=asyncgen_object_body.getFunctionName() ), "asyncgen_qualname_obj": getFunctionQualnameObj(asyncgen_object_body, context), "code_identifier": context.getCodeObjectHandle( code_object=asyncgen_object_body.getCodeObject() ), "closure_name": "closure" if closure_variables else "NULL", "closure_count": len(closure_variables), } def generateMakeAsyncgenObjectCode(to_name, expression, emit, context): asyncgen_object_body = expression.subnode_asyncgen_ref.getFunctionBody() closure_variables = expression.getClosureVariableVersions() closure_name, closure_copy = getClosureCopyCode( closure_variables=closure_variables, context=context ) args = [] if closure_name: args.append(closure_name) emit( template_make_asyncgen % { "to_name": to_name, "asyncgen_maker_identifier": _getAsyncgenMakerIdentifier( asyncgen_object_body.getCodeName() ), "args": ", ".join(str(arg) for arg in args), "closure_copy": indented(closure_copy, 0, True), } ) context.addCleanupTempName(to_name) Nuitka-0.6.19.1/nuitka/codegen/VariableDeclarations.py0000600000372100037210000002111214166627112027613 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Variable declarations Holds the information necessary to make C code declarations related to a variable. """ from contextlib import contextmanager from .c_types.CTypeBools import CTypeBool from .c_types.CTypeModuleDictVariables import CTypeModuleDictVariable from .c_types.CTypeNuitkaBools import CTypeNuitkaBoolEnum from .c_types.CTypeNuitkaInts import CTypeNuitkaIntOrLongStruct from .c_types.CTypePyObjectPtrs import ( CTypeCellObject, CTypePyObjectPtr, CTypePyObjectPtrPtr, ) from .c_types.CTypeVoids import CTypeVoid class VariableDeclaration(object): __slots__ = ("c_type", "code_name", "init_value", "heap_name", "maybe_unused") def __init__(self, c_type, code_name, init_value, heap_name): if c_type.startswith("NUITKA_MAY_BE_UNUSED"): self.c_type = c_type[21:] self.maybe_unused = True else: self.c_type = c_type self.maybe_unused = False self.code_name = code_name self.init_value = init_value self.heap_name = heap_name def makeCFunctionLevelDeclaration(self): pos = self.c_type.find("[") if pos != -1: lead_c_type = self.c_type[:pos] suffix_c_type = self.c_type[pos:] else: lead_c_type = self.c_type suffix_c_type = "" return "%s%s%s%s%s%s;" % ( "NUITKA_MAY_BE_UNUSED " if self.maybe_unused else "", lead_c_type, " " if lead_c_type[-1] != "*" else "", self.code_name, "" if self.init_value is None else " = %s" % self.init_value, suffix_c_type, ) def makeCStructDeclaration(self): c_type = self.c_type if "[" in c_type: array_decl = c_type[c_type.find("[") :] c_type = c_type[: c_type.find("[")] else: array_decl = "" return "%s%s%s%s;" % ( c_type, " " if self.c_type[-1] != "*" else "", self.code_name, array_decl, ) def makeCStructInit(self): if self.init_value is None: return None assert self.heap_name, repr(self) return "%s%s = %s;" % ( ((self.heap_name + "->") if self.heap_name is not None else ""), self.code_name, self.init_value, ) def getCType(self): # TODO: This ought to become unnecessry function # In the mean time, many cases: pylint: disable=too-many-return-statements c_type = self.c_type if c_type == "PyObject *": return CTypePyObjectPtr elif c_type == "struct Nuitka_CellObject *": return CTypeCellObject elif c_type == "PyObject **": return CTypePyObjectPtrPtr elif c_type == "nuitka_bool": return CTypeNuitkaBoolEnum elif c_type == "bool": return CTypeBool elif c_type == "nuitka_ilong": return CTypeNuitkaIntOrLongStruct elif c_type == "module_var": return CTypeModuleDictVariable elif c_type == "nuitka_void": return CTypeVoid assert False, c_type def __str__(self): if self.heap_name: return "%s->%s" % (self.heap_name, self.code_name) else: return self.code_name def __repr__(self): return "" % ( self.c_type, self.code_name, self.init_value, ) class VariableStorage(object): __slots__ = ( "heap_name", "variable_declarations_heap", "variable_declarations_main", "variable_declarations_closure", "variable_declarations_locals", "exception_variable_declarations", ) def __init__(self, heap_name): self.heap_name = heap_name self.variable_declarations_heap = [] self.variable_declarations_main = [] self.variable_declarations_closure = [] self.variable_declarations_locals = [] self.exception_variable_declarations = None @contextmanager def withLocalStorage(self): """Local storage for only just during context usage. This is for automatic removal of that scope. These are supposed to be nestable eventually. """ self.variable_declarations_locals.append([]) yield self.variable_declarations_locals.pop() def getVariableDeclarationTop(self, code_name): for variable_declaration in self.variable_declarations_main: if variable_declaration.code_name == code_name: return variable_declaration for variable_declaration in self.variable_declarations_heap: if variable_declaration.code_name == code_name: return variable_declaration return None def getVariableDeclarationClosure(self, closure_index): return self.variable_declarations_closure[closure_index] def addFrameCacheDeclaration(self, frame_identifier): return self.addVariableDeclarationFunction( "static struct Nuitka_FrameObject *", "cache_%s" % frame_identifier, "NULL" ) def makeCStructLevelDeclarations(self): return [ variable_declaration.makeCStructDeclaration() for variable_declaration in self.variable_declarations_heap ] def makeCStructInits(self): return [ variable_declaration.makeCStructInit() for variable_declaration in self.variable_declarations_heap if variable_declaration.init_value is not None ] def getExceptionVariableDescriptions(self): if self.exception_variable_declarations is None: self.exception_variable_declarations = ( self.addVariableDeclarationTop("PyObject *", "exception_type", "NULL"), self.addVariableDeclarationTop("PyObject *", "exception_value", "NULL"), self.addVariableDeclarationTop( "PyTracebackObject *", "exception_tb", "NULL" ), self.addVariableDeclarationTop( "NUITKA_MAY_BE_UNUSED int", "exception_lineno", "0" ), ) return self.exception_variable_declarations def addVariableDeclarationLocal(self, c_type, code_name): result = VariableDeclaration(c_type, code_name, None, None) self.variable_declarations_locals[-1].append(result) return result def addVariableDeclarationClosure(self, c_type, code_name): result = VariableDeclaration(c_type, code_name, None, None) self.variable_declarations_closure.append(result) return result def addVariableDeclarationFunction(self, c_type, code_name, init_value): result = VariableDeclaration(c_type, code_name, init_value, None) self.variable_declarations_main.append(result) return result def addVariableDeclarationTop(self, c_type, code_name, init_value): result = VariableDeclaration(c_type, code_name, init_value, self.heap_name) if self.heap_name is not None: self.variable_declarations_heap.append(result) else: self.variable_declarations_main.append(result) return result def makeCLocalDeclarations(self): return [ variable_declaration.makeCFunctionLevelDeclaration() for variable_declaration in self.variable_declarations_locals[-1] ] def makeCFunctionLevelDeclarations(self): return [ variable_declaration.makeCFunctionLevelDeclaration() for variable_declaration in self.variable_declarations_main ] def getLocalPreservationDeclarations(self): result = [] for variable_declarations_local in self.variable_declarations_locals: result.extend(variable_declarations_local) return result Nuitka-0.6.19.1/nuitka/codegen/LoaderCodes.py0000600000372100037210000001262514166627112025732 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with module loaders. This is for generating the look-up table for the modules included in a binary or distribution folder. Also this prepares tables for the freezer for bytecode compiled modules. Not real C compiled modules. This is including modules as bytecode and mostly intended for modules, where we know compiling it useless or does not make much sense, or for standalone mode to access modules during CPython library init that cannot be avoided. The level of compatibility for C compiled stuff is so high that this is not needed except for technical reasons. """ from nuitka import Options from nuitka.ModuleRegistry import ( getDoneModules, getUncompiledModules, getUncompiledTechnicalModules, ) from nuitka.plugins.Plugins import Plugins from nuitka.Tracing import inclusion_logger from nuitka.utils.CStrings import encodePythonStringToC from .Indentation import indented from .templates.CodeTemplatesLoader import ( template_metapath_loader_body, template_metapath_loader_bytecode_module_entry, template_metapath_loader_compiled_module_entry, template_metapath_loader_shlib_module_entry, ) def getModuleMetapathLoaderEntryCode(module, bytecode_accessor): module_c_name = encodePythonStringToC( Plugins.encodeDataComposerName(module.getFullName().asString()) ) flags = ["NUITKA_TRANSLATED_FLAG"] if module.isUncompiledPythonModule(): code_data = module.getByteCode() is_package = module.isUncompiledPythonPackage() flags.append("NUITKA_BYTECODE_FLAG") if is_package: flags.append("NUITKA_PACKAGE_FLAG") accessor_code = bytecode_accessor.getBlobDataCode(code_data) return template_metapath_loader_bytecode_module_entry % { "module_name": module_c_name, "bytecode": accessor_code[accessor_code.find("[") + 1 : -1], "size": len(code_data), "flags": " | ".join(flags) or "0", } elif module.isPythonShlibModule(): flags.append("NUITKA_SHLIB_FLAG") return template_metapath_loader_shlib_module_entry % { "module_name": module_c_name, "flags": " | ".join(flags) or "0", } else: if module.isCompiledPythonPackage(): flags.append("NUITKA_PACKAGE_FLAG") return template_metapath_loader_compiled_module_entry % { "module_name": module_c_name, "module_identifier": module.getCodeName(), "flags": " | ".join(flags), } def getMetapathLoaderBodyCode(bytecode_accessor): metapath_loader_inittab = [] metapath_module_decls = [] uncompiled_modules = getUncompiledModules() for other_module in getDoneModules(): # Put those at the end. if other_module in uncompiled_modules: continue metapath_loader_inittab.append( getModuleMetapathLoaderEntryCode( module=other_module, bytecode_accessor=bytecode_accessor ) ) if other_module.isCompiledPythonModule(): metapath_module_decls.append( """\ extern PyObject *modulecode_%(module_identifier)s(PyObject *, struct Nuitka_MetaPathBasedLoaderEntry const *);""" % {"module_identifier": other_module.getCodeName()} ) for uncompiled_module in uncompiled_modules: metapath_loader_inittab.append( getModuleMetapathLoaderEntryCode( module=uncompiled_module, bytecode_accessor=bytecode_accessor ) ) frozen_defs = [] for uncompiled_module in getUncompiledTechnicalModules(): module_name = uncompiled_module.getFullName() code_data = uncompiled_module.getByteCode() is_package = uncompiled_module.isUncompiledPythonPackage() size = len(code_data) # Packages are indicated with negative size. if is_package: size = -size accessor_code = bytecode_accessor.getBlobDataCode(code_data) frozen_defs.append( """\ {{"{module_name}", {start}, {size}}},""".format( module_name=module_name, start=accessor_code[accessor_code.find("[") + 1 : -1], size=size, ) ) if Options.isShowInclusion(): inclusion_logger.info("Embedded as frozen module '%s'." % module_name) return template_metapath_loader_body % { "metapath_module_decls": indented(metapath_module_decls, 0), "metapath_loader_inittab": indented(metapath_loader_inittab), "bytecode_count": bytecode_accessor.getConstantsCount(), "frozen_modules": indented(frozen_defs), } Nuitka-0.6.19.1/nuitka/codegen/DictCodes.py0000600000372100037210000006133614166627112025412 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for dictionaries. """ from nuitka import Options from nuitka.PythonVersions import python_version from nuitka.utils.Jinja2 import renderTemplateFromString from .CodeHelpers import ( assignConstantNoneResult, decideConversionCheckNeeded, generateChildExpressionsCode, generateExpressionCode, withCleanupFinally, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCodes from .PythonAPICodes import ( generateCAPIObjectCode, generateCAPIObjectCode0, makeArgDescFromExpression, ) def generateBuiltinDictCode(to_name, expression, emit, context): if expression.subnode_pos_arg: seq_name = context.allocateTempName("dict_seq") generateExpressionCode( to_name=seq_name, expression=expression.subnode_pos_arg, emit=emit, context=context, allow_none=True, ) else: seq_name = None with withObjectCodeTemporaryAssignment( to_name, "dict_value", expression, emit, context ) as value_name: if expression.subnode_pairs: # If there is no sequence to mix in, then directly generate # into to_name. if seq_name is None: _getDictionaryCreationCode( to_name=value_name, pairs=expression.subnode_pairs, emit=emit, context=context, ) dict_name = None else: dict_name = context.allocateTempName("dict_arg") _getDictionaryCreationCode( to_name=dict_name, pairs=expression.subnode_pairs, emit=emit, context=context, ) else: dict_name = None if seq_name is not None: emit( "%s = TO_DICT(%s, %s);" % (value_name, seq_name, "NULL" if dict_name is None else dict_name) ) getErrorExitCode( check_name=value_name, release_names=(seq_name, dict_name), emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateDictionaryCreationCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "dict_result", expression, emit, context ) as value_name: _getDictionaryCreationCode( to_name=value_name, pairs=expression.subnode_pairs, emit=emit, context=context, ) def _getDictionaryCreationCode(to_name, pairs, emit, context): # Detailed, and verbose code, pylint: disable=too-many-locals pairs_count = len(pairs) # Empty dictionaries should not get to this function, but be constant value instead. assert pairs_count > 0 # Unique per dictionary, they might be nested, but used for all of them. dict_key_name = context.allocateTempName("dict_key") dict_value_name = context.allocateTempName("dict_value") is_hashable_key = [pair.subnode_key.isKnownToBeHashable() for pair in pairs] # Does this dictionary build need an exception handling at all. if all(is_hashable_key): for pair in pairs[1:]: if pair.subnode_key.mayRaiseException(BaseException): needs_exception_exit = True break if pair.subnode_value.mayRaiseException(BaseException): needs_exception_exit = True break else: needs_exception_exit = False else: needs_exception_exit = True def generateValueCode(dict_value_name, pair): generateExpressionCode( to_name=dict_value_name, expression=pair.subnode_value, emit=emit, context=context, ) def generateKeyCode(dict_key_name, pair): generateExpressionCode( to_name=dict_key_name, expression=pair.subnode_key, emit=emit, context=context, ) def generatePairCode(pair): # Strange as it is, CPython 3.5 and before evaluated the key/value pairs # strictly in order, but for each pair, the value first. if python_version < 0x350: generateValueCode(dict_value_name, pair) generateKeyCode(dict_key_name, pair) else: generateKeyCode(dict_key_name, pair) generateValueCode(dict_value_name, pair) key_needs_release = context.needsCleanup(dict_key_name) if key_needs_release: context.removeCleanupTempName(dict_key_name) value_needs_release = context.needsCleanup(dict_value_name) if value_needs_release: context.removeCleanupTempName(dict_value_name) return key_needs_release, value_needs_release key_needs_release, value_needs_release = generatePairCode(pairs[0]) # Create dictionary presized. emit("%s = _PyDict_NewPresized( %d );" % (to_name, pairs_count)) with withCleanupFinally( "dict_build", to_name, needs_exception_exit, emit, context ) as guarded_emit: emit = guarded_emit.emit for count, pair in enumerate(pairs): if count > 0: key_needs_release, value_needs_release = generatePairCode(pair) needs_check = not is_hashable_key[count] res_name = context.getIntResName() emit( "%s = PyDict_SetItem(%s, %s, %s);" % (res_name, to_name, dict_key_name, dict_value_name) ) if value_needs_release: emit("Py_DECREF(%s);" % dict_value_name) if key_needs_release: emit("Py_DECREF(%s);" % dict_key_name) getErrorExitBoolCode( condition="%s != 0" % res_name, needs_check=needs_check, emit=emit, context=context, ) def generateDictOperationUpdateCode(statement, emit, context): value_arg_name = context.allocateTempName("dictupdate_value", unique=True) generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_value, emit=emit, context=context, ) dict_arg_name = context.allocateTempName("dictupdate_dict", unique=True) generateExpressionCode( to_name=dict_arg_name, expression=statement.subnode_dict_arg, emit=emit, context=context, ) with context.withCurrentSourceCodeReference(statement.getSourceReference()): res_name = context.getIntResName() emit("assert(PyDict_Check(%s));" % dict_arg_name) emit("%s = PyDict_Update(%s, %s);" % (res_name, dict_arg_name, value_arg_name)) getErrorExitBoolCode( condition="%s != 0" % res_name, release_names=(dict_arg_name, value_arg_name), needs_check=statement.mayRaiseException(BaseException), emit=emit, context=context, ) def generateDictOperationItemCode(to_name, expression, emit, context): dict_name, key_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "dict_value", expression, emit, context ) as value_name: emit( "%s = DICT_GET_ITEM_WITH_ERROR(%s, %s);" % (value_name, dict_name, key_name) ) getErrorExitCode( check_name=value_name, release_names=(dict_name, key_name), needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateDictOperationGet2Code(to_name, expression, emit, context): dict_name, key_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "dict_value", expression, emit, context ) as value_name: emit( renderTemplateFromString( r""" {% if expression.known_hashable_key %} %(value_name)s = DICT_GET_ITEM0(%(dict_name)s, %(key_name)s); if (%(value_name)s == NULL) { {% else %} %(value_name)s = DICT_GET_ITEM_WITH_HASH_ERROR0(%(dict_name)s, %(key_name)s); if (%(value_name)s == NULL && !ERROR_OCCURRED()) { {% endif %} %(value_name)s = Py_None; } """, expression=expression, ) % { "value_name": value_name, "dict_name": dict_name, "key_name": key_name, } ) getErrorExitCode( check_name=value_name, release_names=(dict_name, key_name), needs_check=not expression.known_hashable_key, emit=emit, context=context, ) def generateDictOperationGet3Code(to_name, expression, emit, context): dict_name, key_name, default_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # TODO: This code could actually make it dependent on default taking # a reference or not, and then use DICT_GET_ITEM0/DICT_GET_ITEM_WITH_HASH_ERROR0 if not. with withObjectCodeTemporaryAssignment( to_name, "dict_value", expression, emit, context ) as value_name: emit( renderTemplateFromString( r""" {% if expression.known_hashable_key %} %(value_name)s = DICT_GET_ITEM1(%(dict_name)s, %(key_name)s); if (%(value_name)s == NULL) { {% else %} %(value_name)s = DICT_GET_ITEM_WITH_HASH_ERROR1(%(dict_name)s, %(key_name)s); if (%(value_name)s == NULL && !ERROR_OCCURRED()) { {% endif %} %(value_name)s = %(default_name)s; Py_INCREF(%(value_name)s); } """, expression=expression, ) % { "value_name": value_name, "dict_name": dict_name, "key_name": key_name, "default_name": default_name, } ) getErrorExitCode( check_name=value_name, release_names=(dict_name, key_name, default_name), needs_check=not expression.known_hashable_key, emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateDictOperationSetdefault2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_SETDEFAULT2", arg_desc=makeArgDescFromExpression(expression), may_raise=not expression.known_hashable_key, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationSetdefault3Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_SETDEFAULT3", arg_desc=makeArgDescFromExpression(expression), may_raise=not expression.known_hashable_key, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationPop2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_POP2", arg_desc=makeArgDescFromExpression(expression), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationPop3Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_POP3", arg_desc=makeArgDescFromExpression(expression), may_raise=not expression.known_hashable_key, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationUpdate2Code(to_name, expression, emit, context): dict_name, iterable_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getIntResName() emit("assert(PyDict_Check(%s));" % dict_name) emit("%s = PyDict_Update(%s, %s);" % (res_name, dict_name, iterable_name)) getErrorExitBoolCode( condition="%s != 0" % res_name, release_names=(dict_name, iterable_name), needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) assignConstantNoneResult(to_name, emit, context) def generateDictOperationUpdate3Code(to_name, expression, emit, context): dict_name, iterable_name, pair_names = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getIntResName() emit("assert(PyDict_Check(%s));" % dict_name) if expression.subnode_iterable is not None: emit( renderTemplateFromString( r""" {% if has_keys_attribute == None %} if (HAS_ATTR_BOOL(%(iterable_name)s, const_str_plain_keys)){ %(res_name)s = PyDict_Merge(%(dict_name)s, %(iterable_name)s, 1); } else { %(res_name)s = PyDict_MergeFromSeq2(%(dict_name)s, %(iterable_name)s, 1); } {% elif has_keys_attribute == True %} %(res_name)s = PyDict_Merge(%(dict_name)s, %(iterable_name)s, 1); {% else %} %(res_name)s = PyDict_MergeFromSeq2(%(dict_name)s, %(iterable_name)s, 1); {% endif %} """, has_keys_attribute=expression.subnode_iterable.isKnownToHaveAttribute( "keys" ), ) % { "res_name": res_name, "dict_name": dict_name, "iterable_name": iterable_name, } ) getErrorExitBoolCode( condition="%s != 0" % res_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) for count, (pair_key_name, pair_key_value) in enumerate(pair_names): if python_version < 0x350: pair_key_name, pair_key_value = pair_key_value, pair_key_name emit( "%s = PyDict_SetItem(%s, %s, %s);" % (res_name, dict_name, pair_key_name, pair_key_value) ) getErrorExitBoolCode( condition="%s != 0" % res_name, needs_check=not expression.subnode_pairs[count].isKnownToBeHashable(), emit=emit, context=context, ) getReleaseCodes( release_names=(dict_name, iterable_name) + sum(pair_names, ()), emit=emit, context=context, ) assignConstantNoneResult(to_name, emit, context) def generateDictOperationCopyCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_COPY", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationClearCode(to_name, expression, emit, context): generateCAPIObjectCode0( to_name=None, capi="DICT_CLEAR", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) # None result if wanted. assignConstantNoneResult(to_name, emit, context) def generateDictOperationItemsCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_ITEMS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationIteritemsCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_ITERITEMS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationViewitemsCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_VIEWITEMS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationKeysCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_KEYS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationIterkeysCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_ITERKEYS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationViewkeysCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_VIEWKEYS", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationValuesCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_VALUES", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationItervaluesCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_ITERVALUES", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationViewvaluesCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="DICT_VIEWVALUES", arg_desc=(("dict_arg", expression.subnode_dict_arg),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateDictOperationInCode(to_name, expression, emit, context): inverted = expression.isExpressionDictOperationNotIn() dict_name, key_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # Reverse child order. if expression.isExpressionDictOperationHaskey(): dict_name, key_name = key_name, dict_name res_name = context.getIntResName() emit("%s = DICT_HAS_ITEM(%s, %s);" % (res_name, key_name, dict_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(dict_name, key_name), needs_check=expression.known_hashable_key is not True, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s %s 0" % (res_name, "==" if inverted else "!="), emit=emit, ) def generateDictOperationSetCode(statement, emit, context): value_arg_name = context.allocateTempName("dictset_value", unique=True) generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_value, emit=emit, context=context, ) dict_arg_name = context.allocateTempName("dictset_dict", unique=True) generateExpressionCode( to_name=dict_arg_name, expression=statement.subnode_dict_arg, emit=emit, context=context, ) key_arg_name = context.allocateTempName("dictset_key", unique=True) generateExpressionCode( to_name=key_arg_name, expression=statement.subnode_key, emit=emit, context=context, ) context.setCurrentSourceCodeReference(statement.getSourceReference()) res_name = context.getIntResName() emit( "%s = PyDict_SetItem(%s, %s, %s);" % (res_name, dict_arg_name, key_arg_name, value_arg_name) ) getErrorExitBoolCode( condition="%s != 0" % res_name, release_names=(value_arg_name, dict_arg_name, key_arg_name), emit=emit, needs_check=not statement.subnode_key.isKnownToBeHashable(), context=context, ) def generateDictOperationSetCodeKeyValue(statement, emit, context): key_arg_name = context.allocateTempName("dictset38_key") generateExpressionCode( to_name=key_arg_name, expression=statement.subnode_key, emit=emit, context=context, ) value_arg_name = context.allocateTempName("dictset38_value") generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_value, emit=emit, context=context, ) dict_arg_name = context.allocateTempName("dictset38_dict") generateExpressionCode( to_name=dict_arg_name, expression=statement.subnode_dict_arg, emit=emit, context=context, ) context.setCurrentSourceCodeReference(statement.getSourceReference()) res_name = context.getIntResName() emit( "%s = PyDict_SetItem(%s, %s, %s);" % (res_name, dict_arg_name, key_arg_name, value_arg_name) ) getErrorExitBoolCode( condition="%s != 0" % res_name, release_names=(value_arg_name, dict_arg_name, key_arg_name), emit=emit, needs_check=not statement.subnode_key.isKnownToBeHashable(), context=context, ) def generateDictOperationRemoveCode(statement, emit, context): dict_arg_name = context.allocateTempName("dictdel_dict", unique=True) generateExpressionCode( to_name=dict_arg_name, expression=statement.subnode_dict_arg, emit=emit, context=context, ) key_arg_name = context.allocateTempName("dictdel_key", unique=True) generateExpressionCode( to_name=key_arg_name, expression=statement.subnode_key, emit=emit, context=context, ) with context.withCurrentSourceCodeReference( statement.subnode_key.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): res_name = context.getBoolResName() emit("%s = DICT_REMOVE_ITEM(%s, %s);" % (res_name, dict_arg_name, key_arg_name)) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(dict_arg_name, key_arg_name), needs_check=statement.mayRaiseException(BaseException), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/LocalsDictCodes.py0000600000372100037210000002270214166627112026542 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for locals dict handling. These are variable handling for classes and partially also Python2 exec statements. """ from .CodeHelpers import ( generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .Emission import SourceCodeCollector from .ErrorCodes import ( getErrorExitBoolCode, getErrorExitCode, getNameReferenceErrorCode, ) from .Indentation import indented from .PythonAPICodes import getReferenceExportCode from .templates.CodeTemplatesVariables import ( template_read_locals_dict_with_fallback, template_read_locals_dict_without_fallback, template_read_locals_mapping_with_fallback, template_read_locals_mapping_without_fallback, ) def generateSetLocalsDictCode(statement, emit, context): new_locals_name = context.allocateTempName("set_locals") generateExpressionCode( to_name=new_locals_name, expression=statement.subnode_new_locals, emit=emit, context=context, ) locals_declaration = context.addLocalsDictName( statement.getLocalsScope().getCodeName() ) emit( """\ %(locals_dict)s = %(locals_value)s;""" % {"locals_dict": locals_declaration, "locals_value": new_locals_name} ) getReferenceExportCode(new_locals_name, emit, context) if context.needsCleanup(new_locals_name): context.removeCleanupTempName(new_locals_name) def generateReleaseLocalsDictCode(statement, emit, context): locals_declaration = context.addLocalsDictName( statement.getLocalsScope().getCodeName() ) emit( """\ Py_DECREF(%(locals_dict)s); %(locals_dict)s = NULL;""" % {"locals_dict": locals_declaration} ) def generateLocalsDictSetCode(statement, emit, context): value_arg_name = context.allocateTempName("dictset_value", unique=True) generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_source, emit=emit, context=context, ) context.setCurrentSourceCodeReference(statement.getSourceReference()) locals_scope = statement.getLocalsDictScope() locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) is_dict = locals_scope.hasShapeDictionaryExact() res_name = context.getIntResName() if is_dict: emit( "%s = PyDict_SetItem(%s, %s, %s);" % ( res_name, locals_declaration, context.getConstantCode(statement.getVariableName()), value_arg_name, ) ) else: emit( "%s = PyObject_SetItem(%s, %s, %s);" % ( res_name, locals_declaration, context.getConstantCode(statement.getVariableName()), value_arg_name, ) ) getErrorExitBoolCode( condition="%s != 0" % res_name, release_name=value_arg_name, needs_check=statement.mayRaiseException(BaseException), emit=emit, context=context, ) def generateLocalsDictDelCode(statement, emit, context): locals_scope = statement.getLocalsDictScope() dict_arg_name = locals_scope.getCodeName() is_dict = locals_scope.hasShapeDictionaryExact() context.setCurrentSourceCodeReference(statement.getSourceReference()) if is_dict: res_name = context.getBoolResName() emit( "%s = DICT_REMOVE_ITEM(%s, %s);" % ( res_name, dict_arg_name, context.getConstantCode(statement.getVariableName()), ) ) getErrorExitBoolCode( condition="%s == false" % res_name, needs_check=statement.mayRaiseException(BaseException), emit=emit, context=context, ) else: res_name = context.getIntResName() emit( "%s = PyObject_DelItem(%s, %s);" % ( res_name, dict_arg_name, context.getConstantCode(statement.getVariableName()), ) ) getErrorExitBoolCode( condition="%s == -1" % res_name, needs_check=statement.mayRaiseException(BaseException), emit=emit, context=context, ) def generateLocalsDictVariableRefOrFallbackCode(to_name, expression, emit, context): variable_name = expression.getVariableName() fallback_emit = SourceCodeCollector() with withObjectCodeTemporaryAssignment( to_name, "locals_lookup_value", expression, emit, context ) as value_name: generateExpressionCode( to_name=value_name, expression=expression.subnode_fallback, emit=fallback_emit, context=context, ) locals_scope = expression.getLocalsDictScope() locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) is_dict = locals_scope.hasShapeDictionaryExact() assert not context.needsCleanup(value_name) if is_dict: template = template_read_locals_dict_with_fallback fallback_codes = indented(fallback_emit.codes) emit( template % { "to_name": value_name, "locals_dict": locals_declaration, "fallback": fallback_codes, "var_name": context.getConstantCode(constant=variable_name), } ) else: template = template_read_locals_mapping_with_fallback fallback_codes = indented(fallback_emit.codes, 2) emit( template % { "to_name": value_name, "locals_dict": locals_declaration, "fallback": fallback_codes, "var_name": context.getConstantCode(constant=variable_name), "exception_exit": context.getExceptionEscape(), } ) # If the fallback took no reference, then make it do it # anyway. context.addCleanupTempName(value_name) def generateLocalsDictVariableRefCode(to_name, expression, emit, context): variable_name = expression.getVariableName() locals_scope = expression.getLocalsDictScope() locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) is_dict = locals_scope.hasShapeDictionaryExact() if is_dict: template = template_read_locals_dict_without_fallback else: template = template_read_locals_mapping_without_fallback with withObjectCodeTemporaryAssignment( to_name, "locals_lookup_value", expression, emit, context ) as value_name: emit( template % { "to_name": value_name, "locals_dict": locals_declaration, "var_name": context.getConstantCode(constant=variable_name), } ) getNameReferenceErrorCode( variable_name=variable_name, condition="%s == NULL && CHECK_AND_CLEAR_KEY_ERROR_OCCURRED()" % value_name, emit=emit, context=context, ) getErrorExitCode(check_name=value_name, emit=emit, context=context) if not is_dict: context.addCleanupTempName(value_name) def generateLocalsDictVariableCheckCode(to_name, expression, emit, context): variable_name = expression.getVariableName() locals_scope = expression.getLocalsDictScope() locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) is_dict = locals_scope.hasShapeDictionaryExact() if is_dict: to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="DICT_HAS_ITEM(%(locals_dict)s, %(var_name)s) == 1" % { "locals_dict": locals_declaration, "var_name": context.getConstantCode(constant=variable_name), }, emit=emit, ) else: tmp_name = context.getIntResName() template = """\ %(tmp_name)s = MAPPING_HAS_ITEM(%(locals_dict)s, %(var_name)s); """ emit( template % { "locals_dict": locals_declaration, "var_name": context.getConstantCode(constant=variable_name), "tmp_name": tmp_name, } ) getErrorExitBoolCode( condition="%s == -1" % tmp_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s == 1" % tmp_name, emit=emit ) Nuitka-0.6.19.1/nuitka/codegen/templates_c/0000700000372100037210000000000014167275622025472 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonTuple.c.j20000600000372100037210000000742414166627112034320 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); {# Shortcut for equality, driven by length check. #} {% if operand in ("==", "!=") %} if (len_a != len_b) { {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } {% endif %} {# Find the first non-identical object. #} {% if operand not in ("==", "!=") %} bool found = false; {% endif %} nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return {{target.getExceptionResultIndicatorValue()}}; } if (res == NUITKA_BOOL_FALSE) { {% if operand not in ("==", "!=") %} found = true; {% endif %} break; } } {# If size mismatches, but all is equal at the start, compare sizes to order tuples. #} {% if operand not in ("==", "!=") %} if (found == false) { bool r = len_a {{operand}} len_b; // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } return RICH_COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); {% else %} {% if operand == "==" %} bool r = res == NUITKA_BOOL_TRUE; {% else %} bool r = res == NUITKA_BOOL_FALSE; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonInt.c.j20000600000372100037210000000410614166627112033753 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} {# This is supposed to be Python2 code #} const long a = {{left.getAsLongValueExpression("operand1")}}; const long b = {{right.getAsLongValueExpression("operand2")}}; bool r = a {{operand}} b; // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsTuple.c.j20000600000372100037210000000565014166627112031430 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro tuple_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% if nb_slot == "nb_add" %} {% if left.type_name == "tuple" == right.type_name %} PyObject *x = TUPLE_CONCAT({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *x = {{ left.getSlotCallExpression("sq_concat", "PyTuple_Type.tp_as_sequence->sq_concat", operand1, operand2) }}; {% endif %} {% elif nb_slot == "nb_multiply" %} PyObject *x = {{ left.getSlotCallExpression("sq_repeat", "PyTuple_Type.tp_as_sequence->sq_repeat", operand1, operand2) }}; {% else %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyTuple_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; {% endif %} assert(x != Py_NotImplemented); {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsStr.c.j20000600000372100037210000000571414166627112031110 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro str_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% if nb_slot == "nb_add" %} PyObject *x = {{ left.getSlotCallExpression("sq_concat", "PyString_Type.tp_as_sequence->sq_concat", operand1, operand2) }}; assert(x != Py_NotImplemented); {% elif nb_slot == "nb_multiply" %} PyObject *x = {{ left.getSlotCallExpression("sq_repeat", "PyString_Type.tp_as_sequence->sq_repeat", operand1, operand2) }}; assert(x != Py_NotImplemented); {% elif nb_slot == "nb_remainder" %} PyObject *x = PyString_Format({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyString_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; assert(x != Py_NotImplemented); {% endif %} {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsBytes.c.j20000600000372100037210000000543314166627112031424 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro bytes_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% if nb_slot == "nb_add" %} PyObject *x = {{ left.getSlotCallExpression("sq_concat", "PyBytes_Type.tp_as_sequence->sq_concat", operand1, operand2) }}; {% elif nb_slot == "nb_multiply" %} PyObject *x = {{ left.getSlotCallExpression("sq_repeat", "PyBytes_Type.tp_as_sequence->sq_repeat", operand1, operand2) }}; {% else %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyBytes_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; {% endif %} assert(x != Py_NotImplemented); {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperBuiltinMethodOperation.c.j20000600000372100037210000000417714166627112033745 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} PyObject *{{builtin_type.type_name.upper()}}_{{method_name.upper()}}{{api_suffix}}({{builtin_type.getVariableDecl(builtin_arg_name)}} {{formatArgumentDeclaration(arg_types, arg_names, starting=False)}}) { {{builtin_type.getCheckValueCode(builtin_arg_name)}} {% for arg_type, arg_name in zip(arg_types, arg_names) %} {{arg_type.getCheckValueCode(arg_name)}} {% endfor %} {% if len(arg_names) > 0 %} PyObject *args[{{len(arg_names)+1}}] = { {{builtin_arg_name}}, {{",".join(arg_names)}} }; return CALL_METHODDESCR_WITH_ARGS{{len(arg_names)+1}}({{builtin_type.type_name}}_builtin_{{method_name}}, args); {% else %} return CALL_METHODDESCR_WITH_SINGLE_ARG({{builtin_type.type_name}}_builtin_{{method_name}}, {{builtin_arg_name}}); {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/CodeTemplateCallsPositionalMethodDescr.c.j20000600000372100037210000001203314166627112035654 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperObjectTools.c.j2' import CHECK_OBJECTS %} {% if args_count == 1 %} PyObject *CALL_METHODDESCR_WITH_SINGLE_ARG(PyObject *called, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. {% else %} PyObject *CALL_METHODDESCR_WITH_ARGS{{args_count}}(PyObject *called, PyObject *const *args) { {% endif %} CHECK_OBJECT(called); {{ CHECK_OBJECTS(args, args_count) }} #if PYTHON_VERSION >= 0x380 assert (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)); vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); assert(func != NULL); {% if args_count == 0 %} PyObject *result = func(called, NULL, 0, NULL); {% else %} PyObject *result = func(called, args, {{args_count}}, NULL); {% endif %} return Nuitka_CheckFunctionResult(result); #else PyMethodDescrObject *called_descr = (PyMethodDescrObject *)called; PyMethodDef *method_def = called_descr->d_method; // Try to be fast about wrapping the arguments. int flags = method_def->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if ({{ unlikely_or_likely_from(args_count != 1) }}(flags & METH_NOARGS)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, NULL); return Nuitka_CheckFunctionResult(result); } else if ({{ unlikely_if(args_count != 1) }}(flags & METH_O)) { {% if args_count == 2 %} PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, args[1]); return Nuitka_CheckFunctionResult(result); {% else %} SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument ({{args_count}} given)", method_def->ml_name ); return NULL; {% endif %} } else if (flags & METH_VARARGS) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args+1, {{args_count-1}}); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS|METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args+1, {{args_count-1}}); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args+1, {{args_count-1}}, NULL); #else PyObject *pos_args = MAKE_TUPLE(args+1, {{args_count-1}}); result = (*(_PyCFunctionFast)method)(self, &pos_args, {{args_count}}); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args+1, {{args_count-1}}); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif return Nuitka_CheckFunctionResult(result); } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif {# TODO: How come the PyCFunction call does not cover all cases, that should be doable. #} {% if args_count == 0 %} PyObject *result = CALL_FUNCTION(called, const_tuple_empty, NULL); {% else %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); {% endif %} return result; #endif } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperImportHard.c.j20000600000372100037210000000331114166627112031353 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {{target.getTypeDecl()}} IMPORT_HARD_{{module_name.upper()}}(void) { static PyObject *module_{{module_name}} = NULL; if (module_{{module_name}} == NULL) { module_{{module_name}} = PyImport_ImportModule("{{module_name}}"); } CHECK_OBJECT(module_{{module_name}}); return module_{{module_name}}; } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsCommon.c.j20000600000372100037210000000706314166627112031567 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {# This contains macros that are used for all slot helper macros #} {% macro goto_exit(props, target, result, qual="all") %} {% if target.endswith(("_exception", "_left", "_right")) or "_const_" in target or target == "exit_result_ok" %} {% elif target.endswith("_cbool") %} cbool_result = {{ result }}; {% elif target.endswith("_nbool") %} nbool_result = {{ result }}; {% elif target.endswith("_clong") %} clong_result = {{ result }}; {% elif target.endswith("_cfloat") %} cfloat_result = {{ result }}; {% elif target.endswith("_object") %} obj_result = {{ result }}; {% else %} #error Cannot derive result variable from {{target}} {% endif %} goto {{ target }}; {% if target not in props.get("exits") %} {% do props.get("exits").update({target: []}) %} {% endif %} {% do props.get("exits").get(target).append(qual) %} {% endmacro %} {% macro constant_float_exit_target(props, target, result, left, operand1, label, constant_value, exit_result_ok) %} {{label}}: {% if target %} {{ target.getAssignFromFloatConstantCode(result, constant_value) }} {% else %} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignFromFloatConstantCode(operand1, constant_value) }} {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} {% macro constant_int_exit_target(props, target, result, left, operand1, label, constant_value, exit_result_ok) %} {{label}}: {% if target %} {{ target.getAssignFromIntConstantCode(result, constant_value) }} {% else %} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignFromIntConstantCode(operand1, constant_value) }} {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} {% macro constant_long_exit_target(props, target, result, left, operand1, label, constant_value, exit_result_ok) %} {{label}}: {% if target %} {{ target.getAssignFromLongConstantCode(result, constant_value) }} {% else %} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignFromLongConstantCode(operand1, constant_value) }} {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonStr.c.j20000600000372100037210000001030414166627112033766 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { {% if operand in ("==", ">=", "<=") %} bool r = true; {% else %} bool r = false; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); {% if operand in ("==", "!=") %} if (len_a != len_b) { {# Shortcut for equality/inequality, driven by length divergence. #} {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { {% if operand == "==" %} bool r = true; {% else %} bool r = false; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } else { {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } } {% else %} Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c==0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } {% if operand == "<" %} c = c < 0; {% elif operand == "<=" %} c = c <= 0; {% elif operand == ">" %} c = c > 0; {% elif operand == ">=" %} c = c >= 0; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("c != 0")}}; {{target.getTakeReferenceStatement("result")}} return result; {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonUnicode.c.j20000600000372100037210000001060714166627112034612 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { {% if operand in ("==", ">=", "<=") %} bool r = true; {% else %} bool r = false; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } {% if operand in ("==", "!=") %} #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r == " + ("true" if operand == "==" else "false"))}}; {{target.getTakeReferenceStatement("result")}} return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r == " + ("true" if operand == "==" else "false"))}}; {{target.getTakeReferenceStatement("result")}} return result; #endif {% else %} {# TODO: Make these specialized for Python versions, if only because we have no way of going to C bool quickly otherwise #} PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_{{op_code}}); CHECK_OBJECT(r); {% if target.type_name == "object" %} return r; {% else %} // Convert to target type if necessary {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r == Py_True")}}; Py_DECREF(r); {{target.getTakeReferenceStatement("result")}} return result; {% endif %} {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonList.c.j20000600000372100037210000000753514166627112034145 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} {# TODO: Unify with tuple, seems the iteration part is only difference #} PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); {# Shortcut for equality, driven by length check. #} {% if operand in ("==", "!=") %} if (len_a != len_b) { {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } {% endif %} {# Find the first non-identical object. #} {% if operand not in ("==", "!=") %} bool found = false; {% endif %} nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return {{target.getExceptionResultIndicatorValue()}}; } if (res == NUITKA_BOOL_FALSE) { {% if operand not in ("==", "!=") %} found = true; {% endif %} break; } } {# If size mismatches, but all is equal at the start, compare sizes to order lists. #} {% if operand not in ("==", "!=") %} if (found == false) { bool r = len_a {{operand}} len_b; // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } return RICH_COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); {% else %} {% if operand == "==" %} bool r = res == NUITKA_BOOL_TRUE; {% else %} bool r = res == NUITKA_BOOL_FALSE; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparison.c.j20000600000372100037210000002700714166627112033305 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {{target.getTypeDecl()}} RICH_COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {# Divert to more special implementation immediately if possible. #} {% if left.getSameTypeComparisonSpecializationCode(right, op_code, target, "operand1", "operand2") %} {% if left != right %} if ({{left.getTypeValueExpression("operand1")}} == {{right.getTypeValueExpression("operand2")}}) { {{left.getSameTypeComparisonSpecializationCode(right, op_code, target, "operand1", "operand2")}} } {% else %} {{left.getSameTypeComparisonSpecializationCode(right, op_code, target, "operand1", "operand2")}} {% endif %} {% endif %} {# For non-identical types, or for "OBJECT_OBJECT", do the full work. #} {% if left != right or left.type_name == "object" %} {# CPython2 treats integer values with fast path. #} {% if left.type_name == "object" == right.type_name %} #if PYTHON_VERSION < 0x300 if ({{left.getIntCheckExpression("operand1")}} && {{right.getIntCheckExpression("operand2")}}) { return COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_INT_INT(operand1, operand2); } #endif {% endif %} {% if op_code in ("EQ", "GE", "LE", "NE") and left.type_name == "object" and right.type_name == "object" %} // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && {{left.getMostSpecificType(right).getSaneTypeCheckCode("operand1")}}) { bool r = {% if op_code == "NE" %} false {% else %} true {%endif %}; {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } {% endif %} #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return {{target.getExceptionResultIndicatorValue()}}; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return {{target.getExceptionResultIndicatorValue()}}; } #endif PyTypeObject *type1 = {{left.getTypeValueExpression("operand1")}}; PyTypeObject *type2 = {{right.getTypeValueExpression("operand2")}}; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if ({{left.getTypeIdenticalCheckExpression(right, "type1", "type2")}} && !{{left.getMostSpecificType(right).getInstanceCheckCode("operand1")}} ) { {% if left.getMostSpecificType(right) == left %} richcmpfunc frich = {{left.getSlotValueExpression("type1", "tp_richcompare")}}; {% else %} richcmpfunc frich = {{right.getSlotValueExpression("type2", "tp_richcompare")}}; {% endif %} if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_{{op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. {% if left.getMostSpecificType(right) == left %} cmpfunc fcmp = {{left.getSlotValueExpression("type1", "tp_compare")}}; {% else %} cmpfunc fcmp = {{right.getSlotValueExpression("type2", "tp_compare")}}; {% endif %} if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return {{target.getExceptionResultIndicatorValue()}}; } switch(Py_{{op_code}}) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && {{left.getRealSubTypeCheckCode(right, "type2", "type1")}}) { f = {{right.getSlotValueExpression("type2", "tp_richcompare")}}; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_{{reversed_args_op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } } f = {{left.getSlotValueExpression("type1", "tp_richcompare")}}; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_{{op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } f = {{right.getSlotValueExpression("type2", "tp_richcompare")}}; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_{{reversed_args_op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } int c; if ({{left.getInstanceCheckCode("operand1")}}) { c = (*type1->tp_compare)(operand1, operand2); } else if ({{right.getInstanceCheckCode("operand2")}}) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return {{target.getExceptionResultIndicatorValue()}}; } switch(Py_{{op_code}}) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = {{right.getSlotValueExpression("type2", "tp_richcompare")}}; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_{{reversed_args_op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } } f = {{left.getSlotValueExpression("type1", "tp_richcompare")}}; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_{{op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } if (checked_reverse_op == false) { f = {{right.getSlotValueExpression("type2", "tp_richcompare")}}; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_{{reversed_args_op_code}}); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); {{ target.getReturnFromObjectExpressionCode("result") }} } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch(Py_{{op_code}}) { case Py_EQ: { bool r = operand1 == operand2; {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } case Py_NE: { bool r = operand1 != operand2; {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } default: {{target.getReturnUnorderableTypeErrorCode(operator, left, right, "type1", "type2")}} } #endif {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationInplace.c.j20000600000372100037210000002601614166627112032545 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% from 'HelperSlotsBinary.c.j2' import binary_operation, call_binary_slot with context %} {% macro inplace_fallback_operation(props, left, right, type1, type2) %} #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif {% if left == object_desc or left.hasSlot(nb_islot) %} {{ left.getSlotType(nb_islot)}} islot = {{left.getSlotValueExpression("type1", nb_islot) }}; if (islot != NULL) { PyObject *x = {{ left.getSlotCallExpression(nb_islot, "islot", "*operand1", "operand2") }}; if (x != Py_NotImplemented) { {{ goto_exit(props, "exit_inplace_result_object", "x") }} } Py_DECREF(x); } {% else %} // No inplace number slot {{ nb_islot }} available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->{{ nb_islot }} == NULL); {% endif %} { {{ binary_operation(props, operator, nb_slot, left, right, "type1", "type2", "*operand1", "operand2", "exit_inplace_result_object", "exit_inplace_result_cbool_ok", "exit_inplace_result_nbool", "exit_inplace_exception") }} } {% if "exit_inplace_result_object" in props["exits"] %} exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; {% endif %} {% if "exit_inplace_exception" in props["exits"] %} {% if "all" not in props["exits"]["exit_inplace_exception"] %} #if PYTHON_VERSION < 0x300 {% endif %} exit_inplace_exception: return false; {% if "all" not in props["exits"]["exit_inplace_exception"] %} #endif {% endif %} {% endif %} {% endmacro %} {% if not left.hasTypeSpecializationCode(right, nb_slot, sq_slot) and left.getSameTypeType(right).hasSameTypeOperationSpecializationCode(right.getSameTypeType(left), nb_slot, sq_slot) %} static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_{{op_code}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}_INPLACE({{left.getVariableDecl("*operand1")}}, {{right.getVariableDecl("operand2")}}) { {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("*operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; {{ inplace_fallback_operation(props, left, right, "type1", "type2") }} } {% endif %} static inline bool _BINARY_OPERATION_{{op_code}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}_INPLACE({{left.getVariableDecl("*operand1")}}, {{right.getVariableDecl("operand2")}}) { assert(operand1); // Pointer must be non-null. {{ left.getCheckValueCode("*operand1") }} {{ right.getCheckValueCode("operand2") }} {% if left.type_name == "object" and right.type_name == "object" %} {# CPython2 treats integer values with fast path. #} #if PYTHON_VERSION < 0x300 if ({{ left.getIntCheckExpression("*operand1") }} && {{ right.getIntCheckExpression("operand2") }}) { {% from 'HelperSlotsInt.c.j2' import int_slot %} {% set props = {"exits": {}} %} {{ int_slot(props, operator, nb_slot, None, int_desc, int_desc, "result", "*operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return true; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return false; {% endif %} } #endif {% endif %} if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. {% if operator == "+" and left.mayBothHaveType(right, "str") %} #if PYTHON_VERSION < 0x300 if ({{left.getStringCheckExpression("*operand1")}} && !PyString_CHECK_INTERNED(*operand1) && {{right.getStringCheckExpression("operand2")}}) { return STRING_ADD_INPLACE(operand1, operand2); } #endif {% endif %} {% if operator == "+" and left.mayBothHaveType(right, "unicode") %} #if PYTHON_VERSION >= 0x300 if ({{ left.getUnicodeCheckExpression("*operand1")}} && !PyUnicode_CHECK_INTERNED(*operand1) && {{right.getUnicodeCheckExpression("operand2") }}) { return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif {% endif %} {% if operator == "+" and left.hasOneOrBothType(right, "bytes") %} #if PYTHON_VERSION >= 0x300 if ({{ left.getBytesCheckExpression("*operand1")}} && {{right.getBytesCheckExpression("operand2") }}) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } #endif {% endif %} } {% if left == object_desc and right == object_desc %} {# Floats are very good for in-place operations. #} if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { {% if float_desc.hasTypeSpecializationCode(float_desc, nb_slot, sq_slot) %} if ({{left.getFloatCheckExpression("operand2")}}) { return _BINARY_OPERATION_{{op_code}}_{{float_desc.getHelperCodeName()}}_{{float_desc.getHelperCodeName()}}_INPLACE(operand1, operand2); } {% endif %} {% if long_desc.hasTypeSpecializationCode(long_desc, nb_slot, sq_slot) %} #if PYTHON_VERSION >= 0x300 if ({{left.getLongCheckExpression("operand2")}}) { return _BINARY_OPERATION_{{op_code}}_{{long_desc.getHelperCodeName()}}_{{long_desc.getHelperCodeName()}}_INPLACE(operand1, operand2); } #endif {% endif %} } {% endif %} {% if operator == "+" and left == right and left in (object_desc, str_desc) %} {# Fast path for Python2 str values, very important for performance. #} #if PYTHON_VERSION < 0x300 // Python2 strings are to be treated differently, fall back to Python API here. if ({{ left.getStringCheckExpression("*operand1")}} && {{right.getStringCheckExpression("operand2") }}) { {# This could be inlined too, but it has some detail behind it. #} PyString_Concat(operand1, operand2); return !ERROR_OCCURRED(); } #endif {% endif %} {% if operator == "+" and left == right and right == object_desc %} {# Fast path for Python3 str values, very important for performance. #} #if PYTHON_VERSION >= 0x300 // Python3 Strings are to be treated differently. if ({{ left.getUnicodeCheckExpression("*operand1")}} && {{right.getUnicodeCheckExpression("operand2") }}) { PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } #endif {% endif %} {# Fast path for list in-place add with at least one known list. #} {% if operator == "+" and left.hasOneOrBothType(right, "list") %} if ({{ left.getListCheckExpression("*operand1")}} && {{ right.getListCheckExpression("operand2") }}) { return LIST_EXTEND_FROM_LIST(*operand1, operand2); } {% endif %} {# TODO: No special function for tuple += tuple yet. #} {# Fast path for sequences in-place add with at least one known sequence type. #} {% if operator == "+" and left.type_name in ("list", "tuple") and right.type_name in ("list", "tuple", "object") %} if ({{ left.getSequenceCheckExpression("*operand1", right)}} && {{ right.getSequenceCheckExpression("operand2", left) }}) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } {% endif %} {% if left.hasTypeSpecializationCode(right, nb_slot, sq_slot) %} {% set props = {"exits": {}} %} {{ call_binary_slot(props, operator, nb_slot, nb_islot, left, right, "result", "*operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return true; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return false; {% endif %} {% elif left.getSameTypeType(right).hasSameTypeOperationSpecializationCode(right.getSameTypeType(left), nb_slot, sq_slot) %} {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("*operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; if ({{ left.getTypeIdenticalCheckExpression(right, "type1", "type2") }}) { assert(type1 == type2); {# There is special code for same types. #} // return _BINARY_OPERATION_{{op_code}}_{{left.getSameTypeType(right).getHelperCodeName()}}_{{right.getSameTypeType(left).getHelperCodeName()}}_INPLACE(operand1, operand2); {{ call_binary_slot(props, operator, nb_slot, nb_islot, left.getSameTypeType(right), right.getSameTypeType(left), "result", "*operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return true; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return false; {% endif %} } return __BINARY_OPERATION_{{op_code}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}_INPLACE(operand1, operand2); {% else %} {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("*operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; {{ inplace_fallback_operation(props, left, right, "type1", "type2") }} {% endif %} } bool BINARY_OPERATION_{{op_code}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}_INPLACE({{left.getVariableDecl("*operand1")}}, {{right.getVariableDecl("operand2")}}) { return _BINARY_OPERATION_{{op_code}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/codegen/templates_c/CodeTemplateCallsMixed.c.j20000600000372100037210000001325314166627112032464 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperObjectTools.c.j2' import CHECK_OBJECTS %} {% if not has_dict_values %} PyObject *CALL_FUNCTION_WITH_ARGS{{args_count}}_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { {% elif args_count == 0 and has_dict_values %} PyObject *CALL_FUNCTION_WITH_NO_ARGS_KWSPLIT(PyObject *called, PyObject *const *kw_values, PyObject *kw_names) { {% elif not has_tuple_arg %} PyObject *CALL_FUNCTION_WITH_ARGS{{args_count}}_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { {% else %} PyObject *CALL_FUNCTION_WITH_POSARGS{{args_count}}_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); {% endif %} {{ CHECK_OBJECTS(args, args_count) }} CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); {# The dict values might be joined and separately, check them too. #} {% if has_dict_values %} CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); {% else %} CHECK_OBJECTS(&args[{{args_count}}], nkwargs); {% endif %} if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; {% if args_count == 0 %} {# TODO: Add more specialized entry point for KwSplit only. #} PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, NULL, {{args_count}}, kw_values, kw_names); {% elif not has_dict_values %} PyObject *result = Nuitka_CallFunctionVectorcall(function, args, {{args_count}}, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); {% else %} PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, {{args_count}}, kw_values, kw_names); {% endif %} Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { {% if args_count == 0 %} PyObject *result = func(called, kw_values, 0, kw_names); {% elif not has_dict_values %} PyObject *result = func(called, args, {{args_count}}, kw_names); {% else %} NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, {{args_count}} + nkwargs); memcpy(vectorcall_args, args, {{args_count}}*sizeof(PyObject *)); memcpy(&vectorcall_args[{{args_count}}], kw_values, nkwargs*sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, {{args_count}}, kw_names); {% endif %} return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } {% if args_count == 0 %} PyObject *pos_args = const_tuple_empty; {% elif not has_tuple_arg or not has_dict_values %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% endif %} PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); {% if not has_dict_values %} PyObject *value = args[{{args_count}}+i]; {% else %} PyObject *value = kw_values[i]; {% endif %} CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); {% if args_count != 0 and not has_tuple_arg %} Py_DECREF(pos_args); {% endif %} Py_DECREF(named_args); {% if args_count != 0 %} CHECK_OBJECTS(args, {{args_count}}); {% endif %} {% if has_dict_values %} CHECK_OBJECTS(kw_values, nkwargs); {% endif %} Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperObjectTools.c.j20000600000372100037210000000301014166627112031525 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% macro CHECK_OBJECTS(args, args_count) %} {% if args_count != 0 %} CHECK_OBJECTS(args, {{args_count}}); {% endif %} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/CodeTemplateCallsMethodPositional.c.j20000600000372100037210000002576014166627112034706 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperObjectTools.c.j2' import CHECK_OBJECTS %} {% macro call_function_with_args(called, args, args_count) %} {% if args_count == 0 %} CALL_FUNCTION_NO_ARGS({{ called }}) {% elif args_count == 1 %} CALL_FUNCTION_WITH_SINGLE_ARG({{ called }}, {{ args }}[0]) {% else %} CALL_FUNCTION_WITH_ARGS{{args_count}}({{ called }}, {{args}}) {% endif %} {% endmacro %} {% if args_count == 0 %} PyObject *CALL_METHOD_NO_ARGS(PyObject *source, PyObject *attr_name) { {% elif args_count == 1 %} PyObject *CALL_METHOD_WITH_SINGLE_ARG(PyObject *source, PyObject *attr_name, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. {% else %} PyObject *CALL_METHOD_WITH_ARGS{{args_count}}(PyObject *source, PyObject *attr_name, PyObject *const *args) { {% endif %} CHECK_OBJECT(source); CHECK_OBJECT(attr_name); {{ CHECK_OBJECTS(args, args_count) }} PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = {{ call_function_with_args( "called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **) ((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = {{ call_function_with_args( "called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { {% if args_count != 0 %} PyObject *result = Nuitka_CallMethodFunctionPosArgs( (struct Nuitka_FunctionObject const *)descr, source, args, {{ args_count }} ); {% else %} PyObject *result = Nuitka_CallMethodFunctionNoArgs( (struct Nuitka_FunctionObject const *)descr, source ); {% endif %} Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = {{ call_function_with_args( "called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = {{ call_function_with_args( "descr", "args", args_count) }}; Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2( PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name) ); #else PyErr_Format( PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name ); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE( (PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name ); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return {{ call_function_with_args( "called_object", "args", args_count) }}; } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS( source_instance->in_class, attr_name ); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { {% if args_count != 0 %} return Nuitka_CallMethodFunctionPosArgs( (struct Nuitka_FunctionObject const *)called_object, source, args, {{ args_count }} ); {% else %} return Nuitka_CallMethodFunctionNoArgs( (struct Nuitka_FunctionObject const *)called_object, source ); {% endif %} } else if (descr_get != NULL) { PyObject *method = descr_get( called_object, source, (PyObject *)source_instance->in_class ); if (unlikely(method == NULL)) { return NULL; } PyObject *result = {{ call_function_with_args( "method", "args", args_count) }}; Py_DECREF(method); return result; } else { return {{ call_function_with_args( "called_object", "args", args_count) }}; } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2( PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name) ); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = { source, attr_name }; called_object = CALL_FUNCTION_WITH_ARGS2( source_instance->in_class->cl_getattr, args2 ); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = {{ call_function_with_args( "called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = {{ call_function_with_args("called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } } PyObject *result = {{ call_function_with_args("descr", "args", args_count) }}; Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)( source, (char *)Nuitka_String_AsString_Unchecked(attr_name) ); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = {{ call_function_with_args( "called_object", "args", args_count) }}; Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2( PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name) ); return NULL; } } Nuitka-0.6.19.1/nuitka/codegen/templates_c/CodeTemplateCallsPositional.c.j20000600000372100037210000005344614166627112033547 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperObjectTools.c.j2' import CHECK_OBJECTS %} {% if args_count == 0 %} PyObject *CALL_FUNCTION_NO_ARGS(PyObject *called) { {% elif args_count == 1 and not has_tuple_arg %} PyObject *CALL_FUNCTION_WITH_SINGLE_ARG(PyObject *called, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. {% else %} {% if has_tuple_arg %} PyObject *CALL_FUNCTION_WITH_POSARGS{{args_count}}(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == {{args_count}}); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); {% else %} PyObject *CALL_FUNCTION_WITH_ARGS{{args_count}}(PyObject *called, PyObject *const *args) { {% endif %} {% endif %} CHECK_OBJECT(called); {{ CHECK_OBJECTS(args, args_count) }} if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && {{args_count}} == function->m_args_positional_count){ {% if args_count == 1 %} Py_INCREF(args[0]); {% elif args_count > 1 %} for (Py_ssize_t i = 0; i < {{args_count}}; i++) { Py_INCREF(args[i]); } {% endif %} result = function->m_c_code(function, {% if args_count != 0 %} (PyObject **)args {% else %} NULL {% endif %}); } else if (function->m_args_simple && {{args_count}} + function->m_defaults_given == function->m_args_positional_count) { {% if args_count != 0 %} NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, {{args_count}} * sizeof(PyObject *)); memcpy(python_pars + {{args_count}}, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); {% else %} PyObject **python_pars = &PyTuple_GET_ITEM(function->m_defaults, 0); {% endif %} for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { {% if args_count == 0 %} result = Nuitka_CallFunctionNoArgs(function); {% else %} result = Nuitka_CallFunctionPosArgs(function, args, {{args_count}}); {% endif %} } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { {% if args_count < 1 %} PyErr_Format( PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class)); return NULL; {% else %} PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, {{args_count}}); {% endif %} } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && {{args_count}} + 1 == function->m_args_positional_count) { PyObject *python_pars[{{args_count}} + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); {% if args_count == 1 %} python_pars[1] = args[0]; Py_INCREF(args[0]); {% elif args_count > 1 %} for (Py_ssize_t i = 0; i < {{args_count}}; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } {% endif %} result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && {{args_count}} + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); {% if args_count != 0 %} memcpy(python_pars+1, args, {{args_count}} * sizeof(PyObject *)); {% endif %} memcpy(python_pars+1 + {{args_count}}, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { {% if args_count != 0 %} result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, {{args_count}}); {% else %} result = Nuitka_CallMethodFunctionNoArgs(function, method->m_object); {% endif %} } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if ({{ unlikely_or_likely_from(args_count != 0) }}(flags & METH_NOARGS)) { {% if args_count == 0 %} // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result = (*method)(self, NULL); #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); {% else %} SET_CURRENT_EXCEPTION_TYPE0_FORMAT1( PyExc_TypeError, "%s() takes no arguments ({{args_count}} given)", ((PyCFunctionObject *)called)->m_ml->ml_name ); return NULL; {% endif %} } else if ({{ unlikely_if(args_count != 1) }}(flags & METH_O)) { {% if args_count == 1 %} // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result = (*method)(self, args[0]); #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); {% else %} SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument ({{args_count}} given)", ((PyCFunctionObject *)called)->m_ml->ml_name ); return NULL; {% endif %} } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 {% if not has_tuple_arg and args_count != 0 %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% elif not has_tuple_arg %} PyObject *pos_args = const_tuple_empty; {% endif %} if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } {% if not has_tuple_arg and args_count != 0 %} Py_DECREF(pos_args); {% endif %} #else if (flags == (METH_VARARGS|METH_KEYWORDS)) { {% if not has_tuple_arg and args_count != 0 %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% elif not has_tuple_arg %} PyObject *pos_args = const_tuple_empty; {% endif %} result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); {% if not has_tuple_arg and args_count != 0 %} Py_DECREF(pos_args); {% endif %} } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 {% if args_count != 0 %} result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, {{args_count}}, NULL); {% else %} result = (*(_PyCFunctionFast)method)(self, NULL, 0, NULL); {% endif %} #else {% if not has_tuple_arg and args_count != 0 %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% elif not has_tuple_arg %} PyObject *pos_args = const_tuple_empty; {% endif %} result = (*(_PyCFunctionFast)method)(self, &pos_args, {{args_count}}); {% if not has_tuple_arg and args_count != 0 %} Py_DECREF(pos_args); {% endif %} #endif } else { {% if not has_tuple_arg and args_count != 0 %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% elif not has_tuple_arg %} PyObject *pos_args = const_tuple_empty; {% endif %} result = (*method)(self, pos_args); {% if not has_tuple_arg and args_count != 0 %} Py_DECREF(pos_args); {% endif %} } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { {% if args_count == 0 %} return _fast_function_noargs(called); {% else %} return callPythonFunction( called, args, {{args_count}} ); {% endif %} } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); {% if args_count == 1 %} {# For single argument, special case "type" itself, this is however unlikely, as this ought to be optimized in normal compilation to built-in call. #} if (unlikely(called == (PyObject *)&PyType_Type)) { PyObject *result = (PyObject *)Py_TYPE(args[0]); Py_INCREF(result); return result; } {% endif %} if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } {% if not has_tuple_arg and args_count != 0 %} PyObject *pos_args = NULL; {% elif not has_tuple_arg %} PyObject *pos_args = const_tuple_empty; {% endif %} PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { {% if not has_tuple_arg and args_count != 0 %} pos_args = MAKE_TUPLE(args, {{args_count}}); {% endif %} obj = called_type->tp_new(called_type, pos_args, NULL); {# TODO: obj = _Py_CheckFunctionResult(obj) for Python3 in debug mode #} } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { {% if not has_tuple_arg and args_count != 0 %} Py_DECREF(pos_args); {% endif %} return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { {% if not has_tuple_arg and args_count != 0 %} Py_XDECREF(pos_args); pos_args = NULL; {% endif %} PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; {% if args_count == 0 %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)init_method, obj); } else { result = CALL_FUNCTION_NO_ARGS(init_method); Py_DECREF(init_method); } {% elif args_count == 1 %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } {% else %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, {{args_count}}); } else { {% if has_tuple_arg %} result = CALL_FUNCTION_WITH_POSARGS{{args_count}}(init_method, pos_args); {% else %} result = CALL_FUNCTION_WITH_ARGS{{args_count}}(init_method, args); {% endif %} Py_DECREF(init_method); } {% endif %} if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { {% if not has_tuple_arg and args_count != 0 %} if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, {{args_count}}); } {% endif %} if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); {% if not has_tuple_arg and args_count != 0 %} Py_XDECREF(pos_args); {% endif %} return NULL; } } } } {% if not has_tuple_arg and args_count != 0 %} Py_XDECREF(pos_args); {% endif %} return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if ({{ unlikely_if(args_count != 0)}}(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } {% if args_count == 0 %} return obj; {% else %} Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; {% endif %} } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; {% if args_count == 0 %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)init_method, obj); } else { result = CALL_FUNCTION_NO_ARGS(init_method); Py_DECREF(init_method); } {% elif args_count == 1 %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } {% else %} if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, {{args_count}}); } else { {% if has_tuple_arg %} result = CALL_FUNCTION_WITH_POSARGS{{args_count}}(init_method, pos_args); {% else %} result = CALL_FUNCTION_WITH_ARGS{{args_count}}(init_method, args); {% endif %} Py_DECREF(init_method); } {% endif %} if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { {% if args_count == 0 %} PyObject *result = func(called, NULL, 0, NULL); {% else %} PyObject *result = func(called, args, {{args_count}}, NULL); {% endif %} return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif {% if args_count == 0 %} PyObject *result = CALL_FUNCTION(called, const_tuple_empty, NULL); {% else %} {% if not has_tuple_arg %} PyObject *pos_args = MAKE_TUPLE(args, {{args_count}}); {% endif %} PyObject *result = CALL_FUNCTION(called, pos_args, NULL); {% if not has_tuple_arg %} Py_DECREF(pos_args); {% endif %} {% endif %} return result; } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsLong.c.j20000600000372100037210000002002214166627112031224 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit, constant_long_exit_target, constant_int_exit_target %} {% macro long_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {% if operator == "+" %} if (Py_ABS(Py_SIZE({{ operand1 }})) <= 1 && Py_ABS(Py_SIZE({{ operand2 }})) <= 1) { {% if target == None %} if (Py_REFCNT({{operand1}}) == 1) { Nuitka_LongUpdateFromCLong(&{{operand1}}, MEDIUM_VALUE({{ operand1 }}) + MEDIUM_VALUE({{ operand2 }})); {{ goto_exit(props, "exit_result_ok") }} } {% endif %} PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE({{ operand1 }}) + MEDIUM_VALUE({{ operand2 }})); {{ goto_exit(props, "exit_result_object", "r") }} } {% if target == None %} if (Py_REFCNT({{operand1}}) == 1) { digit const *b = Nuitka_LongGetDigitPointer({{ operand2 }}); Py_ssize_t size_b = Nuitka_LongGetDigitSize({{ operand2 }}); #if 0 PyObject *r = BINARY_OPERATION_ADD_OBJECT_LONG_LONG( {{ operand1 }}, {{ operand2 }} ); #endif if (Py_SIZE({{ operand1 }}) < 0) { if (Py_SIZE({{ operand2 }}) < 0) { {{ operand1 }} = _Nuitka_LongAddInplaceDigits({{ operand1 }}, b, size_b); Py_SIZE({{ operand1 }}) = -Py_ABS(Py_SIZE({{ operand1 }})); } else { {# Reversed operands order means sign inversion. #} {{ operand1 }} = _Nuitka_LongSubInplaceDigits({{ operand1 }}, b, size_b, -1); } } else { if (Py_SIZE({{ operand2 }}) < 0) { {{ operand1 }} = _Nuitka_LongSubInplaceDigits({{ operand1 }}, b, size_b, 1); } else { {{ operand1 }} = _Nuitka_LongAddInplaceDigits({{ operand1 }}, b, size_b); } } #if 0 assert(PyObject_RichCompareBool(r, {{operand1}}, Py_EQ) == 1); Py_DECREF(r); #endif {{ goto_exit(props, "exit_result_ok") }} } {% endif %} { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer({{ operand1 }}); Py_ssize_t size_a = Nuitka_LongGetDigitSize({{ operand1 }}); digit const *b = Nuitka_LongGetDigitPointer({{ operand2 }}); Py_ssize_t size_b = Nuitka_LongGetDigitSize({{ operand2 }}); if (Py_SIZE({{ operand1 }}) < 0) { if (Py_SIZE({{ operand2 }}) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { {# Reversed operands order. #} z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE({{ operand2 }}) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } {{ goto_exit(props, "exit_result_object", "(PyObject *)z") }} } {% elif operator == "-" %} if (Py_ABS(Py_SIZE({{ operand1 }})) <= 1 && Py_ABS(Py_SIZE({{ operand2 }})) <= 1) { {% if target == None %} if (Py_REFCNT({{operand1}}) == 1) { Nuitka_LongUpdateFromCLong(&{{operand1}}, MEDIUM_VALUE({{ operand1 }}) - MEDIUM_VALUE({{ operand2 }})); {{ goto_exit(props, "exit_result_ok") }} } {% endif %} PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE({{ operand1 }}) - MEDIUM_VALUE({{ operand2 }})); {{ goto_exit(props, "exit_result_object", "r") }} } {% if target == None %} if (Py_REFCNT({{operand1}}) == 1) { digit const *b = Nuitka_LongGetDigitPointer({{ operand2 }}); Py_ssize_t size_b = Nuitka_LongGetDigitSize({{ operand2 }}); #if 0 PyObject *r = BINARY_OPERATION_SUB_OBJECT_LONG_LONG( {{ operand1 }}, {{ operand2 }} ); #endif if (Py_SIZE({{ operand1 }}) < 0) { if (Py_SIZE({{ operand2 }}) < 0) { {# Reversed operands order means sign inversion. #} {{ operand1 }} = _Nuitka_LongSubInplaceDigits({{ operand1 }}, b, size_b, -1); } else { {{ operand1 }} = _Nuitka_LongAddInplaceDigits({{ operand1 }}, b, size_b); Py_SIZE({{ operand1 }}) = -Py_ABS(Py_SIZE({{ operand1 }})); } } else { if (Py_SIZE({{ operand2 }}) < 0) { {{ operand1 }} = _Nuitka_LongAddInplaceDigits({{ operand1 }}, b, size_b); } else { {{ operand1 }} = _Nuitka_LongSubInplaceDigits({{ operand1 }}, b, size_b, 1); } } #if 0 assert(PyObject_RichCompareBool(r, {{operand1}}, Py_EQ) == 1); Py_DECREF(r); #endif {{ goto_exit(props, "exit_result_ok") }} } {% endif %} { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer({{ operand1 }}); Py_ssize_t size_a = Nuitka_LongGetDigitSize({{ operand1 }}); digit const *b = Nuitka_LongGetDigitPointer({{ operand2 }}); Py_ssize_t size_b = Nuitka_LongGetDigitSize({{ operand2 }}); if (Py_SIZE({{ operand1 }}) < 0) { if (Py_SIZE({{ operand2 }}) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE({{ operand2 }}) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } {{ goto_exit(props, "exit_result_object", "(PyObject *)z") }} } {% else %} {# TODO: Could and should in-line and specialize this for more operators #} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyLong_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; assert(x != Py_NotImplemented); {{ goto_exit(props, "exit_result_object", "x") }} {% endif %} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% if "exit_result_ok_const_long_0" in props["exits"] %} {{ constant_long_exit_target(props, target, result, left, operand1, "exit_result_ok_const_long_0", 0, exit_result_ok) }} {% endif %} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsList.c.j20000600000372100037210000000564314166627112031254 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro list_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% if nb_slot == "nb_add" %} {% if left.type_name == "list" == right.type_name %} PyObject *x = LIST_CONCAT({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *x = {{ left.getSlotCallExpression("sq_concat", "PyList_Type.tp_as_sequence->sq_concat", operand1, operand2) }}; {% endif %} {% elif nb_slot == "nb_multiply" %} PyObject *x = {{ left.getSlotCallExpression("sq_repeat", "PyList_Type.tp_as_sequence->sq_repeat", operand1, operand2) }}; {% else %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyList_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; {% endif %} assert(x != Py_NotImplemented); {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsInt.c.j20000600000372100037210000003574314166627112031077 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit, constant_int_exit_target, constant_float_exit_target %} {% macro int_core(props, operator, nb_slot, bool_mode, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception, exit_result_ok_cbool, exit_result_ok_clong, exit_result_ok_cfloat, exit_result_object, exit_result_ok_left, exit_result_ok_const_int_0, exit_result_ok_const_int_neg_1, exit_result_ok_const_float_0_0, exit_result_ok_const_float_minus_0_0) %} {% set fall_through_needed = 1 %} {{ left.getCheckValueCode(operand1) }} {{ right.getCheckValueCode(operand2) }} {# This is supposed to be Python2 only code with types no bigger than int, therefore this works always #} const long a = {{ left.getAsLongValueExpression(operand1) }}; const long b = {{ right.getAsLongValueExpression(operand2) }}; {% if operator in "+-" %} const long x = (long)((unsigned long)a {{operator}} b); bool no_overflow = ((x^a) >= 0 || (x^{{"~" if operator == "-" else ""}}b) >= 0); {% if bool_mode %} bool t = !no_overflow || x != 0; {{ goto_exit(props, exit_result_ok_cbool, "t") }} {% set fall_through_needed = 0 %} {% else %} if (likely(no_overflow)) { {{ goto_exit(props, exit_result_ok_clong, "x") }} } {% endif %} {% elif operator == "*" %} const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { {{ goto_exit(props, exit_result_ok_clong, "longprod") }} } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { {{ goto_exit(props, exit_result_ok_clong, "longprod") }} } } {% elif operator == "//" or nb_slot == "nb_divide" %} if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); {{ goto_exit(props, exit_result_exception) }} } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } {{ goto_exit(props, exit_result_ok_clong, "a_div_b") }} } {% elif operator=="/" and "true_div" in nb_slot %} if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); {{ goto_exit(props, exit_result_exception) }} } {% if bool_mode %} {{ goto_exit(props, exit_result_ok_cbool, "a == 0") }} {% set fall_through_needed = 0 %} {% else %} if (a == 0) { if (b < 0) { {{ goto_exit(props, exit_result_ok_const_float_minus_0_0) }} } else { {{ goto_exit(props, exit_result_ok_const_float_0_0) }} } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } {% endif %} {% elif operator=="%" %} /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0) ) { r += b; } {{ goto_exit(props, exit_result_ok_clong, "r") }} } {% elif operator in "|^&" %} const long r = a {{operator}} b; {{ goto_exit(props, exit_result_ok_clong, "r") }} {% set fall_through_needed = 0 %} {% elif operator == "<<" %} if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); {{ goto_exit(props, exit_result_exception) }} } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { {{ goto_exit(props, exit_result_ok_left) }} } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); {{ goto_exit(props, exit_result_object, "r") }} } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); {{ goto_exit(props, exit_result_object, "r") }} } else { {{ goto_exit(props, exit_result_ok_clong, "c") }} } } {% set fall_through_needed = 0 %} {% elif operator == ">>" %} if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); {{ goto_exit(props, exit_result_exception) }} } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { {{ goto_exit(props, exit_result_ok_left) }} } else if (b >= LONG_BIT) { if (a < 0) { {{ goto_exit(props, exit_result_ok_const_int_neg_1) }} } else { {{ goto_exit(props, exit_result_ok_const_int_0) }} } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); {{ goto_exit(props, exit_result_ok_clong, "r") }} } {% set fall_through_needed = 0 %} {% elif operator == "**" %} if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); {{ goto_exit(props, exit_result_object, "r") }} } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); {{ goto_exit(props, exit_result_object, "r") }} } } bb >>= 1; if (bb==0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); {{ goto_exit(props, exit_result_object, "r") }} } } {{ goto_exit(props, exit_result_ok_clong, "ix") }} } {% set fall_through_needed = 0 %} {% elif operator == "divmod" %} if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); {{ goto_exit(props, exit_result_exception) }} } if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b); {{ goto_exit(props, exit_result_object, "r") }} } {% else %} #error Operator {{operator}} not implemented {% endif %} {% if fall_through_needed %} { PyObject *operand1_object = {{ left.getAsObjectValueExpression(operand1) }}; PyObject *operand2_object = {{ right.getAsObjectValueExpression(operand2) }}; PyObject *r = {{ left.getSlotCallExpression(nb_slot, "PyLong_Type.tp_as_number->"+nb_slot, "operand1_object", "operand2_object") }}; assert(r != Py_NotImplemented); {{ left.releaseAsObjectValueStatement("operand1_object") }} {{ right.releaseAsObjectValueStatement("operand2_object") }} {{ goto_exit(props, exit_result_object, "r") }} } {% endif %} {% endmacro %} {% macro int_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} {% set bool_mode = target and target.type_name in ("nuitka_bool", "nbool") %} // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif {{ int_core(props, operator, nb_slot, bool_mode, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception, "exit_result_ok_cbool", "exit_result_ok_clong", "exit_result_ok_cfloat", "exit_result_object", "exit_result_ok_left", "exit_result_ok_const_int_0", "exit_result_ok_const_int_neg_1", "exit_result_ok_const_float_0_0", "exit_result_ok_const_float_minus_0_0") }} {# // {{ props }} #} {% if "exit_result_ok_cbool" in props["exits"] %} exit_result_ok_cbool: {% if target %} {{ target.getAssignFromBoolExpressionCode(result, "cbool_result", give_ref=1) }} {% else %} {# TODO: Check the reference we were handed down. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); // That's our return value then. As we use a dedicated variable, it's // OK that way. {{ operand1 }} = PyInt_FromLong(cbool_result); {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_clong" in props["exits"] %} exit_result_ok_clong: {% if target %} {{ target.getAssignFromLongExpressionCode(result, "clong_result") }} {% else %} {# TODO: Check the reference we were handed down. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); // That's our return value then. As we use a dedicated variable, it's // OK that way. {{ operand1 }} = PyInt_FromLong(clong_result); {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_cfloat" in props["exits"] %} exit_result_ok_cfloat: {% if target %} {{ target.getAssignFromFloatExpressionCode(result, "cfloat_result") }} {% else %} {# TODO: Check the reference we were handed down. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignFromFloatExpressionCode(operand1, "cfloat_result") }} {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_left" in props["exits"] %} exit_result_ok_left: {% if target %} {{ target.getAssignConversionCode(result, left, operand1) }} {% endif %} {# Nothing to do in case of in-place. #} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_object" in props["exits"] %} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_int_0" in props["exits"] %} {{ constant_int_exit_target(props, target, result, left, operand1, "exit_result_ok_const_int_0", 0, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_int_neg_1" in props["exits"] %} {{ constant_int_exit_target(props, target, result, left, operand1, "exit_result_ok_const_int_neg_1", -1, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_float_0_0" in props["exits"] %} {{ constant_float_exit_target(props, target, result, left, operand1, "exit_result_ok_const_float_0_0", 0.0, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_float_minus_0_0" in props["exits"] %} {{ constant_float_exit_target(props, target, result, left, operand1, "exit_result_ok_const_float_minus_0_0", -0.0, exit_result_ok) }} {% endif %} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonFloat.c.j20000600000372100037210000000404014166627112034263 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} const double a = {{left.getAsDoubleValueExpression("operand1")}}; const double b = {{right.getAsDoubleValueExpression("operand2")}}; bool r = a {{operand}} b; // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsFloat.c.j20000600000372100037210000002416414166627112031405 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit, constant_int_exit_target, constant_float_exit_target %} {% macro float_core(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_object, exit_result_exception, exit_result_ok_cfloat, exit_result_ok_left, exit_result_ok_right, exit_result_ok_const_float_1_0, exit_result_ok_const_float_0_0, exit_result_ok_const_float_minus_1_0) %} {{ left.getCheckValueCode(operand1) }} {{ right.getCheckValueCode(operand2) }} double a = PyFloat_AS_DOUBLE({{ operand1 }}); double b = PyFloat_AS_DOUBLE({{ operand2 }}); {% if operator in "+-*" %} double r = a {{operator}} b; {{ goto_exit(props, exit_result_ok_cfloat, "r") }} {% elif operator == "//" %} if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); {{ goto_exit(props, exit_result_exception) }} } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a/b); } {{ goto_exit(props, exit_result_ok_cfloat, "floordiv") }} } {% elif operator == "/" %} if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); {{ goto_exit(props, exit_result_exception) }} } { double r = a {{operator}} b; {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } {% elif operator == "%" %} if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); {{ goto_exit(props, exit_result_exception) }} } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } {{ goto_exit(props, exit_result_ok_cfloat, "mod") }} } {% elif operator == "divmod" %} if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); {{ goto_exit(props, exit_result_exception) }} } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { mod += b; div -= 1.0; } } else { mod = copysign(0.0, b); } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a/b); } PyObject *r = Py_BuildValue("(dd)", floordiv, mod); {{ goto_exit(props, exit_result_object, "r") }} } {% elif operator == "**" %} if (b == 0) { {{ goto_exit(props, exit_result_ok_const_float_1_0) }} } if (Py_IS_NAN(a)) { {{ goto_exit(props, exit_result_ok_left) }} } if (Py_IS_NAN(b)) { if (a == 1.0) { {{ goto_exit(props, exit_result_ok_const_float_1_0) }} } else { {{ goto_exit(props, exit_result_ok_right) }} } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { {{ goto_exit(props, exit_result_ok_const_float_1_0) }} } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); {# TODO: Should this be ok_clong then? #} {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } else { {{ goto_exit(props, exit_result_ok_const_float_0_0) }} } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); {{ goto_exit(props, exit_result_exception) }} } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); {{ goto_exit(props, exit_result_exception) }} } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { {{ goto_exit(props, exit_result_ok_const_float_minus_1_0) }} } else { {{ goto_exit(props, exit_result_ok_const_float_1_0) }} } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); {{ goto_exit(props, exit_result_exception) }} } r = negate_result ? -r : r; {{ goto_exit(props, exit_result_ok_cfloat, "r") }} } } {% else %} #error Operator {{operator}} not implemented in {{name}} {% endif %} {% endmacro %} {% macro float_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif {{ float_core(props, operator, nb_slot, target, left, right, result, operand1, operand2, "exit_result_object", exit_result_exception, "exit_result_ok_cfloat", "exit_result_ok_left", "exit_result_ok_right", "exit_result_ok_const_float_1_0", "exit_result_ok_const_float_0_0", "exit_result_ok_const_float_minus_1_0") }} {% if "exit_result_ok_cfloat" in props["exits"] %} exit_result_ok_cfloat: {% if target %} {{ target.getAssignFromFloatExpressionCode(result, "cfloat_result") }} {% else %} {# TODO: Check the reference we were handed down. #} if (Py_REFCNT({{ operand1 }}) == 1) { PyFloat_AS_DOUBLE({{ operand1 }}) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignFromFloatExpressionCode(operand1, "cfloat_result") }} } {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_object" in props["exits"] %} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_left" in props["exits"] %} exit_result_ok_left: {% if target %} {{ target.getAssignConversionCode(result, left, operand1) }} {% endif %} {# Nothing to do in case of in-place. #} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_right" in props["exits"] %} exit_result_ok_right: {% if target %} {{ target.getAssignConversionCode(result, right, operand2) }} {% else %} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ left.getAssignConversionCode(operand1, right, operand2) }} {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_float_0_0" in props["exits"] %} {{ constant_float_exit_target(props, target, result, left, operand1, "exit_result_ok_const_float_0_0", 0.0, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_float_1_0" in props["exits"] %} {{ constant_float_exit_target(props, target, result, left, operand1, "exit_result_ok_const_float_1_0", 1.0, exit_result_ok) }} {% endif %} {% if "exit_result_ok_const_float_minus_1_0" in props["exits"] %} {{ constant_float_exit_target(props, target, result, left, operand1, "exit_result_ok_const_float_minus_1_0", -1.0, exit_result_ok) }} {% endif %} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsSet.c.j20000600000372100037210000000475714166627112031101 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro set_slot(props, operator, nb_slot, nb_islot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% set slot = nb_islot or nb_slot %} PyObject *x = {{ left.getSlotCallExpression(slot, "PySet_Type.tp_as_number->" + slot, operand1, operand2) }}; assert(x != Py_NotImplemented); {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsBinary.c.j20000600000372100037210000004464614166627112031573 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% from 'HelperSlotsInt.c.j2' import int_slot %} {% from 'HelperSlotsLong.c.j2' import long_slot %} {% from 'HelperSlotsFloat.c.j2' import float_slot %} {% from 'HelperSlotsStr.c.j2' import str_slot %} {% from 'HelperSlotsUnicode.c.j2' import unicode_slot %} {% from 'HelperSlotsBytes.c.j2' import bytes_slot %} {% from 'HelperSlotsTuple.c.j2' import tuple_slot %} {% from 'HelperSlotsList.c.j2' import list_slot %} {% from 'HelperSlotsSet.c.j2' import set_slot %} {% macro operation_unsupported_error_exit(props, operator, left, right, type1, type2, exit_result_exception) %} {% set args = [] %} {% if left == object_desc %} {% do args.append("%s->tp_name" % type1) %} {% endif %} {% if right == object_desc %} {% do args.append("%s->tp_name" % type2) %} {% endif %} {% set left_name_2 = "'%s'" % ("%s" if left == object_desc else left.getTypeName2()) %} {% set left_name_3 = "'%s'" % ("%s" if left == object_desc else left.getTypeName3()) %} {% set right_name_2 = "'%s'" % ("%s" if right == object_desc else right.getTypeName2()) %} {% set right_name_3 = "'%s'" % ("%s" if right == object_desc else right.getTypeName3()) %} {% if (left_name_2 == left_name_3 and right_name_2 == right_name_3) or left.python_requirement or right.python_requirement %} {% if left.python_requirement == "PYTHON_VERSION < 0x300" or right.python_requirement == "PYTHON_VERSION < 0x300" %} PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for {{ left.getOperationErrorMessageName(operator) }}: {{ left_name_2 }} and {{ right_name_2 }}"{{ "," + ",".join(args) if args else "" }}); {% else %} PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for {{ left.getOperationErrorMessageName(operator) }}: {{ left_name_3 }} and {{ right_name_3 }}"{{ "," + ",".join(args) if args else "" }}); {% endif %} {% else %} #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for {{ left.getOperationErrorMessageName(operator) }}: {{ left_name_2 }} and {{ right_name_2 }}"{{ "," + ",".join(args) if args else "" }}); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for {{ left.getOperationErrorMessageName(operator) }}: {{ left_name_3 }} and {{ right_name_3 }}"{{ "," + ",".join(args) if args else "" }}); #endif {% endif %} {{ goto_exit(props, exit_result_exception) }} {% endmacro %} {% macro cannot_fit_to_index_size_error_exit(props, left, right, type2, exit_result_exception) %} {% if right == object_desc %} PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", {{ type2 }}->tp_name); {% else %} {% set right_name_2 = right.getTypeName2() %} {% set right_name_3 = right.getTypeName3() %} {% if right_name_2 == right_name_3 or left.python_requirement or right.python_requirement %} {% if left.python_requirement == "PYTHON_VERSION < 0x300" or right.python_requirement == "PYTHON_VERSION < 0x300" %} PyErr_Format(PyExc_OverflowError, "cannot fit '{{ right_name_2 }}' into an index-sized integer" ); {% else %} PyErr_Format(PyExc_OverflowError, "cannot fit '{{ right_name_3 }}' into an index-sized integer" ); {% endif %} {% else %} #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit '{{ right_name_2 }}' into an index-sized integer" ); #else PyErr_Format(PyExc_OverflowError, "cannot fit '{{ right_name_3 }}' into an index-sized integer" ); #endif {% endif %} {% endif %} {{ goto_exit(props, exit_result_exception) }} {% endmacro %} {% macro concat_operation(props, left, right, type1, type2, operand1, operand2, exit_result_object, exit_result_exception) %} {% if sq_islot and left.hasSlot(sq_islot) %} { PyObject *o = {{ left.getSlotValueExpression(type1, "sq_inplace_concat") }}({{ operand1 }}, {{ operand2 }}); {{ goto_exit(props, exit_result_object, "o") }} } {% endif %} { PyObject *o = {{ left.getSlotValueExpression(type1, "sq_concat") }}({{ operand1 }}, {{ operand2 }}); {{ goto_exit(props, exit_result_object, "o") }} } {% endmacro %} {% macro repeat_operation(props, left, right, type1, type2, operand1, operand2, exit_result_object, exit_result_exception) %} {# This is the SEQUENCE_REPEAT() helper specialized #} if (unlikely(!{{ right.getIndexCheckExpression(operand2) }})) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", {{ type2 }}->tp_name); {{ goto_exit(props, exit_result_exception) }} } { {% if right.needsIndexConversion() %} PyObject *index_value = PyNumber_Index({{ operand2 }}); if (unlikely(index_value == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% else %} PyObject *index_value = {{ operand2 }}; {% endif %} { {% if right.type_name == "int" %} Py_ssize_t count = PyInt_AS_LONG(index_value); {% else %} {% if right.type_name == "long" %} Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); {% else %} Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); {% endif %} {% if right.needsIndexConversion() %} Py_DECREF(index_value); {% endif %} /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { {{ cannot_fit_to_index_size_error_exit(props, left, right, type2, exit_result_exception) }} } {% endif %} { {% if sq_islot %} {{ left.getSlotType(sq_slot) }} repeatfunc = {{ left.getSlotValueExpression(type1, sq_islot) }}; if (repeatfunc == NULL) { repeatfunc = {{ left.getSlotValueExpression(type1, sq_slot) }}; } {% else %} {{ left.getSlotType(sq_slot) }} repeatfunc = {{ left.getSlotValueExpression(type1, sq_slot) }}; {% endif %} PyObject *r = (*repeatfunc)({{ operand1 }}, count); {{ goto_exit(props, exit_result_object, "r") }} } } } {% endmacro %} {% macro binary_operation(props, operator, nb_slot, left, right, type1, type2, operand1, operand2, exit_result_object, exit_result_cbool_ok, exit_result_nbool, exit_result_exception) %} {% set slot1_relevant = left == object_desc or left.hasSlot(nb_slot) %} {% set slot2_relevant = right == object_desc or (left != right and right.hasSlot(nb_slot)) %} {% set error_needed = 1 %} {% if slot1_relevant %} {{ left.getSlotType(nb_slot) }} slot1 = {{ left.getSlotValueExpression(type1, nb_slot) }}; {% endif %} {% if slot2_relevant %} {{ left.getSlotType(nb_slot) }} slot2 = NULL; if (!({{ left.getTypeIdenticalCheckExpression(right, type1, type2) }})) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = {{ right.getSlotValueExpression(type2, nb_slot) }}; {% if slot1_relevant and (left == object_desc or right == object_desc) %} if (slot1 == slot2) { slot2 = NULL; } {% endif %} } {% else %} assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->{{nb_slot}} == NULL || type1->tp_as_number->{{nb_slot}} == type2->tp_as_number->{{nb_slot}}); {% endif %} {% if slot1_relevant %} if (slot1 != NULL) { {% if slot2_relevant and right == object_desc %} if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = {{ left.getSlotCallExpression(nb_slot, "slot2", operand1, operand2) }}; if (x != Py_NotImplemented) { {{ goto_exit(props, exit_result_object, "x") }} } Py_DECREF(x); slot2 = NULL; } } {% endif %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "slot1", operand1, operand2) }}; if (x != Py_NotImplemented) { {{ goto_exit(props, exit_result_object, "x") }} } Py_DECREF(x); } {% endif %} {% if slot2_relevant %} if (slot2 != NULL) { PyObject *x = {{ left.getSlotCallExpression(nb_slot, "slot2", operand1, operand2) }}; if (x != Py_NotImplemented) { {{ goto_exit(props, exit_result_object, "x") }} } Py_DECREF(x); } {% endif %} {% if operator != "@" %} {% if not left.isKnownToNotCoerce(right) or not right.isKnownToNotCoerce(left) %} #if PYTHON_VERSION < 0x300 if (!{{ left.getNewStyleNumberTypeCheckExpression(type1) }} || !{{ right.getNewStyleNumberTypeCheckExpression(type2)}} ) { {% if not left.isKnownToNotCoerce(right) %} coercion c1 = {{ left.getSlotValueExpression(type1, "nb_coerce") }}; if (c1 != NULL) { PyObject *coerced1 = {{ operand1 }}; PyObject *coerced2 = {{ operand2 }}; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { {{ goto_exit(props, exit_result_exception, None, "py2") }} } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { {{ left.getSlotType(nb_slot) }} slot = mv->{{ nb_slot }}; if (likely(slot != NULL)) { PyObject *x = {{ left.getSlotCallExpression(nb_slot, "slot", "coerced1", "coerced2") }}; Py_DECREF(coerced1); Py_DECREF(coerced2); {{ goto_exit(props, exit_result_object, "x") }} } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } {% endif %} {% if not right.isKnownToNotCoerce(left) %} coercion c2 = {{ right.getSlotValueExpression(type2, "nb_coerce") }}; if (c2 != NULL) { PyObject *coerced1 = {{ operand1 }}; PyObject *coerced2 = {{ operand2 }}; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { {{ goto_exit(props, exit_result_exception, None, "py2") }} } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { {{ left.getSlotType(nb_slot)}} slot = mv->{{ nb_slot }}; if (likely(slot != NULL)) { PyObject *x = {{ left.getSlotCallExpression(nb_slot, "slot", "coerced1", "coerced2") }}; Py_DECREF(coerced1); Py_DECREF(coerced2); {{ goto_exit(props, exit_result_object, "x") }} } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } {% endif %} } #endif {% else %} // Statically recognized that coercion is not possible with these types {% endif %} {% else %} // Statically recognized that coercion is not possible with Python3 only operator '@' {% endif %} {# There might be a sq_slot specialization that saves the day. #} {% if operator in "+*" %} {% if left.type_name != "object" and left.hasSlot(sq_slot) %} {% if operator == "*" %} {{ repeat_operation(props, left, right, type1, type2, operand1, operand2, exit_result_object, exit_result_exception) }} {% else %} {{ concat_operation(props, left, right, type1, type2, operand1, operand2, exit_result_object, exit_result_exception) }} {% endif %} {% set error_needed = 0 %} {% else %} { {% if sq_islot and (left == object_desc or left.hasSlot(sq_islot)) %} // Special case for "+" and "*", also works as sequence concat/repeat. {{ left.getSlotType(sq_slot) }} sq_slot = {{ left.getSlotValueExpression(type1, sq_islot) }}; if (sq_slot == NULL) { sq_slot = {{ left.getSlotValueExpression(type1, sq_slot) }}; } {% set lslot_needed = 1 %} {% elif left == object_desc or left.hasSlot(sq_slot) %} // Special case for "+" and "*", also works as sequence concat/repeat. {{ left.getSlotType(sq_slot) }} sq_slot = {{ left.getSlotValueExpression(type1, sq_slot) }}; {% set lslot_needed = 1 %} {% else %} // No sequence repeat slot {{ sq_slot }} available for this type. assert({{ type1 }}->tp_as_sequence == NULL || {{ type1 }}->tp_as_sequence->{{ sq_slot }} == NULL); {% if sq_islot %} // No inplace sequence repeat slot {{ sq_islot }} available for this type. assert({{ type1 }}->tp_as_sequence == NULL || {{ type1 }}->tp_as_sequence->{{ sq_islot }} == NULL); {% endif %} {% set lslot_needed = 0 %} {% endif %} {% if lslot_needed == 1 %} if (sq_slot != NULL) { {% if operator == "+" %} PyObject *result = sq_slot({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *result = SEQUENCE_REPEAT(sq_slot, {{ operand1 }}, {{ operand2 }}); {% endif %} {{ goto_exit(props, exit_result_object, "result") }} } {% endif %} } {% if operator == "*" %} {% if right.type_name != "object" and right.hasSlot("sq_repeat") %} {% if operator == "*" %} {% if sq_islot %} if ({{ type1 }}->tp_as_sequence == NULL) { {% endif %} {{ repeat_operation(props, right, left, type2, type1, operand2, operand1, exit_result_object, exit_result_exception) }} {% if sq_islot %} } {% endif %} {% else %} {{ target.getTypeDecl() }} x = SLOT_sq_repeat_{{target.getHelperCodeName()}}_{{right.getHelperCodeName()}}_{{left.getHelperCodeName()}}(operand2, operand1); {% if target and target.type_name == "cbool" %} {{ goto_exit(props, exit_result_ok_cbool, "x") }} {% elif target and target.type_name == "nbool" %} {{ goto_exit(props, exit_result_nbool, "x") }} {% else %} {{ goto_exit(props, exit_result_object, "x") }} {% endif %} {% endif %} {% if not sq_islot %} {% set error_needed = 0 %} {% endif %} {% else %} {% if right == object_desc or right.hasSlot(sq_slot) %} // Special case for "*", also work with sequence repeat from right argument. {% if sq_islot %} if ({{ type1 }}->tp_as_sequence == NULL ) {% endif %} { {{ right.getSlotType(sq_slot) }} sq_slot = {{ right.getSlotValueExpression(type2, sq_slot) }}; {% set rslot_needed = 1 %} {% else %} // No sequence repeat slot {{ sq_slot }} available for this type. assert({{ type2 }}->tp_as_sequence == NULL || {{ type2 }}->tp_as_sequence->{{ sq_slot }} == NULL); {% set rslot_needed = 0 %} {% endif %} {% if rslot_needed == 1 %} if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, {{ operand2 }}, {{ operand1 }}); {{ goto_exit(props, exit_result_object, "result") }} } } {% endif %} {% endif %} {% endif %} {% endif %} {% endif %} {% if error_needed == 1 %} {{ operation_unsupported_error_exit(props, operator, left, right, type1, type2, exit_result_exception) }} {% else %} NUITKA_CANNOT_GET_HERE("missing error exit annotation"); {% endif %} {% endmacro %} {% macro call_binary_slot(props, operator, nb_slot, nb_islot, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} {% if left.isSimilarOrSameTypesAsOneOf(int_desc) or right.isSimilarOrSameTypesAsOneOf(int_desc) %} {{ int_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(long_desc) or right.isSimilarOrSameTypesAsOneOf(long_desc) %} {{ long_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(float_desc) or right.isSimilarOrSameTypesAsOneOf(float_desc) %} {{ float_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(str_desc) or right.isSimilarOrSameTypesAsOneOf(str_desc) %} {{ str_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(unicode_desc) or right.isSimilarOrSameTypesAsOneOf(unicode_desc) %} {{ unicode_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(bytes_desc) or right.isSimilarOrSameTypesAsOneOf(bytes_desc) %} {{ bytes_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(tuple_desc) or right.isSimilarOrSameTypesAsOneOf(tuple_desc) %} {{ tuple_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(list_desc) or right.isSimilarOrSameTypesAsOneOf(list_desc) %} {{ list_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% elif left.isSimilarOrSameTypesAsOneOf(set_desc) or right.isSimilarOrSameTypesAsOneOf(set_desc) %} {{ set_slot(props, operator, nb_slot, nb_islot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) }} {% else %} {{ 0/0 }} {% endif %} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationBinary.c.j20000600000372100037210000001547214166627112032422 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% from 'HelperSlotsInt.c.j2' import int_slot %} {% from 'HelperSlotsBinary.c.j2' import binary_operation, call_binary_slot with context %} {% macro binary_fallback_operation(props, target, left, right, type1, type2) %} #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif {% set props = {"exits": {}} %} {{ binary_operation(props, operator, nb_slot, left, right, "type1", "type2", "operand1", "operand2", "exit_binary_result_object", "exit_binary_result_cbool_ok", "exit_binary_result_nbool", "exit_binary_exception") }} {% if "exit_binary_result_object" in props["exits"] %} exit_binary_result_object: {{ target.getReturnFromObjectExpressionCode("obj_result") }} {% endif %} {% if "exit_binary_result_cbool_ok" in props["exits"] %} exit_binary_result_cbool_ok: return cbool_result; {% endif %} {% if "exit_binary_exception" in props["exits"] %} {% if "all" not in props["exits"]["exit_binary_exception"] %} #if PYTHON_VERSION < 0x300 {% endif %} exit_binary_exception: return {{target.getExceptionResultIndicatorValue()}}; {% if "all" not in props["exits"]["exit_binary_exception"] %} #endif {% endif %} {% endif %} {% endmacro %} {% if not left.hasTypeSpecializationCode(right, nb_slot, sq_slot) and left.getSameTypeType(right).hasSameTypeOperationSpecializationCode(right.getSameTypeType(left), nb_slot, sq_slot) %} static HEDLEY_NEVER_INLINE {{target.getTypeDecl()}} __BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; {{ binary_fallback_operation(props, target, left, right, "type1", "type2") }} } {% endif %} static {{target.getTypeDecl()}} _BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{ left.getCheckValueCode("operand1") }} {{ right.getCheckValueCode("operand2") }} {% if left.type_name == "object" and right.type_name == "object" %} {# CPython2 treats integer values with fast path. #} #if PYTHON_VERSION < 0x300 if ({{ left.getIntCheckExpression("operand1") }} && {{ right.getIntCheckExpression("operand2") }}) { {{target.getTypeDecl()}} result; {% set props = {"exits": {}} %} {{ int_slot(props, operator, nb_slot, target, int_desc, int_desc, "result", "operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return result; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return {{target.getExceptionResultIndicatorValue()}}; {% endif %} } #endif {% endif %} {% if left.hasTypeSpecializationCode(right, nb_slot, sq_slot) %} {% set props = {"exits": {}} %} {{ target.getTypeDecl() }} result; {{ call_binary_slot(props, operator, nb_slot, None, left, right, "result", "operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return result; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return {{target.getExceptionResultIndicatorValue()}}; {% endif %} {% elif left.getSameTypeType(right).hasSameTypeOperationSpecializationCode(right.getSameTypeType(left), nb_slot, sq_slot) %} {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; if ({{ left.getTypeIdenticalCheckExpression(right, "type1", "type2") }}) { assert(type1 == type2); {{target.getTypeDecl()}} result; {# There is special code for same types. #} // return _BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getSameTypeType(right).getHelperCodeName()}}_{{right.getSameTypeType(left).getHelperCodeName()}}(operand1, operand2); {{ call_binary_slot(props, operator, nb_slot, nb_slot, left.getSameTypeType(right), right.getSameTypeType(left), "result", "operand1", "operand2", "exit_result_ok", "exit_result_exception") }} exit_result_ok: return result; {% if "exit_result_exception" in props["exits"] %} exit_result_exception: return {{target.getExceptionResultIndicatorValue()}}; {% endif %} } return __BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}(operand1, operand2); {% else %} {% set props = {"exits": {}} %} PyTypeObject *type1 = {{ left.getTypeValueExpression("operand1") }}; PyTypeObject *type2 = {{ right.getTypeValueExpression("operand2") }}; {{ binary_fallback_operation(props, target, left, right, "type1", "type2") }} {% endif %} } {{target.getTypeDecl()}} BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { return _BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}(operand1, operand2); } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonBytes.c.j20000600000372100037210000001030014166627112034300 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { {% if operand in ("==", ">=", "<=") %} bool r = true; {% else %} bool r = false; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); {% if operand in ("==", "!=") %} if (len_a != len_b) { {# Shortcut for equality/inequality, driven by length divergence. #} {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { {% if operand == "==" %} bool r = true; {% else %} bool r = false; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } else { {% if operand == "==" %} bool r = false; {% else %} bool r = true; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } } {% else %} Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c==0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } {% if operand == "<" %} c = c < 0; {% elif operand == "<=" %} c = c <= 0; {% elif operand == ">" %} c = c > 0; {% elif operand == ">=" %} c = c >= 0; {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("c != 0")}}; {{target.getTakeReferenceStatement("result")}} return result; {% endif %} } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperOperationComparisonLong.c.j20000600000372100037210000001076314166627112034126 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} static {{target.getTypeDecl()}} COMPARE_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) { {{left.getCheckValueCode("operand1")}} {{right.getCheckValueCode("operand2")}} PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; {% if operand == "==" %} if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = false; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = false; break; } } } {% elif operand == "!=" %} if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = true; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = true; break; } } } {% elif operand == "<=" %} if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } {% elif operand == ">=" %} if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } {% elif operand == "<" %} if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } {% elif operand == ">" %} if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } {% else %} # error unknown operand {{operand}} {% endif %} // Convert to target type. {{target.getTypeDecl()}} result = {{target.getToValueFromBoolExpression("r")}}; {{target.getTakeReferenceStatement("result")}} return result; } Nuitka-0.6.19.1/nuitka/codegen/templates_c/HelperSlotsUnicode.c.j20000600000372100037210000000614514166627112031725 0ustar nuitka-buildslavenuitka-buildslave00000000000000{# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com #} {# #} {# Part of "Nuitka", an optimizing Python compiler that is compatible and #} {# integrates with CPython, but also works on its own. #} {# #} {# Licensed under the Apache License, Version 2.0 (the "License"); #} {# you may not use this file except in compliance with the License. #} {# You may obtain a copy of the License at #} {# #} {# http://www.apache.org/licenses/LICENSE-2.0 #} {# #} {# Unless required by applicable law or agreed to in writing, software #} {# distributed under the License is distributed on an "AS IS" BASIS, #} {# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #} {# See the License for the specific language governing permissions and #} {# limitations under the License. #} {# #} {% from 'HelperSlotsCommon.c.j2' import goto_exit %} {% macro unicode_slot(props, operator, nb_slot, target, left, right, result, operand1, operand2, exit_result_ok, exit_result_exception) %} // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; {# TODO: Could and should in-line and specialize this per slot too. #} {% if nb_slot == "nb_add" %} {% if left.type_name == "unicode" == right.type_name %} PyObject *x = UNICODE_CONCAT({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *x = {{ left.getSlotCallExpression("sq_concat", "PyUnicode_Type.tp_as_sequence->sq_concat", operand1, operand2) }}; assert(x != Py_NotImplemented); {% endif %} {% elif nb_slot == "nb_multiply" %} PyObject *x = {{ left.getSlotCallExpression("sq_repeat", "PyUnicode_Type.tp_as_sequence->sq_repeat", operand1, operand2) }}; assert(x != Py_NotImplemented); {% elif nb_slot == "nb_remainder" %} PyObject *x = PyUnicode_Format({{ operand1 }}, {{ operand2 }}); {% else %} PyObject *x = {{ left.getSlotCallExpression(nb_slot, "PyUnicode_Type.tp_as_number->" + nb_slot, operand1, operand2) }}; assert(x != Py_NotImplemented); {% endif %} {{ goto_exit(props, "exit_result_object", "x") }} exit_result_object: if (unlikely(obj_result == NULL)) { {{ goto_exit(props, exit_result_exception) }} } {% if target %} {{ target.getAssignFromObjectExpressionCode(result, "obj_result") }} {% else %} {# TODO: Check the reference we were handed down and do it in-place really. #} // We got an object handed, that we have to release. Py_DECREF({{ operand1 }}); {{ operand1 }} = obj_result; {% endif %} {{ goto_exit(props, exit_result_ok) }} {% endmacro %} Nuitka-0.6.19.1/nuitka/codegen/HelperDefinitions.py0000600000372100037210000005360214166627112027161 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Shared definitions of what helpers are available. These are functions to work with helper names, as well as sets of functions to generate specialized code variants for. Note: These are ordered, so we can define the order they are created in the code generation of specialized helpers, as this set is used for input there too. """ from nuitka.containers.oset import OrderedSet def parseTypesFromHelper(helper_name): """Function to parse helper names.""" if "_INPLACE" not in helper_name: target_code = helper_name.split("_")[3] left_code = helper_name.split("_")[4] right_code = helper_name.split("_")[5] else: target_code = None left_code = helper_name.split("_")[3] right_code = helper_name.split("_")[4] return target_code, left_code, right_code def deriveInplaceFromBinaryOperations(operations_set): """Derive the in-place operations from the binary ones. These can largely be the same, or should be, and keeping them inline is easier when generating them. Obviously the templates might both need changes to optimize equally well for all variants. """ if not operations_set: return None operation = next(iter(operations_set)).split("_")[2] return OrderedSet( helper_name.replace(operation + "_OBJECT", operation) + "_INPLACE" for helper_name in operations_set if parseTypesFromHelper(helper_name)[0] == "OBJECT" if "CLONG" not in parseTypesFromHelper( helper_name ) # TODO: In-place template must be enhanced for these. ) def buildOrderedSet(*producers): values = [] for producer in producers: values.extend(producer) return OrderedSet(values) def makeTypeOps(op_code, type_name, include_nbool): yield "BINARY_OPERATION_%s_OBJECT_%s_%s" % (op_code, type_name, type_name) yield "BINARY_OPERATION_%s_OBJECT_OBJECT_%s" % (op_code, type_name) yield "BINARY_OPERATION_%s_OBJECT_%s_OBJECT" % (op_code, type_name) if include_nbool: for helper in makeTypeOpsNbool(op_code, type_name): yield helper def makeTypeOpsNbool(op_code, type_name): yield "BINARY_OPERATION_%s_NBOOL_%s_%s" % (op_code, type_name, type_name) yield "BINARY_OPERATION_%s_NBOOL_OBJECT_%s" % (op_code, type_name) yield "BINARY_OPERATION_%s_NBOOL_%s_OBJECT" % (op_code, type_name) def makeFriendOps(op_code, include_nbool, *type_names): for type_name1 in type_names: for type_name2 in type_names: if type_name1 == type_name2: continue yield "BINARY_OPERATION_%s_OBJECT_%s_%s" % (op_code, type_name1, type_name2) yield "BINARY_OPERATION_%s_OBJECT_%s_%s" % (op_code, type_name2, type_name1) if include_nbool: yield "BINARY_OPERATION_%s_NBOOL_%s_%s" % ( op_code, type_name1, type_name2, ) yield "BINARY_OPERATION_%s_NBOOL_%s_%s" % ( op_code, type_name2, type_name1, ) def makeDefaultOps(op_code, include_nbool): yield "BINARY_OPERATION_%s_OBJECT_OBJECT_OBJECT" % op_code if include_nbool: yield "BINARY_OPERATION_%s_NBOOL_OBJECT_OBJECT" % op_code def makeNonContainerMathOps(op_code): for type_name in "TUPLE", "LIST", "DICT", "SET", "FROZENSET": if "BIT" in op_code and type_name == "SET": continue if "SUB" in op_code and type_name == "SET": continue for value in makeTypeOps(op_code, type_name, include_nbool=True): yield value specialized_add_helpers_set = buildOrderedSet( makeTypeOps("ADD", "INT", include_nbool=True), makeTypeOps("ADD", "LONG", include_nbool=True), makeTypeOps("ADD", "FLOAT", include_nbool=True), makeTypeOps("ADD", "STR", include_nbool=False), makeTypeOps("ADD", "UNICODE", include_nbool=False), makeTypeOps("ADD", "BYTES", include_nbool=False), makeTypeOps("ADD", "TUPLE", include_nbool=False), makeTypeOps("ADD", "LIST", include_nbool=True), # These are friends naturally, they all add with another makeFriendOps("ADD", True, "INT", "LONG", "FLOAT"), # TODO: Make CLONG ready to join above group. # makeFriendOps("ADD", True, "INT", "CLONG"), # These are friends too. makeFriendOps("ADD", True, "STR", "UNICODE"), # Default implementation. makeDefaultOps("ADD", include_nbool=True), ) nonspecialized_add_helpers_set = buildOrderedSet( makeTypeOpsNbool("ADD", "STR"), # Not really likely to be used. makeTypeOpsNbool("ADD", "UNICODE"), # Not really likely to be used. makeTypeOpsNbool("ADD", "BYTES"), # Not really likely to be used. makeTypeOpsNbool("ADD", "TUPLE"), # Not really likely to be used. ) specialized_sub_helpers_set = buildOrderedSet( makeTypeOps("SUB", "INT", include_nbool=True), makeTypeOps("SUB", "LONG", include_nbool=True), makeTypeOps("SUB", "FLOAT", include_nbool=True), # These are friends naturally, they all sub with another makeFriendOps("SUB", True, "INT", "LONG", "FLOAT"), makeDefaultOps("SUB", include_nbool=True), ) # These made no sense to specialize for, nothing to gain. nonspecialized_sub_helpers_set = buildOrderedSet( makeTypeOps("SUB", "STR", include_nbool=True), makeTypeOps("SUB", "UNICODE", include_nbool=True), makeTypeOps("SUB", "BYTES", include_nbool=True), makeNonContainerMathOps("SUB"), ) specialized_mult_helpers_set = buildOrderedSet( makeTypeOps("MULT", "INT", include_nbool=True), makeTypeOps("MULT", "LONG", include_nbool=True), makeTypeOps("MULT", "FLOAT", include_nbool=True), ( "BINARY_OPERATION_MULT_OBJECT_CLONG_CLONG", "BINARY_OPERATION_MULT_OBJECT_INT_CLONG", "BINARY_OPERATION_MULT_OBJECT_CLONG_INT", # "BINARY_OPERATION_MULT_OBJECT_LONG_CLONG", # "BINARY_OPERATION_MULT_OBJECT_CLONG_LONG", "BINARY_OPERATION_MULT_OBJECT_OBJECT_STR", "BINARY_OPERATION_MULT_OBJECT_STR_OBJECT", "BINARY_OPERATION_MULT_OBJECT_INT_STR", "BINARY_OPERATION_MULT_OBJECT_STR_INT", "BINARY_OPERATION_MULT_OBJECT_LONG_STR", "BINARY_OPERATION_MULT_OBJECT_STR_LONG", "BINARY_OPERATION_MULT_OBJECT_OBJECT_UNICODE", "BINARY_OPERATION_MULT_OBJECT_UNICODE_OBJECT", "BINARY_OPERATION_MULT_OBJECT_INT_UNICODE", "BINARY_OPERATION_MULT_OBJECT_UNICODE_INT", "BINARY_OPERATION_MULT_OBJECT_LONG_UNICODE", "BINARY_OPERATION_MULT_OBJECT_UNICODE_LONG", "BINARY_OPERATION_MULT_OBJECT_OBJECT_TUPLE", "BINARY_OPERATION_MULT_OBJECT_TUPLE_OBJECT", "BINARY_OPERATION_MULT_OBJECT_INT_TUPLE", "BINARY_OPERATION_MULT_OBJECT_TUPLE_INT", "BINARY_OPERATION_MULT_OBJECT_LONG_TUPLE", "BINARY_OPERATION_MULT_OBJECT_TUPLE_LONG", "BINARY_OPERATION_MULT_OBJECT_OBJECT_LIST", "BINARY_OPERATION_MULT_OBJECT_LIST_OBJECT", "BINARY_OPERATION_MULT_OBJECT_INT_LIST", "BINARY_OPERATION_MULT_OBJECT_LIST_INT", "BINARY_OPERATION_MULT_OBJECT_LONG_LIST", "BINARY_OPERATION_MULT_OBJECT_LIST_LONG", "BINARY_OPERATION_MULT_OBJECT_OBJECT_BYTES", "BINARY_OPERATION_MULT_OBJECT_BYTES_OBJECT", "BINARY_OPERATION_MULT_OBJECT_LONG_BYTES", "BINARY_OPERATION_MULT_OBJECT_BYTES_LONG", ), # These are friends naturally, they all mul with another makeFriendOps("MULT", True, "INT", "LONG", "FLOAT"), makeDefaultOps("MULT", include_nbool=True), ) nonspecialized_mult_helpers_set = None specialized_truediv_helpers_set = buildOrderedSet( makeTypeOps("TRUEDIV", "INT", include_nbool=True), makeTypeOps("TRUEDIV", "LONG", include_nbool=True), makeTypeOps("TRUEDIV", "FLOAT", include_nbool=True), # These are friends naturally, they div mul with another makeFriendOps("TRUEDIV", True, "INT", "LONG", "FLOAT"), makeDefaultOps("TRUEDIV", include_nbool=True), ) nonspecialized_truediv_helpers_set = buildOrderedSet( makeTypeOps("TRUEDIV", "UNICODE", include_nbool=True), makeTypeOps("TRUEDIV", "STR", include_nbool=True), makeTypeOps("TRUEDIV", "BYTES", include_nbool=True), makeNonContainerMathOps("TRUEDIV"), ) specialized_olddiv_helpers_set = OrderedSet( helper.replace("TRUEDIV", "OLDDIV") for helper in specialized_truediv_helpers_set ) nonspecialized_olddiv_helpers_set = OrderedSet( helper.replace("TRUEDIV", "OLDDIV") for helper in nonspecialized_truediv_helpers_set ) specialized_floordiv_helpers_set = OrderedSet( helper.replace("TRUEDIV", "FLOORDIV") for helper in specialized_truediv_helpers_set ) nonspecialized_floordiv_helpers_set = OrderedSet( helper.replace("TRUEDIV", "FLOORDIV") for helper in nonspecialized_truediv_helpers_set ) specialized_mod_helpers_set = buildOrderedSet( makeTypeOps("MOD", "INT", include_nbool=True), makeTypeOps("MOD", "LONG", include_nbool=True), makeTypeOps("MOD", "FLOAT", include_nbool=True), # These are friends naturally, they mod with another makeFriendOps("MOD", True, "INT", "LONG", "FLOAT"), ( # String interpolation with STR: "BINARY_OPERATION_MOD_OBJECT_STR_INT", "BINARY_OPERATION_MOD_OBJECT_STR_LONG", "BINARY_OPERATION_MOD_OBJECT_STR_FLOAT", "BINARY_OPERATION_MOD_OBJECT_STR_STR", "BINARY_OPERATION_MOD_OBJECT_STR_UNICODE", "BINARY_OPERATION_MOD_OBJECT_STR_TUPLE", "BINARY_OPERATION_MOD_OBJECT_STR_LIST", "BINARY_OPERATION_MOD_OBJECT_STR_DICT", "BINARY_OPERATION_MOD_OBJECT_STR_OBJECT", # String formatting with UNICODE: "BINARY_OPERATION_MOD_OBJECT_UNICODE_INT", "BINARY_OPERATION_MOD_OBJECT_UNICODE_LONG", "BINARY_OPERATION_MOD_OBJECT_UNICODE_FLOAT", "BINARY_OPERATION_MOD_OBJECT_UNICODE_STR", "BINARY_OPERATION_MOD_OBJECT_UNICODE_BYTES", "BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE", "BINARY_OPERATION_MOD_OBJECT_UNICODE_TUPLE", "BINARY_OPERATION_MOD_OBJECT_UNICODE_LIST", "BINARY_OPERATION_MOD_OBJECT_UNICODE_DICT", "BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT", # String formatting with BYTES: "BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES", "BINARY_OPERATION_MOD_OBJECT_BYTES_LONG", "BINARY_OPERATION_MOD_OBJECT_BYTES_FLOAT", "BINARY_OPERATION_MOD_OBJECT_BYTES_UNICODE", "BINARY_OPERATION_MOD_OBJECT_BYTES_TUPLE", "BINARY_OPERATION_MOD_OBJECT_BYTES_LIST", "BINARY_OPERATION_MOD_OBJECT_BYTES_DICT", "BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT", # String formatting with OBJECT: "BINARY_OPERATION_MOD_OBJECT_OBJECT_STR", "BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES", "BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE", "BINARY_OPERATION_MOD_OBJECT_OBJECT_TUPLE", "BINARY_OPERATION_MOD_OBJECT_OBJECT_LIST", "BINARY_OPERATION_MOD_OBJECT_OBJECT_DICT", # Default implementation. "BINARY_OPERATION_MOD_OBJECT_OBJECT_OBJECT", ), makeDefaultOps("MOD", include_nbool=True), ) nonspecialized_mod_helpers_set = buildOrderedSet( ( "BINARY_OPERATION_MOD_OBJECT_TUPLE_OBJECT", "BINARY_OPERATION_MOD_OBJECT_LIST_OBJECT", # String formatting with STR: "BINARY_OPERATION_MOD_NBOOL_STR_INT", "BINARY_OPERATION_MOD_NBOOL_STR_LONG", "BINARY_OPERATION_MOD_NBOOL_STR_FLOAT", "BINARY_OPERATION_MOD_NBOOL_STR_STR", "BINARY_OPERATION_MOD_NBOOL_STR_UNICODE", "BINARY_OPERATION_MOD_NBOOL_STR_TUPLE", "BINARY_OPERATION_MOD_NBOOL_STR_LIST", "BINARY_OPERATION_MOD_NBOOL_STR_DICT", "BINARY_OPERATION_MOD_NBOOL_STR_OBJECT", # String formatting with UNICODE: "BINARY_OPERATION_MOD_NBOOL_UNICODE_INT", "BINARY_OPERATION_MOD_NBOOL_UNICODE_LONG", "BINARY_OPERATION_MOD_NBOOL_UNICODE_FLOAT", "BINARY_OPERATION_MOD_NBOOL_UNICODE_STR", "BINARY_OPERATION_MOD_NBOOL_UNICODE_BYTES", "BINARY_OPERATION_MOD_NBOOL_UNICODE_UNICODE", "BINARY_OPERATION_MOD_NBOOL_UNICODE_TUPLE", "BINARY_OPERATION_MOD_NBOOL_UNICODE_LIST", "BINARY_OPERATION_MOD_NBOOL_UNICODE_DICT", "BINARY_OPERATION_MOD_NBOOL_UNICODE_OBJECT", ) ) specialized_imod_helpers_set = deriveInplaceFromBinaryOperations( specialized_mod_helpers_set ) nonspecialized_imod_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_mod_helpers_set ) specialized_bitor_helpers_set = buildOrderedSet( makeTypeOps("BITOR", "LONG", include_nbool=True), makeTypeOps("BITOR", "INT", include_nbool=True), makeFriendOps("BITOR", True, "INT", "LONG"), ( # Set containers can do this "BINARY_OPERATION_BITOR_OBJECT_SET_SET", "BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET", "BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT", ), makeDefaultOps("BITOR", include_nbool=True), ) nonspecialized_bitor_helpers_set = buildOrderedSet( makeTypeOps("BITOR", "FLOAT", include_nbool=True), makeNonContainerMathOps("BITOR"), makeTypeOps("BITOR", "UNICODE", include_nbool=True), makeTypeOps("BITOR", "STR", include_nbool=True), makeTypeOps("BITOR", "BYTES", include_nbool=True), ) specialized_bitand_helpers_set = OrderedSet( helper.replace("_BITOR_", "_BITAND_") for helper in specialized_bitor_helpers_set ) nonspecialized_bitand_helpers_set = OrderedSet( helper.replace("_BITOR_", "_BITAND_") for helper in nonspecialized_bitor_helpers_set ) specialized_bitxor_helpers_set = OrderedSet( helper.replace("_BITOR_", "_BITXOR_") for helper in specialized_bitor_helpers_set ) nonspecialized_bitxor_helpers_set = OrderedSet( helper.replace("_BITOR_", "_BITXOR_") for helper in nonspecialized_bitor_helpers_set ) specialized_lshift_helpers_set = OrderedSet( helper.replace("_BITOR_", "_LSHIFT_") for helper in specialized_bitor_helpers_set if "_SET" not in helper if "_TUPLE" not in helper ) nonspecialized_lshift_helpers_set = buildOrderedSet( makeTypeOps("BITOR", "FLOAT", include_nbool=True), makeNonContainerMathOps("BITOR") ) nonspecialized_lshift_helpers_set = OrderedSet( helper.replace("_BITOR_", "_LSHIFT_") for helper in nonspecialized_bitor_helpers_set ) specialized_rshift_helpers_set = OrderedSet( helper.replace("_LSHIFT_", "_RSHIFT_") for helper in specialized_lshift_helpers_set ) nonspecialized_rshift_helpers_set = OrderedSet( helper.replace("_LSHIFT_", "_RSHIFT_") for helper in nonspecialized_lshift_helpers_set ) specialized_pow_helpers_set = OrderedSet( ( # Float is used by other types for ** operations. "BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT", "BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT", "BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT", "BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT", "BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT", "BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT", "BINARY_OPERATION_POW_OBJECT_LONG_LONG", "BINARY_OPERATION_POW_NBOOL_LONG_LONG", "BINARY_OPERATION_POW_OBJECT_OBJECT_LONG", "BINARY_OPERATION_POW_NBOOL_OBJECT_LONG", "BINARY_OPERATION_POW_OBJECT_LONG_OBJECT", "BINARY_OPERATION_POW_NBOOL_LONG_OBJECT", # TODO: Enable these later. # "BINARY_OPERATION_POW_OBJECT_LONG_FLOAT", # "BINARY_OPERATION_POW_NBOOL_LONG_FLOAT", "BINARY_OPERATION_POW_OBJECT_INT_INT", "BINARY_OPERATION_POW_NBOOL_INT_INT", "BINARY_OPERATION_POW_OBJECT_OBJECT_INT", "BINARY_OPERATION_POW_NBOOL_OBJECT_INT", "BINARY_OPERATION_POW_OBJECT_INT_OBJECT", "BINARY_OPERATION_POW_NBOOL_INT_OBJECT", "BINARY_OPERATION_POW_OBJECT_LONG_INT", "BINARY_OPERATION_POW_NBOOL_LONG_INT", "BINARY_OPERATION_POW_OBJECT_INT_LONG", "BINARY_OPERATION_POW_NBOOL_INT_LONG", # Default implementation. "BINARY_OPERATION_POW_OBJECT_OBJECT_OBJECT", "BINARY_OPERATION_POW_NBOOL_OBJECT_OBJECT", ) ) nonspecialized_pow_helpers_set = buildOrderedSet( makeTypeOps("POW", "STR", include_nbool=True), makeTypeOps("POW", "UNICODE", include_nbool=True), makeTypeOps("POW", "BYTES", include_nbool=True), makeNonContainerMathOps("POW"), ) specialized_divmod_helpers_set = buildOrderedSet( makeTypeOps("DIVMOD", "INT", include_nbool=False), makeTypeOps("DIVMOD", "LONG", include_nbool=False), makeTypeOps("DIVMOD", "FLOAT", include_nbool=False), # These are friends naturally, they mod with another # makeFriendOps("DIVMOD", False, "INT", "LONG", "FLOAT"), makeDefaultOps("DIVMOD", include_nbool=False), ) nonspecialized_divmod_helpers_set = buildOrderedSet( makeTypeOpsNbool("DIVMOD", "INT"), makeTypeOpsNbool("DIVMOD", "LONG"), makeTypeOpsNbool("DIVMOD", "FLOAT"), makeTypeOps("DIVMOD", "UNICODE", include_nbool=True), makeTypeOps("DIVMOD", "STR", include_nbool=True), makeTypeOps("DIVMOD", "BYTES", include_nbool=True), makeNonContainerMathOps("DIVMOD"), ) assert ( "BINARY_OPERATION_DIVMOD_OBJECT_TUPLE_OBJECT" in nonspecialized_divmod_helpers_set ) specialized_matmult_helpers_set = buildOrderedSet( makeTypeOps("MATMULT", "LONG", include_nbool=False), makeTypeOps("MATMULT", "FLOAT", include_nbool=False), makeDefaultOps("MATMULT", include_nbool=False), ) nonspecialized_matmult_helpers_set = buildOrderedSet( makeTypeOpsNbool("MATMULT", "LONG"), makeTypeOpsNbool("MATMULT", "FLOAT"), makeTypeOps("MATMULT", "TUPLE", include_nbool=True), makeTypeOps("MATMULT", "LIST", include_nbool=True), makeTypeOps("MATMULT", "DICT", include_nbool=True), makeTypeOps("MATMULT", "BYTES", include_nbool=True), makeTypeOps("MATMULT", "UNICODE", include_nbool=True), ) specialized_iadd_helpers_set = buildOrderedSet( deriveInplaceFromBinaryOperations(specialized_add_helpers_set), ("BINARY_OPERATION_ADD_LIST_TUPLE_INPLACE",), ) nonspecialized_iadd_helpers_set = buildOrderedSet( deriveInplaceFromBinaryOperations(nonspecialized_add_helpers_set), ( "BINARY_OPERATION_ADD_LIST_STR_INPLACE", "BINARY_OPERATION_ADD_LIST_BYTES_INPLACE", "BINARY_OPERATION_ADD_LIST_BYTEARRAY_INPLACE", "BINARY_OPERATION_ADD_LIST_UNICODE_INPLACE", "BINARY_OPERATION_ADD_LIST_SET_INPLACE", # semi useful only "BINARY_OPERATION_ADD_LIST_FROZENSET_INPLACE", "BINARY_OPERATION_ADD_LIST_DICT_INPLACE", ), ) specialized_isub_helpers_set = deriveInplaceFromBinaryOperations( specialized_sub_helpers_set ) nonspecialized_isub_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_sub_helpers_set ) specialized_imult_helpers_set = deriveInplaceFromBinaryOperations( specialized_mult_helpers_set ) nonspecialized_imult_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_mult_helpers_set ) specialized_ibitor_helpers_set = deriveInplaceFromBinaryOperations( specialized_bitor_helpers_set ) nonspecialized_ibitor_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_bitor_helpers_set ) specialized_ibitand_helpers_set = deriveInplaceFromBinaryOperations( specialized_bitand_helpers_set ) nonspecialized_ibitand_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_bitand_helpers_set ) specialized_ibitxor_helpers_set = deriveInplaceFromBinaryOperations( specialized_bitxor_helpers_set ) nonspecialized_ibitxor_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_bitxor_helpers_set ) specialized_ilshift_helpers_set = deriveInplaceFromBinaryOperations( specialized_lshift_helpers_set ) nonspecialized_ilshift_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_lshift_helpers_set ) specialized_irshift_helpers_set = deriveInplaceFromBinaryOperations( specialized_rshift_helpers_set ) nonspecialized_irshift_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_rshift_helpers_set ) specialized_ifloordiv_helpers_set = deriveInplaceFromBinaryOperations( specialized_floordiv_helpers_set ) nonspecialized_ifloordiv_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_floordiv_helpers_set ) specialized_itruediv_helpers_set = deriveInplaceFromBinaryOperations( specialized_truediv_helpers_set ) nonspecialized_itruediv_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_truediv_helpers_set ) specialized_iolddiv_helpers_set = deriveInplaceFromBinaryOperations( specialized_olddiv_helpers_set ) nonspecialized_iolddiv_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_olddiv_helpers_set ) specialized_ipow_helpers_set = deriveInplaceFromBinaryOperations( specialized_pow_helpers_set ) nonspecialized_ipow_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_pow_helpers_set ) specialized_imatmult_helpers_set = deriveInplaceFromBinaryOperations( specialized_matmult_helpers_set ) nonspecialized_imatmult_helpers_set = deriveInplaceFromBinaryOperations( nonspecialized_matmult_helpers_set ) def getSpecializedOperations(operator): return globals()["specialized_%s_helpers_set" % operator.lower()] def getNonSpecializedOperations(operator): return globals()["nonspecialized_%s_helpers_set" % operator.lower()] def getCodeNameForOperation(operator): return operator[1:].upper() if operator[0] == "I" else operator.upper() Nuitka-0.6.19.1/nuitka/codegen/CodeObjectCodes.py0000600000372100037210000001073214166627112026522 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for code objects. Right now only the creation is done here. But more should be added later on. """ import os from nuitka import Options def getCodeObjectsDeclCode(context): statements = [] for _code_object_key, code_identifier in context.getCodeObjects(): declaration = "static PyCodeObject *%s;" % code_identifier statements.append(declaration) if context.getOwner().getFullName() == "__main__": statements.append('/* For use in "MainProgram.c". */') statements.append("PyCodeObject *codeobj_main = NULL;") return statements def _getMakeCodeObjectArgs(code_object_handle, context): """Code objects have many flags for creation. This is also version dependent, but we hide this behind macros that ignore some arguments. """ co_flags = [] if code_object_handle.co_kind in ("Module", "Class", "Function"): pass elif code_object_handle.co_kind == "Generator": co_flags.append("CO_GENERATOR") elif code_object_handle.co_kind == "Coroutine": co_flags.append("CO_COROUTINE") elif code_object_handle.co_kind == "Asyncgen": co_flags.append("CO_ASYNC_GENERATOR") else: assert False, code_object_handle.co_kind if code_object_handle.is_optimized: co_flags.append("CO_OPTIMIZED") if code_object_handle.co_new_locals: co_flags.append("CO_NEWLOCALS") if code_object_handle.co_has_starlist: co_flags.append("CO_VARARGS") if code_object_handle.co_has_stardict: co_flags.append("CO_VARKEYWORDS") if not code_object_handle.co_freevars: co_flags.append("CO_NOFREE") co_flags.extend(code_object_handle.future_flags) return ( code_object_handle.line_number, " | ".join(co_flags) or "0", context.getConstantCode(constant=code_object_handle.co_name), context.getConstantCode(constant=code_object_handle.co_varnames) if code_object_handle.co_varnames else "NULL", context.getConstantCode(constant=code_object_handle.co_freevars) if code_object_handle.co_freevars else "NULL", code_object_handle.co_argcount, code_object_handle.co_kwonlyargcount, code_object_handle.co_posonlyargcount, ) def getCodeObjectsInitCode(context): # There is a bit of details to this, and we are making some optimizations as # well as customization to what path should be put there. statements = [] code_objects = context.getCodeObjects() # Create the always identical, but dynamic filename first thing. module_filename = context.getOwner().getRunTimeFilename() # We do not care about release of this object, as code object live # forever anyway. if Options.getFileReferenceMode() == "frozen" or os.path.isabs(module_filename): template = "module_filename_obj = %s; CHECK_OBJECT(module_filename_obj);" else: template = "module_filename_obj = MAKE_RELATIVE_PATH(%s); CHECK_OBJECT(module_filename_obj);" statements.append(template % (context.getConstantCode(constant=module_filename))) for code_object_key, code_identifier in code_objects: # Make sure the filename is always identical. assert code_object_key.co_filename == module_filename, code_object_key args = ( code_identifier, ", ".join(str(s) for s in _getMakeCodeObjectArgs(code_object_key, context)), ) code = "%s = MAKE_CODEOBJECT(module_filename_obj, %s);" % args statements.append(code) if context.getOwner().getFullName() == "__main__": if code_object_key[1] == "": statements.append("codeobj_main = %s;" % code_identifier) return statements Nuitka-0.6.19.1/nuitka/codegen/TryCodes.py0000600000372100037210000002565014166627112025304 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Try statement and related code generation. For Nuitka, all try/except and try/finally are dealt with this, where the finally block gets duplicated into handlers. So this is a common low level structure used, where exception handling and everything is made explicit. """ from nuitka import Options from .CodeHelpers import generateExpressionCode, generateStatementSequenceCode from .ErrorCodes import getMustNotGetHereCode from .ExceptionCodes import getExceptionUnpublishedReleaseCode from .IteratorCodes import getBuiltinLoopBreakNextCode from .LabelCodes import getGotoCode, getLabelCode from .VariableCodes import getVariableAssignmentCode def generateTryCode(statement, emit, context): # The try construct is the most complex for code generation. We may need to # react on break, continue, return, raise in the handlers. For exception # and return handlers, we need to be able to re-raise or re-return. # So this is full of detail stuff, pylint: disable=too-many-branches,too-many-locals,too-many-statements if generateTryNextExceptStopIterationCode(statement, emit, context): return # Get the statement sequences involved. All except the tried block can be # None. For the tried block it would be a missed optimization. Also not all # the handlers must be None, then it's also a missed optimization. tried_block = statement.subnode_tried except_handler = statement.subnode_except_handler continue_handler = statement.subnode_continue_handler break_handler = statement.subnode_break_handler return_handler = statement.subnode_return_handler tried_block_may_raise = tried_block.mayRaiseException(BaseException) assert ( tried_block_may_raise or continue_handler is not None or break_handler is not None or return_handler is not None ), statement.asXmlText() # The tried statements might raise, for which we define an escape. tried_handler_escape = context.allocateLabel("try_except_handler") if tried_block_may_raise: old_exception_escape = context.setExceptionEscape(tried_handler_escape) # The tried statements might continue, for which we define an escape. continue_handler_escape = context.allocateLabel("try_continue_handler") if continue_handler is not None: old_continue_target = context.setLoopContinueTarget(continue_handler_escape) # The tried statements might break, for which we define an escape. break_handler_escape = context.allocateLabel("try_break_handler") if break_handler is not None: old_break_target = context.setLoopBreakTarget(break_handler_escape) # The tried statements might return, for which we define an escape. return_handler_escape = context.allocateLabel("try_return_handler") if return_handler is not None: old_return_target = context.setReturnTarget(return_handler_escape) # Now the tried block can be generated, cannot be "None" or else the # optimization failed. emit("// Tried code:") generateStatementSequenceCode( statement_sequence=tried_block, emit=emit, allow_none=False, context=context ) # Restore the old escape targets as preserved above, during the handlers, # the parent handlers should be back in effect. if tried_block_may_raise: context.setExceptionEscape(old_exception_escape) if continue_handler: context.setLoopContinueTarget(old_continue_target) if break_handler: context.setLoopBreakTarget(old_break_target) if return_handler: context.setReturnTarget(old_return_target) post_label = None if not tried_block.isStatementAborting(): if post_label is None: post_label = context.allocateLabel("try_end") getGotoCode(post_label, emit) else: getMustNotGetHereCode(reason="tried codes exits in all cases", emit=emit) if return_handler is not None: assert tried_block.mayReturn() emit("// Return handler code:") getLabelCode(return_handler_escape, emit) # During the return value, the value being returned is in a variable, # and therefore needs to be released before being updated with a new # return value. old_return_value_release = context.setReturnReleaseMode(True) generateStatementSequenceCode( statement_sequence=return_handler, emit=emit, allow_none=False, context=context, ) context.setReturnReleaseMode(old_return_value_release) assert return_handler.isStatementAborting() if tried_block_may_raise: emit("// Exception handler code:") getLabelCode(tried_handler_escape, emit) # Need to preserve exception state. ( keeper_type, keeper_value, keeper_tb, keeper_lineno, ) = context.allocateExceptionKeeperVariables() old_keepers = context.setExceptionKeeperVariables( (keeper_type, keeper_value, keeper_tb, keeper_lineno) ) assert keeper_type is not None ( exception_type, exception_value, exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() # TODO: That normalization and chaining is only necessary if the # exception is published. emit( """\ %(keeper_type)s = %(exception_type)s; %(keeper_value)s = %(exception_value)s; %(keeper_tb)s = %(exception_tb)s; %(keeper_lineno)s = %(exception_lineno)s; %(exception_type)s = NULL; %(exception_value)s = NULL; %(exception_tb)s = NULL; %(exception_lineno)s = 0; """ % { "keeper_type": keeper_type, "keeper_value": keeper_value, "keeper_tb": keeper_tb, "keeper_lineno": keeper_lineno, "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "exception_lineno": exception_lineno, } ) generateStatementSequenceCode( statement_sequence=except_handler, emit=emit, allow_none=True, context=context, ) if except_handler is None or not except_handler.isStatementAborting(): getExceptionUnpublishedReleaseCode(emit, context) if post_label is None: post_label = context.allocateLabel("try_end") getGotoCode(post_label, emit) getMustNotGetHereCode( reason="exception handler codes exits in all cases", emit=emit ) context.setExceptionKeeperVariables(old_keepers) else: assert except_handler is None, tried_block.asXmlText() if break_handler is not None: assert tried_block.mayBreak() emit("// try break handler code:") getLabelCode(break_handler_escape, emit) generateStatementSequenceCode( statement_sequence=break_handler, emit=emit, allow_none=False, context=context, ) assert break_handler.isStatementAborting() if continue_handler is not None: assert tried_block.mayContinue() emit("// try continue handler code:") getLabelCode(continue_handler_escape, emit) generateStatementSequenceCode( statement_sequence=continue_handler, emit=emit, allow_none=False, context=context, ) assert continue_handler.isStatementAborting() emit("// End of try:") if post_label is not None: getLabelCode(post_label, emit) def generateTryNextExceptStopIterationCode(statement, emit, context): # This has many branches which mean this optimized code generation is not # applicable, we return each time. pylint: disable=too-many-branches,too-many-return-statements except_handler = statement.subnode_except_handler if except_handler is None: return False if statement.subnode_break_handler is not None: return False if statement.subnode_continue_handler is not None: return False if statement.subnode_return_handler is not None: return False tried_statements = statement.subnode_tried.subnode_statements if len(tried_statements) != 1: return False handling_statements = except_handler.subnode_statements if len(handling_statements) != 1: return False tried_statement = tried_statements[0] if not tried_statement.isStatementAssignmentVariable(): return False assign_source = tried_statement.subnode_source if not assign_source.isExpressionBuiltinNext1(): return False handling_statement = handling_statements[0] if not handling_statement.isStatementConditional(): return False yes_statements = handling_statement.subnode_yes_branch.subnode_statements no_statements = handling_statement.subnode_no_branch.subnode_statements if len(yes_statements) != 1: return False if not yes_statements[0].isStatementLoopBreak(): return False if len(no_statements) != 1: return False if not no_statements[0].isStatementReraiseException(): return False tmp_name = context.allocateTempName("next_source") generateExpressionCode( expression=assign_source.subnode_value, to_name=tmp_name, emit=emit, context=context, ) tmp_name2 = context.allocateTempName("assign_source") with context.withCurrentSourceCodeReference( assign_source.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): getBuiltinLoopBreakNextCode( to_name=tmp_name2, value=tmp_name, emit=emit, context=context ) getVariableAssignmentCode( tmp_name=tmp_name2, variable=tried_statement.getVariable(), variable_trace=tried_statement.getVariableTrace(), needs_release=None, in_place=False, emit=emit, context=context, ) if context.needsCleanup(tmp_name2): context.removeCleanupTempName(tmp_name2) return True Nuitka-0.6.19.1/nuitka/codegen/ReturnCodes.py0000600000372100037210000001216214166627112025777 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Return codes This handles code generation for return statements of normal functions and of generator functions. Also the value currently being returned, and intercepted by a try statement is accessible this way. """ from nuitka.PythonVersions import python_version from .CodeHelpers import generateExpressionCode from .ExceptionCodes import getExceptionUnpublishedReleaseCode from .LabelCodes import getGotoCode def generateReturnCode(statement, emit, context): getExceptionUnpublishedReleaseCode(emit, context) return_value = statement.subnode_expression return_value_name = context.getReturnValueName() if context.getReturnReleaseMode(): emit("CHECK_OBJECT(%s);" % return_value_name) emit("Py_DECREF(%s);" % return_value_name) generateExpressionCode( to_name=return_value_name, expression=return_value, emit=emit, context=context, ) if context.needsCleanup(return_value_name): context.removeCleanupTempName(return_value_name) else: emit("Py_INCREF(%s);" % return_value_name) getGotoCode(label=context.getReturnTarget(), emit=emit) def generateReturnedValueCode(statement, emit, context): # We don't need the statement, pylint: disable=unused-argument getExceptionUnpublishedReleaseCode(emit, context) getGotoCode(label=context.getReturnTarget(), emit=emit) def generateReturnConstantCode(statement, emit, context): getExceptionUnpublishedReleaseCode(emit, context) return_value_name = context.getReturnValueName() if context.getReturnReleaseMode(): emit("CHECK_OBJECT(%s);" % return_value_name) emit("Py_DECREF(%s);" % return_value_name) return_value_name.getCType().emitAssignmentCodeFromConstant( to_name=return_value_name, constant=statement.getConstant(), may_escape=True, emit=emit, context=context, ) if context.needsCleanup(return_value_name): context.removeCleanupTempName(return_value_name) else: emit("Py_INCREF(%s);" % return_value_name) getGotoCode(label=context.getReturnTarget(), emit=emit) def generateGeneratorReturnValueCode(statement, emit, context): if context.getOwner().isExpressionAsyncgenObjectBody(): pass elif python_version >= 0x300: return_value_name = context.getGeneratorReturnValueName() expression = statement.subnode_expression if context.getReturnReleaseMode(): emit("CHECK_OBJECT(%s);" % return_value_name) emit("Py_DECREF(%s);" % return_value_name) generateExpressionCode( to_name=return_value_name, expression=expression, emit=emit, context=context ) if context.needsCleanup(return_value_name): context.removeCleanupTempName(return_value_name) else: emit("Py_INCREF(%s);" % return_value_name) elif statement.getParentVariableProvider().needsGeneratorReturnHandling(): return_value_name = context.getGeneratorReturnValueName() generator_return_name = context.allocateTempName( "generator_return", "bool", unique=True ) emit("%s = true;" % generator_return_name) getGotoCode(context.getReturnTarget(), emit) def generateGeneratorReturnNoneCode(statement, emit, context): if context.getOwner().isExpressionAsyncgenObjectBody(): pass elif python_version >= 0x300: return_value_name = context.getGeneratorReturnValueName() if context.getReturnReleaseMode(): emit("CHECK_OBJECT(%s);" % return_value_name) emit("Py_DECREF(%s);" % return_value_name) return_value_name.getCType().emitAssignmentCodeFromConstant( to_name=return_value_name, constant=None, may_escape=False, emit=emit, context=context, ) if context.needsCleanup(return_value_name): context.removeCleanupTempName(return_value_name) else: emit("Py_INCREF(%s);" % return_value_name) elif statement.getParentVariableProvider().needsGeneratorReturnHandling(): return_value_name = context.getGeneratorReturnValueName() generator_return_name = context.allocateTempName( "generator_return", "bool", unique=True ) emit("%s = true;" % generator_return_name) getGotoCode(context.getReturnTarget(), emit) Nuitka-0.6.19.1/nuitka/codegen/TupleCodes.py0000600000372100037210000000721014166627112025607 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tuple codes """ from .CodeHelpers import ( decideConversionCheckNeeded, generateExpressionCode, withCleanupFinally, withObjectCodeTemporaryAssignment, ) from .PythonAPICodes import generateCAPIObjectCode def _areConstants(expressions): for expression in expressions: if not expression.isExpressionConstantRef(): return False if expression.isMutable(): return False return True def generateTupleCreationCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "tuple_value", expression, emit, context ) as value_name: getTupleCreationCode( to_name=value_name, elements=expression.subnode_elements, emit=emit, context=context, ) def getTupleCreationCode(to_name, elements, emit, context): if _areConstants(elements): to_name.getCType().emitAssignmentCodeFromConstant( to_name=to_name, constant=tuple(element.getCompileTimeConstant() for element in elements), # TODO: Would depend on our target being escaping. may_escape=True, emit=emit, context=context, ) else: element_name = context.allocateTempName("tuple_element") def generateElementCode(element): generateExpressionCode( to_name=element_name, expression=element, emit=emit, context=context ) # Use helper that makes sure we provide a reference. if context.needsCleanup(element_name): context.removeCleanupTempName(element_name) helper_code = "PyTuple_SET_ITEM" else: helper_code = "PyTuple_SET_ITEM0" return helper_code helper_code = generateElementCode(elements[0]) emit("%s = PyTuple_New(%d);" % (to_name, len(elements))) needs_exception_exit = any( element.mayRaiseException(BaseException) for element in elements[1:] ) with withCleanupFinally( "tuple_build", to_name, needs_exception_exit, emit, context ) as guarded_emit: emit = guarded_emit.emit for count, element in enumerate(elements): if count > 0: helper_code = generateElementCode(element) emit("%s(%s, %d, %s);" % (helper_code, to_name, count, element_name)) def generateBuiltinTupleCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PySequence_Tuple", arg_desc=(("tuple_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/templates/0000700000372100037210000000000014167275622025170 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesGeneratorFunction.py0000600000372100037210000000617114166627112033651 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Generator function (with yield) related templates. """ template_genfunc_yielder_maker_decl = """\ static PyObject *%(generator_maker_identifier)s(%(generator_creation_args)s); """ template_genfunc_yielder_body_template = """ struct %(function_identifier)s_locals { %(function_local_types)s }; static PyObject *%(function_identifier)s_context(struct Nuitka_GeneratorObject *generator, PyObject *yield_return_value) { CHECK_OBJECT(generator); assert(Nuitka_Generator_Check((PyObject *)generator)); CHECK_OBJECT_X(yield_return_value); // Heap access if used. %(heap_declaration)s // Dispatch to yield based on return label index: %(function_dispatch)s // Local variable initialization %(function_var_inits)s // Actual generator function body. %(function_body)s %(generator_exit)s } static PyObject *%(generator_maker_identifier)s(%(generator_creation_args)s) { return Nuitka_Generator_New( %(function_identifier)s_context, %(generator_module)s, %(generator_name_obj)s, #if PYTHON_VERSION >= 0x350 %(generator_qualname_obj)s, #endif %(code_identifier)s, %(closure_name)s, %(closure_count)d, sizeof(struct %(function_identifier)s_locals) ); } """ template_make_generator = """\ %(closure_copy)s %(to_name)s = %(generator_maker_identifier)s(%(args)s); """ template_make_empty_generator = """\ %(closure_copy)s %(to_name)s = Nuitka_Generator_NewEmpty( %(generator_module)s, %(generator_name_obj)s, #if PYTHON_VERSION >= 0x350 %(generator_qualname_obj)s, #endif %(code_identifier)s, %(closure_name)s, %(closure_count)d ); """ template_generator_exception_exit = """\ %(function_cleanup)s return NULL; function_exception_exit: %(function_cleanup)s\ assert(%(exception_type)s); RESTORE_ERROR_OCCURRED(%(exception_type)s, %(exception_value)s, %(exception_tb)s); return NULL; """ template_generator_noexception_exit = """\ // Return statement need not be present. %(function_cleanup)s\ return NULL; """ template_generator_return_exit = """\ NUITKA_CANNOT_GET_HERE("Generator must have exited already."); return NULL; function_return_exit: #if PYTHON_VERSION >= 0x300 generator->m_returned = %(return_value)s; #endif return NULL; """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesCoroutines.py0000600000372100037210000000537114166627112032350 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Coroutines function (await/async) related templates. """ template_coroutine_object_maker = """\ static PyObject *%(coroutine_maker_identifier)s(%(coroutine_creation_args)s); """ template_coroutine_object_body = """ struct %(function_identifier)s_locals { %(function_local_types)s }; static PyObject *%(function_identifier)s_context(struct Nuitka_CoroutineObject *coroutine, PyObject *yield_return_value) { CHECK_OBJECT(coroutine); assert(Nuitka_Coroutine_Check((PyObject *)coroutine)); // Heap access if used. %(heap_declaration)s // Dispatch to yield based on return label index: %(function_dispatch)s // Local variable initialization %(function_var_inits)s // Actual coroutine body. %(function_body)s %(coroutine_exit)s } static PyObject *%(coroutine_maker_identifier)s(%(coroutine_creation_args)s) { return Nuitka_Coroutine_New( %(function_identifier)s_context, %(coroutine_module)s, %(coroutine_name_obj)s, %(coroutine_qualname_obj)s, %(code_identifier)s, %(closure_name)s, %(closure_count)d, sizeof(struct %(function_identifier)s_locals) ); } """ template_make_coroutine = """\ %(closure_copy)s %(to_name)s = %(coroutine_maker_identifier)s(%(args)s); """ # TODO: For functions NUITKA_CANNOT_GET_HERE is injected by composing code. template_coroutine_exception_exit = """\ NUITKA_CANNOT_GET_HERE("Return statement must be present"); function_exception_exit: %(function_cleanup)s\ assert(%(exception_type)s); RESTORE_ERROR_OCCURRED(%(exception_type)s, %(exception_value)s, %(exception_tb)s); return NULL; """ template_coroutine_noexception_exit = """\ NUITKA_CANNOT_GET_HERE("Return statement must be present"); %(function_cleanup)s\ return NULL; """ template_coroutine_return_exit = """\ function_return_exit:; coroutine->m_returned = %(return_value)s; return NULL; """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesModules.py0000600000372100037210000004667114166627112031636 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Main module code templates This for the main program in case of executables, the module templates and stuff related to importing, and of course the generated code license. """ template_global_copyright = """\ /* Generated code for Python module '%(module_name)s' * created by Nuitka version %(version)s * * This code is in part copyright %(year)s Kay Hayen. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ """ template_module_body_template = r""" #include "nuitka/prelude.h" #include "nuitka/unfreezing.h" #include "__helpers.h" /* The "module_%(module_identifier)s" is a Python object pointer of module type. * * Note: For full compatibility with CPython, every module variable access * needs to go through it except for cases where the module cannot possibly * have changed in the mean time. */ PyObject *module_%(module_identifier)s; PyDictObject *moduledict_%(module_identifier)s; /* The declarations of module constants used, if any. */ static PyObject *mod_consts[%(constants_count)d]; #ifndef __NUITKA_NO_ASSERT__ static Py_hash_t mod_consts_hash[%(constants_count)d]; #endif static PyObject *module_filename_obj = NULL; /* Indicator if this modules private constants were created yet. */ static bool constants_created = false; /* Function to create module private constants. */ static void createModuleConstants(void) { if (constants_created == false) { loadConstantsBlob(&mod_consts[0], UNTRANSLATE(%(module_const_blob_name)s)); constants_created = true; #ifndef __NUITKA_NO_ASSERT__ for(int i = 0; i < %(constants_count)d; i++) { mod_consts_hash[i] = DEEP_HASH(mod_consts[i]); } #endif } } // We want to be able to initialize the "__main__" constants in any case. #if %(is_dunder_main)s void createMainModuleConstants(void) { createModuleConstants(); } #endif /* Function to verify module private constants for non-corruption. */ #ifndef __NUITKA_NO_ASSERT__ void checkModuleConstants_%(module_identifier)s(void) { // The module may not have been used at all, then ignore this. if (constants_created == false) return; for(int i = 0; i < %(constants_count)d; i++) { assert(mod_consts_hash[i] == DEEP_HASH(mod_consts[i])); CHECK_OBJECT_DEEP(mod_consts[i]); } } #endif // The module code objects. %(module_code_objects_decl)s static void createModuleCodeObjects(void) { %(module_code_objects_init)s } // The module function declarations. %(module_functions_decl)s // The module function definitions. %(module_functions_code)s extern void _initCompiledCellType(); extern void _initCompiledGeneratorType(); extern void _initCompiledFunctionType(); extern void _initCompiledMethodType(); extern void _initCompiledFrameType(); extern PyTypeObject Nuitka_Loader_Type; #ifdef _NUITKA_PLUGIN_DILL_ENABLED // Provide a way to create find a function via its C code and create it back // in another process, useful for multiprocessing extensions like dill extern void registerDillPluginTables(char const *module_name, PyMethodDef *reduce_compiled_function, PyMethodDef *create_compiled_function); function_impl_code functable_%(module_identifier)s[] = { %(module_function_table_entries)s NULL }; static char const *_reduce_compiled_function_argnames[] = { "func", NULL }; static PyObject *_reduce_compiled_function(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *func; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:reduce_compiled_function", (char **)_reduce_compiled_function_argnames, &func, NULL)) { return NULL; } if (Nuitka_Function_Check(func) == false) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "not a compiled function"); return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)func; function_impl_code *current = functable_%(module_identifier)s; int offset = 0; while (*current != NULL) { if (*current == function->m_c_code) { break; } current += 1; offset += 1; } if (*current == NULL) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "Cannot find compiled function in module."); return NULL; } PyObject *code_object_desc = PyTuple_New(6); PyTuple_SET_ITEM0(code_object_desc, 0, function->m_code_object->co_filename); PyTuple_SET_ITEM0(code_object_desc, 1, function->m_code_object->co_name); PyTuple_SET_ITEM(code_object_desc, 2, PyLong_FromLong(function->m_code_object->co_firstlineno)); PyTuple_SET_ITEM0(code_object_desc, 3, function->m_code_object->co_varnames); PyTuple_SET_ITEM(code_object_desc, 4, PyLong_FromLong(function->m_code_object->co_argcount)); PyTuple_SET_ITEM(code_object_desc, 5, PyLong_FromLong(function->m_code_object->co_flags)); CHECK_OBJECT_DEEP(code_object_desc); PyObject *result = PyTuple_New(4); PyTuple_SET_ITEM(result, 0, PyLong_FromLong(offset)); PyTuple_SET_ITEM(result, 1, code_object_desc); PyTuple_SET_ITEM0(result, 2, function->m_defaults); PyTuple_SET_ITEM0(result, 3, function->m_doc != NULL ? function->m_doc : Py_None); CHECK_OBJECT_DEEP(result); return result; } static PyMethodDef _method_def_reduce_compiled_function = {"reduce_compiled_function", (PyCFunction)_reduce_compiled_function, METH_VARARGS | METH_KEYWORDS, NULL}; static char const *_create_compiled_function_argnames[] = { "func", "code_object_desc", "defaults", "doc", NULL }; static PyObject *_create_compiled_function(PyObject *self, PyObject *args, PyObject *kwds) { CHECK_OBJECT_DEEP(args); PyObject *func; PyObject *code_object_desc; PyObject *defaults; PyObject *doc; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOO:create_compiled_function", (char **)_create_compiled_function_argnames, &func, &code_object_desc, &defaults, &doc, NULL)) { return NULL; } int offset = PyLong_AsLong(func); if (offset == -1 && ERROR_OCCURRED()) { return NULL; } if (offset > sizeof(functable_%(module_identifier)s) || offset < 0) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "Wrong offset for compiled function."); return NULL; } PyObject *filename = PyTuple_GET_ITEM(code_object_desc, 0); PyObject *function_name = PyTuple_GET_ITEM(code_object_desc, 1); PyObject *line = PyTuple_GET_ITEM(code_object_desc, 2); int line_int = PyLong_AsLong(line); assert(!ERROR_OCCURRED()); PyObject *argnames = PyTuple_GET_ITEM(code_object_desc, 3); PyObject *arg_count = PyTuple_GET_ITEM(code_object_desc, 4); int arg_count_int = PyLong_AsLong(arg_count); assert(!ERROR_OCCURRED()); PyObject *flags = PyTuple_GET_ITEM(code_object_desc, 5); int flags_int = PyLong_AsLong(flags); assert(!ERROR_OCCURRED()); PyCodeObject *code_object = MAKE_CODEOBJECT( filename, line_int, flags_int, function_name, argnames, NULL, // freevars arg_count_int, 0, // TODO: Missing kw_only_count 0 // TODO: Missing pos_only_count ); struct Nuitka_FunctionObject *result = Nuitka_Function_New( functable_%(module_identifier)s[offset], code_object->co_name, #if PYTHON_VERSION >= 0x300 NULL, // TODO: Not transferring qualname yet #endif code_object, defaults, #if PYTHON_VERSION >= 0x300 NULL, // kwdefaults are done on the outside currently NULL, // TODO: Not transferring annotations #endif module_%(module_identifier)s, doc, NULL, 0 ); return (PyObject *)result; } static PyMethodDef _method_def_create_compiled_function = { "create_compiled_function", (PyCFunction)_create_compiled_function, METH_VARARGS | METH_KEYWORDS, NULL }; #endif // Internal entry point for module code. PyObject *modulecode_%(module_identifier)s(PyObject *module, struct Nuitka_MetaPathBasedLoaderEntry const *loader_entry) { // Report entry to PGO. PGO_onModuleEntered("%(module_name)s"); // Store the module for future use. module_%(module_identifier)s = module; // Modules can be loaded again in case of errors, avoid the init being done again. static bool init_done = false; if (init_done == false) { #if defined(_NUITKA_MODULE) && %(is_top)d // In case of an extension module loaded into a process, we need to call // initialization here because that's the first and potentially only time // we are going called. // Initialize the constant values used. _initBuiltinModule(); createGlobalConstants(); /* Initialize the compiled types of Nuitka. */ _initCompiledCellType(); _initCompiledGeneratorType(); _initCompiledFunctionType(); _initCompiledMethodType(); _initCompiledFrameType(); _initSlotCompare(); #if PYTHON_VERSION >= 0x270 _initSlotIternext(); #endif patchBuiltinModule(); patchTypeComparison(); // Enable meta path based loader if not already done. #ifdef _NUITKA_TRACE PRINT_STRING("%(module_name)s: Calling setupMetaPathBasedLoader().\n"); #endif setupMetaPathBasedLoader(); #if PYTHON_VERSION >= 0x300 patchInspectModule(); #endif #endif /* The constants only used by this module are created now. */ #ifdef _NUITKA_TRACE PRINT_STRING("%(module_name)s: Calling createModuleConstants().\n"); #endif createModuleConstants(); /* The code objects used by this module are created now. */ #ifdef _NUITKA_TRACE PRINT_STRING("%(module_name)s: Calling createModuleCodeObjects().\n"); #endif createModuleCodeObjects(); init_done = true; } // PRINT_STRING("in init%(module_identifier)s\n"); moduledict_%(module_identifier)s = MODULE_DICT(module_%(module_identifier)s); #ifdef _NUITKA_PLUGIN_DILL_ENABLED registerDillPluginTables(loader_entry->name, &_method_def_reduce_compiled_function, &_method_def_create_compiled_function); #endif // Set "__compiled__" to what version information we have. UPDATE_STRING_DICT0( moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___compiled__, Nuitka_dunder_compiled_value ); // Update "__package__" value to what it ought to be. { #if %(is_dunder_main)s UPDATE_STRING_DICT0( moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___package__, %(dunder_main_package)s ); #elif %(is_package)s PyObject *module_name = GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___name__); UPDATE_STRING_DICT0( moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___package__, module_name ); #else #if PYTHON_VERSION < 0x300 PyObject *module_name = GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___name__); char const *module_name_cstr = PyString_AS_STRING(module_name); char const *last_dot = strrchr(module_name_cstr, '.'); if (last_dot != NULL) { UPDATE_STRING_DICT1( moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___package__, PyString_FromStringAndSize(module_name_cstr, last_dot - module_name_cstr) ); } #else PyObject *module_name = GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___name__); Py_ssize_t dot_index = PyUnicode_Find(module_name, const_str_dot, 0, PyUnicode_GetLength(module_name), -1); if (dot_index != -1) { UPDATE_STRING_DICT1( moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___package__, PyUnicode_Substring(module_name, 0, dot_index) ); } #endif #endif } CHECK_OBJECT(module_%(module_identifier)s); // For deep importing of a module we need to have "__builtins__", so we set // it ourselves in the same way than CPython does. Note: This must be done // before the frame object is allocated, or else it may fail. if (GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___builtins__) == NULL) { PyObject *value = (PyObject *)builtin_module; // Check if main module, not a dict then but the module itself. #if defined(_NUITKA_MODULE) || !%(is_dunder_main)s value = PyModule_GetDict(value); #endif UPDATE_STRING_DICT0(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___builtins__, value); } #if PYTHON_VERSION >= 0x300 UPDATE_STRING_DICT0(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___loader__, (PyObject *)&Nuitka_Loader_Type); #endif #if PYTHON_VERSION >= 0x340 // Set the "__spec__" value #if %(is_dunder_main)s // Main modules just get "None" as spec. UPDATE_STRING_DICT0(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___spec__, Py_None); #else // Other modules get a "ModuleSpec" from the standard mechanism. { PyObject *bootstrap_module = getImportLibBootstrapModule(); CHECK_OBJECT(bootstrap_module); PyObject *_spec_from_module = PyObject_GetAttrString(bootstrap_module, "_spec_from_module"); CHECK_OBJECT(_spec_from_module); PyObject *spec_value = CALL_FUNCTION_WITH_SINGLE_ARG(_spec_from_module, module_%(module_identifier)s); Py_DECREF(_spec_from_module); // We can assume this to never fail, or else we are in trouble anyway. // CHECK_OBJECT(spec_value); if (spec_value == NULL) { PyErr_PrintEx(0); abort(); } // Mark the execution in the "__spec__" value. SET_ATTRIBUTE(spec_value, const_str_plain__initializing, Py_True); UPDATE_STRING_DICT1(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___spec__, spec_value); } #endif #endif // Temp variables if any %(temps_decl)s // Module code. %(module_code)s // Report to PGO about leaving the module without error. PGO_onModuleExit("%(module_name)s", false); return module_%(module_identifier)s; %(module_exit)s """ template_module_external_entry_point = r""" /* Visibility definitions to make the DLL entry point exported */ #if defined(__GNUC__) #if PYTHON_VERSION < 0x300 #if defined(_WIN32) #define NUITKA_MODULE_INIT_FUNCTION __declspec(dllexport) PyMODINIT_FUNC #else #define NUITKA_MODULE_INIT_FUNCTION PyMODINIT_FUNC __attribute__((visibility("default"))) #endif #else #if defined(_WIN32) #define NUITKA_MODULE_INIT_FUNCTION __declspec(dllexport) PyObject * #else #ifdef __cplusplus #define NUITKA_MODULE_INIT_FUNCTION extern "C" __attribute__((visibility("default"))) PyObject * #else #define NUITKA_MODULE_INIT_FUNCTION __attribute__((visibility("default"))) PyObject * #endif #endif #endif #else #define NUITKA_MODULE_INIT_FUNCTION PyMODINIT_FUNC #endif /* The name of the entry point for DLLs changed between CPython versions, and * this is here to hide that. */ #if PYTHON_VERSION < 0x300 #define MOD_INIT_DECL(name) NUITKA_MODULE_INIT_FUNCTION init##name(void) #else #define MOD_INIT_DECL(name) NUITKA_MODULE_INIT_FUNCTION PyInit_##name(void) #endif #if PYTHON_VERSION >= 0x300 static struct PyModuleDef mdef_%(module_identifier)s = { PyModuleDef_HEAD_INIT, NULL, /* m_name, filled later */ NULL, /* m_doc */ -1, /* m_size */ NULL, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; #endif /* The exported interface to CPython. On import of the module, this function * gets called. It has to have an exact function name, in cases it's a shared * library export. This is hidden behind the MOD_INIT_DECL macro. */ // Actual name might be different when loaded as a package. static char const *module_full_name = "%(module_name)s"; MOD_INIT_DECL(%(module_identifier)s) { if (_Py_PackageContext != NULL) { module_full_name = _Py_PackageContext; } #if PYTHON_VERSION < 0x300 PyObject *module = Py_InitModule4( module_full_name, // Module Name NULL, // No methods initially, all are added // dynamically in actual module code only. NULL, // No "__doc__" is initially set, as it could // not contain NUL this way, added early in // actual code. NULL, // No self for modules, we don't use it. PYTHON_API_VERSION ); #else mdef_%(module_identifier)s.m_name = module_full_name; PyObject *module = PyModule_Create(&mdef_%(module_identifier)s); CHECK_OBJECT(module); bool res = Nuitka_SetModuleString(module_full_name, module); assert(res != false); #endif #if PYTHON_VERSION < 0x300 modulecode_%(module_identifier)s(module, NULL); #else PyObject *result = modulecode_%(module_identifier)s(module, NULL); return result; #endif } """ template_module_exception_exit = """\ module_exception_exit: #if defined(_NUITKA_MODULE) && %(is_top)d { PyObject *module_name = GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)const_str_plain___name__); if (module_name != NULL) { Nuitka_DelModule(module_name); } } #endif PGO_onModuleExit("%(module_identifier)s", false); RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; }""" template_module_noexception_exit = """\ }""" template_helper_impl_decl = """\ // This file contains helper functions that are automatically created from // templates. #include "nuitka/prelude.h" extern PyObject *callPythonFunction(PyObject *func, PyObject *const *args, int count); """ template_header_guard = """\ #ifndef %(header_guard_name)s #define %(header_guard_name)s %(header_body)s #endif """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesAsyncgens.py0000600000372100037210000000525314166627112032147 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Async generator (await/async + yield) related templates. """ template_asyncgen_object_maker_template = """\ static PyObject *%(asyncgen_maker_identifier)s(%(asyncgen_creation_args)s); """ template_asyncgen_object_body = """ struct %(function_identifier)s_locals { %(function_local_types)s }; static PyObject *%(function_identifier)s_context(struct Nuitka_AsyncgenObject *asyncgen, PyObject *yield_return_value) { CHECK_OBJECT(asyncgen); assert(Nuitka_Asyncgen_Check((PyObject *)asyncgen)); // Heap access if used. %(heap_declaration)s // Dispatch to yield based on return label index: %(function_dispatch)s // Local variable initialization %(function_var_inits)s // Actual asyngen body. %(function_body)s %(asyncgen_exit)s } static PyObject *%(asyncgen_maker_identifier)s(%(asyncgen_creation_args)s) { return Nuitka_Asyncgen_New( %(function_identifier)s_context, %(asyncgen_module)s, %(asyncgen_name_obj)s, %(asyncgen_qualname_obj)s, %(code_identifier)s, %(closure_name)s, %(closure_count)d, sizeof(struct %(function_identifier)s_locals) ); } """ template_make_asyncgen = """\ %(closure_copy)s %(to_name)s = %(asyncgen_maker_identifier)s(%(args)s); """ # TODO: For functions NUITKA_CANNOT_GET_HERE is injected by composing code. template_asyncgen_exception_exit = """\ NUITKA_CANNOT_GET_HERE("return must be present"); function_exception_exit: %(function_cleanup)s\ assert(%(exception_type)s); RESTORE_ERROR_OCCURRED(%(exception_type)s, %(exception_value)s, %(exception_tb)s); return NULL; """ template_asyncgen_noexception_exit = """\ NUITKA_CANNOT_GET_HERE("return must be present"); %(function_cleanup)s\ return NULL; """ template_asyncgen_return_exit = """\ function_return_exit:; return NULL; """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesConstants.py0000600000372100037210000001315614166627112032172 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Templates for the constants handling. """ template_constants_reading = r""" #include "nuitka/prelude.h" #include "structseq.h" // Global constants storage PyObject *global_constants[%(global_constants_count)d]; // Sentinel PyObject to be used for all our call iterator endings. It will // become a PyCObject pointing to NULL. It's address is unique, and that's // enough for us to use it as sentinel value. PyObject *_sentinel_value = NULL; PyObject *Nuitka_dunder_compiled_value = NULL; #ifdef _NUITKA_STANDALONE extern PyObject *getStandaloneSysExecutablePath(PyObject *basename); #endif // We provide the sys.version info shortcut as a global value here for ease of use. PyObject *Py_SysVersionInfo = NULL; static void _createGlobalConstants(void) { // We provide the sys.version info shortcut as a global value here for ease of use. Py_SysVersionInfo = Nuitka_SysGetObject("version_info"); // The empty name means global. loadConstantsBlob(&global_constants[0], ""); #if _NUITKA_EXE /* Set the "sys.executable" path to the original CPython executable or point to inside the distribution for standalone. */ Nuitka_SysSetObject( "executable", #ifndef _NUITKA_STANDALONE %(sys_executable)s #else getStandaloneSysExecutablePath(%(sys_executable)s) #endif ); #ifndef _NUITKA_STANDALONE /* Set the "sys.prefix" path to the original one. */ Nuitka_SysSetObject( "prefix", %(sys_prefix)s ); /* Set the "sys.prefix" path to the original one. */ Nuitka_SysSetObject( "exec_prefix", %(sys_exec_prefix)s ); #if PYTHON_VERSION >= 0x300 /* Set the "sys.base_prefix" path to the original one. */ Nuitka_SysSetObject( "base_prefix", %(sys_base_prefix)s ); /* Set the "sys.exec_base_prefix" path to the original one. */ Nuitka_SysSetObject( "base_exec_prefix", %(sys_base_exec_prefix)s ); #endif #endif #endif static PyTypeObject Nuitka_VersionInfoType; // Same fields as "sys.version_info" except no serial number. static PyStructSequence_Field Nuitka_VersionInfoFields[] = { {(char *)"major", (char *)"Major release number"}, {(char *)"minor", (char *)"Minor release number"}, {(char *)"micro", (char *)"Micro release number"}, {(char *)"releaselevel", (char *)"'alpha', 'beta', 'candidate', or 'release'"}, {(char *)"standalone", (char *)"boolean indicating standalone mode usage"}, {(char *)"onefile", (char *)"boolean indicating standalone mode usage"}, {0} }; static PyStructSequence_Desc Nuitka_VersionInfoDesc = { (char *)"__nuitka_version__", /* name */ (char *)"__compiled__\\n\\nVersion information as a named tuple.", /* doc */ Nuitka_VersionInfoFields, /* fields */ 6 }; PyStructSequence_InitType(&Nuitka_VersionInfoType, &Nuitka_VersionInfoDesc); Nuitka_dunder_compiled_value = PyStructSequence_New(&Nuitka_VersionInfoType); assert(Nuitka_dunder_compiled_value != NULL); PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 0, PyInt_FromLong(%(nuitka_version_major)s)); PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 1, PyInt_FromLong(%(nuitka_version_minor)s)); PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 2, PyInt_FromLong(%(nuitka_version_micro)s)); PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 3, Nuitka_String_FromString("%(nuitka_version_level)s")); #ifdef _NUITKA_STANDALONE PyObject *is_standalone_mode = Py_True; #else PyObject *is_standalone_mode = Py_False; #endif #ifdef _NUITKA_ONEFILE PyObject *is_onefile_mode = Py_True; #else PyObject *is_onefile_mode = Py_False; #endif PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 4, is_standalone_mode); PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 5, is_onefile_mode); // Prevent users from creating the Nuitka version type object. Nuitka_VersionInfoType.tp_init = NULL; Nuitka_VersionInfoType.tp_new = NULL; } // In debug mode we can check that the constants were not tampered with in any // given moment. We typically do it at program exit, but we can add extra calls // for sanity. #ifndef __NUITKA_NO_ASSERT__ void checkGlobalConstants(void) { // TODO: Ask constant code to check values. } #endif void createGlobalConstants(void) { if (_sentinel_value == NULL) { #if PYTHON_VERSION < 0x300 _sentinel_value = PyCObject_FromVoidPtr(NULL, NULL); #else // The NULL value is not allowed for a capsule, so use something else. _sentinel_value = PyCapsule_New((void *)27, "sentinel", NULL); #endif assert(_sentinel_value); _createGlobalConstants(); } } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesExceptions.py0000600000372100037210000000436214166627112032336 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Templates for handling exceptions. """ template_publish_exception_to_handler = """\ if (%(keeper_tb)s == NULL) { %(keeper_tb)s = %(tb_making)s; } else if (%(keeper_lineno)s != 0) { %(keeper_tb)s = ADD_TRACEBACK(%(keeper_tb)s, %(frame_identifier)s, %(keeper_lineno)s); } """ template_error_catch_quick_exception = """\ if (%(condition)s) { if (!ERROR_OCCURRED()) { %(exception_type)s = %(quick_exception)s; Py_INCREF(%(exception_type)s); %(exception_value)s = NULL; %(exception_tb)s = NULL; } else { FETCH_ERROR_OCCURRED(&%(exception_type)s, &%(exception_value)s, &%(exception_tb)s); } %(release_temps)s %(var_description_code)s %(line_number_code)s goto %(exception_exit)s; }""" template_error_catch_exception = """\ if (%(condition)s) { assert(ERROR_OCCURRED()); FETCH_ERROR_OCCURRED(&%(exception_type)s, &%(exception_value)s, &%(exception_tb)s); %(release_temps)s %(line_number_code)s %(var_description_code)s goto %(exception_exit)s; }""" template_error_format_string_exception = """\ if (%(condition)s) { %(release_temps)s %(set_exception)s %(line_number_code)s %(var_description_code)s goto %(exception_exit)s; } """ template_error_format_name_error_exception = """\ if (unlikely(%(condition)s)) { %(release_temps)s %(set_exception)s %(line_number_code)s %(var_description_code)s goto %(exception_exit)s; } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesFrames.py0000600000372100037210000002060314166627112031426 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code templates for frames of all kinds. """ # Frame in a function template_frame_guard_full_block = """\ if (isFrameUnusable(%(frame_cache_identifier)s)) { Py_XDECREF(%(frame_cache_identifier)s); #if _DEBUG_REFCOUNTS if (%(frame_cache_identifier)s == NULL) { count_active_frame_cache_instances += 1; } else { count_released_frame_cache_instances += 1; } count_allocated_frame_cache_instances += 1; #endif %(frame_cache_identifier)s = MAKE_FUNCTION_FRAME(%(code_identifier)s, %(module_identifier)s, %(locals_size)s); #if _DEBUG_REFCOUNTS } else { count_hit_frame_cache_instances += 1; #endif } assert(%(frame_cache_identifier)s->m_type_description == NULL); %(frame_identifier)s = %(frame_cache_identifier)s; // Push the new frame as the currently active one. pushFrameStack(%(frame_identifier)s); // Mark the frame object as in use, ref count 1 will be up for reuse. assert(Py_REFCNT(%(frame_identifier)s) == 2); // Frame stack // Framed code: %(codes)s #if %(needs_preserve)d RESTORE_FRAME_EXCEPTION(%(frame_identifier)s); #endif // Put the previous frame back on top. popFrameStack(); goto %(no_exception_exit)s; """ template_frame_guard_full_return_handler = """\ %(frame_return_exit)s:; #if %(needs_preserve)d RESTORE_FRAME_EXCEPTION(%(frame_identifier)s); #endif // Put the previous frame back on top. popFrameStack(); goto %(return_exit)s; """ template_frame_attach_locals = """\ Nuitka_Frame_AttachLocals( %(frame_identifier)s, %(type_description)s%(frame_variable_refs)s ); """ template_frame_guard_full_exception_handler = """\ %(frame_exception_exit)s:; #if %(needs_preserve)d RESTORE_FRAME_EXCEPTION(%(frame_identifier)s); #endif if (%(exception_tb)s == NULL) { %(exception_tb)s = %(tb_making)s; } else if (%(exception_tb)s->tb_frame != &%(frame_identifier)s->m_frame) { %(exception_tb)s = ADD_TRACEBACK(%(exception_tb)s, %(frame_identifier)s, %(exception_lineno)s); } // Attaches locals to frame if any. %(attach_locals)s // Release cached frame if used for exception. if (%(frame_identifier)s == %(frame_cache_identifier)s) { #if _DEBUG_REFCOUNTS count_active_frame_cache_instances -= 1; count_released_frame_cache_instances += 1; #endif Py_DECREF(%(frame_cache_identifier)s); %(frame_cache_identifier)s = NULL; } assertFrameObject(%(frame_identifier)s); // Put the previous frame back on top. popFrameStack(); // Return the error. goto %(parent_exception_exit)s; """ # Frame for a module. TODO: Use it for functions called only once. # TODO: The once guard need not take a reference count in its frame class. template_frame_guard_once_block = """\ // Frame without reuse. %(frame_identifier)s = MAKE_MODULE_FRAME(%(code_identifier)s, %(module_identifier)s); // Push the new frame as the currently active one, and we should be exclusively // owning it. pushFrameStack(%(frame_identifier)s); assert(Py_REFCNT(%(frame_identifier)s) == 2); // Framed code: %(codes)s // Restore frame exception if necessary. #if %(needs_preserve)d RESTORE_FRAME_EXCEPTION(%(frame_identifier)s); #endif popFrameStack(); assertFrameObject(%(frame_identifier)s); goto %(no_exception_exit)s; """ template_frame_guard_once_exception_handler = """\ %(frame_exception_exit)s:; #if %(needs_preserve)d RESTORE_FRAME_EXCEPTION(%(frame_identifier)s); #endif if (%(exception_tb)s == NULL) { %(exception_tb)s = %(tb_making)s; } else if (exception_tb->tb_frame != &%(frame_identifier)s->m_frame) { %(exception_tb)s = ADD_TRACEBACK(%(exception_tb)s, %(frame_identifier)s, %(exception_lineno)s); } // Put the previous frame back on top. popFrameStack(); // Return the error. goto %(parent_exception_exit)s; """ # Frame in a generator, coroutine or asyncgen. template_frame_guard_generator = """\ if (isFrameUnusable(%(frame_cache_identifier)s)) { Py_XDECREF(%(frame_cache_identifier)s); #if _DEBUG_REFCOUNTS if (%(frame_cache_identifier)s == NULL) { count_active_frame_cache_instances += 1; } else { count_released_frame_cache_instances += 1; } count_allocated_frame_cache_instances += 1; #endif %(frame_cache_identifier)s = MAKE_FUNCTION_FRAME(%(code_identifier)s, %(module_identifier)s, %(locals_size)s); #if _DEBUG_REFCOUNTS } else { count_hit_frame_cache_instances += 1; #endif } %(context_identifier)s->m_frame = %(frame_cache_identifier)s; // Mark the frame object as in use, ref count 1 will be up for reuse. Py_INCREF(%(context_identifier)s->m_frame); assert(Py_REFCNT(%(context_identifier)s->m_frame) == 2); // Frame stack #if PYTHON_VERSION >= 0x340 %(context_identifier)s->m_frame->m_frame.f_gen = (PyObject *)%(context_identifier)s; #endif assert(%(context_identifier)s->m_frame->m_frame.f_back == NULL); Py_CLEAR(%(context_identifier)s->m_frame->m_frame.f_back); %(context_identifier)s->m_frame->m_frame.f_back = PyThreadState_GET()->frame; Py_INCREF(%(context_identifier)s->m_frame->m_frame.f_back); PyThreadState_GET()->frame = &%(context_identifier)s->m_frame->m_frame; Py_INCREF(%(context_identifier)s->m_frame); Nuitka_Frame_MarkAsExecuting(%(context_identifier)s->m_frame); #if PYTHON_VERSION >= 0x300 // Accept currently existing exception as the one to publish again when we // yield or yield from. { PyThreadState *thread_state = PyThreadState_GET(); EXC_TYPE_F(%(context_identifier)s) = EXC_TYPE(thread_state); if (EXC_TYPE_F(%(context_identifier)s) == Py_None) EXC_TYPE_F(%(context_identifier)s) = NULL; Py_XINCREF(EXC_TYPE_F(%(context_identifier)s)); EXC_VALUE_F(%(context_identifier)s) = EXC_VALUE(thread_state); Py_XINCREF(EXC_VALUE_F(%(context_identifier)s)); EXC_TRACEBACK_F(%(context_identifier)s) = EXC_TRACEBACK(thread_state); Py_XINCREF(EXC_TRACEBACK_F(%(context_identifier)s)); } #endif // Framed code: %(codes)s Nuitka_Frame_MarkAsNotExecuting(%(context_identifier)s->m_frame); #if PYTHON_VERSION >= 0x300 Py_CLEAR(EXC_TYPE_F(%(context_identifier)s)); Py_CLEAR(EXC_VALUE_F(%(context_identifier)s)); Py_CLEAR(EXC_TRACEBACK_F(%(context_identifier)s)); #endif // Allow re-use of the frame again. Py_DECREF(%(context_identifier)s->m_frame); goto %(no_exception_exit)s; """ # TODO: This cannot happen, can it? template_frame_guard_generator_return_handler = """\ %(frame_return_exit)s:; #if PYTHON_VERSION >= 0x300 Py_CLEAR(EXC_TYPE_F(%(context_identifier)s)); Py_CLEAR(EXC_VALUE_F(%(context_identifier)s)); Py_CLEAR(EXC_TRACEBACK_F(%(context_identifier)s)); #endif Py_DECREF(%(frame_identifier)s); goto %(return_exit)s; """ template_frame_guard_generator_exception_handler = """\ %(frame_exception_exit)s:; // If it's not an exit exception, consider and create a traceback for it. if (!EXCEPTION_MATCH_GENERATOR(%(exception_type)s)) { if (%(exception_tb)s == NULL) { %(exception_tb)s = %(tb_making)s; } else if (%(exception_tb)s->tb_frame != &%(frame_identifier)s->m_frame) { %(exception_tb)s = ADD_TRACEBACK(%(exception_tb)s, %(frame_identifier)s, %(exception_lineno)s); } %(attach_locals)s // Release cached frame if used for exception. if (%(frame_identifier)s == %(frame_cache_identifier)s) { #if _DEBUG_REFCOUNTS count_active_frame_cache_instances -= 1; count_released_frame_cache_instances += 1; #endif Py_DECREF(%(frame_cache_identifier)s); %(frame_cache_identifier)s = NULL; } assertFrameObject(%(frame_identifier)s); } #if PYTHON_VERSION >= 0x300 Py_CLEAR(EXC_TYPE_F(%(context_identifier)s)); Py_CLEAR(EXC_VALUE_F(%(context_identifier)s)); Py_CLEAR(EXC_TRACEBACK_F(%(context_identifier)s)); #endif Py_DECREF(%(frame_identifier)s); // Return the error. goto %(parent_exception_exit)s; """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesFunction.py0000600000372100037210000000637214166627112032005 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Normal function (no generator, not yielding) related templates. """ template_function_make_declaration = """\ static PyObject *MAKE_FUNCTION_%(function_identifier)s(%(function_creation_args)s); """ template_function_direct_declaration = """\ %(file_scope)s PyObject *impl_%(function_identifier)s(%(direct_call_arg_spec)s); """ template_maker_function_body = """ static PyObject *%(function_maker_identifier)s(%(function_creation_args)s) { struct Nuitka_FunctionObject *result = Nuitka_Function_New( %(function_impl_identifier)s, %(function_name_obj)s, #if PYTHON_VERSION >= 0x300 %(function_qualname_obj)s, #endif %(code_identifier)s, %(defaults)s, #if PYTHON_VERSION >= 0x300 %(kw_defaults)s, %(annotations)s, #endif %(module_identifier)s, %(function_doc)s, %(closure_name)s, %(closure_count)d ); %(constant_return_code)s return (PyObject *)result; } """ template_make_function = """\ %(closure_copy)s %(to_name)s = %(function_maker_identifier)s(%(args)s); """ template_function_body = """\ static PyObject *impl_%(function_identifier)s(%(parameter_objects_decl)s) { // Preserve error status for checks #ifndef __NUITKA_NO_ASSERT__ NUITKA_MAY_BE_UNUSED bool had_error = ERROR_OCCURRED(); #endif // Local variable declarations. %(function_locals)s // Actual function body. %(function_body)s %(function_exit)s } """ template_function_exception_exit = """\ function_exception_exit: %(function_cleanup)s\ assert(%(exception_type)s); RESTORE_ERROR_OCCURRED(%(exception_type)s, %(exception_value)s, %(exception_tb)s); return NULL; """ template_function_return_exit = """ function_return_exit: // Function cleanup code if any. %(function_cleanup)s // Actual function exit with return value, making sure we did not make // the error status worse despite non-NULL return. CHECK_OBJECT(tmp_return_value); assert(had_error || !ERROR_OCCURRED()); return tmp_return_value;""" function_direct_body_template = """\ %(file_scope)s PyObject *impl_%(function_identifier)s(%(direct_call_arg_spec)s) { #ifndef __NUITKA_NO_ASSERT__ NUITKA_MAY_BE_UNUSED bool had_error = ERROR_OCCURRED(); assert(!had_error); // Do not enter inlined functions with error set. #endif // Local variable declarations. %(function_locals)s // Actual function body. %(function_body)s %(function_exit)s } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesLoader.py0000600000372100037210000000671014166627112031422 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Templates for the loading of embedded modules. """ template_metapath_loader_compiled_module_entry = """\ {%(module_name)s, modulecode_%(module_identifier)s, 0, 0, %(flags)s},""" template_metapath_loader_shlib_module_entry = """\ {%(module_name)s, NULL, 0, 0, %(flags)s},""" template_metapath_loader_bytecode_module_entry = """\ {%(module_name)s, NULL, %(bytecode)s, %(size)d, %(flags)s},""" template_metapath_loader_body = r""" /* Code to register embedded modules for meta path based loading if any. */ #include #include "nuitka/constants_blob.h" #include "nuitka/unfreezing.h" /* Type bool */ #ifndef __cplusplus #include "stdbool.h" #endif #if %(bytecode_count)d > 0 static unsigned char *bytecode_data[%(bytecode_count)d]; #else static unsigned char **bytecode_data = NULL; #endif /* Table for lookup to find compiled or bytecode modules included in this * binary or module, or put along this binary as extension modules. We do * our own loading for each of these. */ %(metapath_module_decls)s static struct Nuitka_MetaPathBasedLoaderEntry meta_path_loader_entries[] = { %(metapath_loader_inittab)s {NULL, NULL, 0, 0, 0} }; static void _loadBytesCodesBlob() { static bool init_done = false; if (init_done == false) { loadConstantsBlob((PyObject **)bytecode_data, ".bytecode"); init_done = true; } } void setupMetaPathBasedLoader(void) { static bool init_done = false; if (init_done == false) { _loadBytesCodesBlob(); registerMetaPathBasedUnfreezer(meta_path_loader_entries, bytecode_data); init_done = true; } } // This provides the frozen (compiled bytecode) files that are included if // any. // These modules should be loaded as bytecode. They may e.g. have to be loadable // during "Py_Initialize" already, or for irrelevance, they are only included // in this un-optimized form. These are not compiled by Nuitka, and therefore // are not accelerated at all, merely bundled with the binary or module, so // that CPython library can start out finding them. struct frozen_desc { char const *name; int index; int size; }; static struct frozen_desc _frozen_modules[] = { %(frozen_modules)s {NULL, 0, 0} }; void copyFrozenModulesTo(struct _frozen *destination) { _loadBytesCodesBlob(); struct frozen_desc *current = _frozen_modules; for (;;) { destination->name = (char *)current->name; destination->code = bytecode_data[current->index]; destination->size = current->size; if (destination->name == NULL) break; current += 1; destination += 1; }; } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/__init__.py0000600000372100037210000000150114166627112027272 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesIterators.py0000600000372100037210000000443714166627112032174 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Templates for the iterator handling. """ template_iterator_check = """\ // Check if iterator has left-over elements. CHECK_OBJECT(%(iterator_name)s); assert(HAS_ITERNEXT(%(iterator_name)s)); %(attempt_name)s = (*Py_TYPE(%(iterator_name)s)->tp_iternext)(%(iterator_name)s); if (likely(%(attempt_name)s == NULL)) { PyObject *error = GET_ERROR_OCCURRED(); if (error != NULL) { if (EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopIteration)) { CLEAR_ERROR_OCCURRED(); } else { FETCH_ERROR_OCCURRED(&%(exception_type)s, &%(exception_value)s, &%(exception_tb)s); %(release_temps_1)s %(var_description_code_1)s %(line_number_code_1)s goto %(exception_exit)s; } } } else { Py_DECREF(%(attempt_name)s); %(exception_type)s = PyExc_ValueError; Py_INCREF(PyExc_ValueError); %(exception_value)s = %(too_many_values_error)s; Py_INCREF(%(exception_value)s); %(exception_tb)s = NULL; %(release_temps_2)s %(var_description_code_2)s %(line_number_code_2)s goto %(exception_exit)s; }""" template_loop_break_next = """\ if (%(to_name)s == NULL) { if (CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED()) { %(break_indicator_code)s goto %(break_target)s; } else { %(release_temps)s FETCH_ERROR_OCCURRED(&%(exception_type)s, &%(exception_value)s, &%(exception_tb)s); %(var_description_code)s %(line_number_code)s goto %(exception_target)s; } } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/templates/TemplateDebugWrapper.py0000600000372100037210000000501114166627112031616 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nuitka templates can have more checks that the normal '%' operation. This wraps strings with a class derived from "str" that does more checks. """ from nuitka import Options from nuitka.__past__ import iterItems from nuitka.Tracing import optimization_logger def enableDebug(globals_dict): templates = dict(globals_dict) class TemplateWrapper(object): """Wrapper around templates. To better trace and control template usage. """ def __init__(self, name, value): self.name = name self.value = value def __str__(self): return self.value def __add__(self, other): return self.__class__( self.name + "+" + other.name, self.value + other.value ) def __mod__(self, other): assert type(other) is dict, self.name for key in other.keys(): if "%%(%s)" % key not in self.value: optimization_logger.warning( "Extra value %r provided to template %r." % (key, self.name) ) try: return self.value % other except KeyError as e: raise KeyError(self.name, *e.args) def split(self, sep): return self.value.split(sep) for template_name, template_value in iterItems(templates): # Ignore internal attribute like "__name__" that the module will also # have of course. if template_name.startswith("_"): continue if type(template_value) is str: globals_dict[template_name] = TemplateWrapper(template_name, template_value) def checkDebug(globals_dict): if Options.is_debug: enableDebug(globals_dict) Nuitka-0.6.19.1/nuitka/codegen/templates/CodeTemplatesVariables.py0000600000372100037210000001506014166627112032122 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Templates for the variable handling. """ template_write_local_unclear_ref0 = """\ { PyObject *old = %(identifier)s; %(identifier)s = %(tmp_name)s; Py_XDECREF(old); } """ template_write_local_unclear_ref1 = """\ { PyObject *old = %(identifier)s; %(identifier)s = %(tmp_name)s; Py_INCREF(%(identifier)s); Py_XDECREF(old); } """ template_write_local_empty_ref0 = """\ assert(%(identifier)s == NULL); %(identifier)s = %(tmp_name)s;""" template_write_local_empty_ref1 = """\ assert(%(identifier)s == NULL); Py_INCREF(%(tmp_name)s); %(identifier)s = %(tmp_name)s;""" template_write_local_clear_ref0 = """\ { PyObject *old = %(identifier)s; assert(old != NULL); %(identifier)s = %(tmp_name)s; Py_DECREF(old); } """ template_write_local_inplace = """\ %(identifier)s = %(tmp_name)s; """ template_write_shared_inplace = """\ PyCell_SET(%(identifier)s, %(tmp_name)s); """ template_write_local_clear_ref1 = """\ { PyObject *old = %(identifier)s; assert(old != NULL); %(identifier)s = %(tmp_name)s; Py_INCREF(%(identifier)s); Py_DECREF(old); } """ template_write_shared_unclear_ref0 = """\ { PyObject *old = Nuitka_Cell_GET(%(identifier)s); PyCell_SET(%(identifier)s, %(tmp_name)s); Py_XDECREF(old); } """ template_write_shared_unclear_ref1 = """\ { PyObject *old = Nuitka_Cell_GET(%(identifier)s); PyCell_SET(%(identifier)s, %(tmp_name)s); Py_INCREF(%(tmp_name)s); Py_XDECREF(old); } """ template_write_shared_clear_ref0 = """\ assert(Nuitka_Cell_GET(%(identifier)s) == NULL); PyCell_SET(%(identifier)s, %(tmp_name)s); """ template_write_shared_clear_ref1 = """\ assert(Nuitka_Cell_GET(%(identifier)s) == NULL); Py_INCREF(%(tmp_name)s); PyCell_SET(%(identifier)s, %(tmp_name)s); """ template_del_local_tolerant = """\ Py_XDECREF(%(identifier)s); %(identifier)s = NULL; """ template_del_shared_tolerant = """\ { PyObject *old = Nuitka_Cell_GET(%(identifier)s); PyCell_SET(%(identifier)s, NULL); Py_XDECREF(old); } """ template_del_local_intolerant = """\ %(result)s = %(identifier)s != NULL; if (likely(%(result)s)) { Py_DECREF(%(identifier)s); %(identifier)s = NULL; } """ template_del_shared_intolerant = """\ { PyObject *old = Nuitka_Cell_GET(%(identifier)s); PyCell_SET(%(identifier)s, NULL); Py_XDECREF(old); %(result)s = old != NULL; } """ template_del_local_known = """\ CHECK_OBJECT(%(identifier)s); Py_DECREF(%(identifier)s); %(identifier)s = NULL; """ template_del_shared_known = """\ { PyObject *old = Nuitka_Cell_GET(%(identifier)s); PyCell_SET(%(identifier)s, NULL); CHECK_OBJECT(old); Py_DECREF(old); } """ template_release_object_unclear = """\ Py_XDECREF(%(identifier)s);""" template_release_object_clear = """\ Py_DECREF(%(identifier)s);""" template_read_shared_known = """\ %(tmp_name)s = Nuitka_Cell_GET(%(identifier)s); """ # For module variable values, need to lookup in module dictionary or in # built-in dictionary. # TODO: Only provide fallback for known actually possible values. Do this # by keeping track of things that were added by "site.py" mechanisms. Then # we can avoid the second call entirely for most cases. template_read_mvar_unclear = """\ %(tmp_name)s = LOOKUP_MODULE_VALUE(moduledict_%(module_identifier)s, %(var_name)s); """ template_read_locals_dict_with_fallback = """\ %(to_name)s = DICT_GET_ITEM0(%(locals_dict)s, %(var_name)s); if (%(to_name)s == NULL) { %(fallback)s } """ template_read_locals_dict_without_fallback = """\ %(to_name)s = DICT_GET_ITEM0(%(locals_dict)s, %(var_name)s); """ template_read_locals_mapping_with_fallback = """\ %(to_name)s = PyObject_GetItem(%(locals_dict)s, %(var_name)s); if (%(to_name)s == NULL) { if (CHECK_AND_CLEAR_KEY_ERROR_OCCURRED()) { %(fallback)s Py_INCREF(%(to_name)s); } else { goto %(exception_exit)s; } } """ template_read_locals_mapping_without_fallback = """\ %(to_name)s = PyObject_GetItem(%(locals_dict)s, %(var_name)s); """ template_del_global_unclear = """\ %(res_name)s = PyDict_DelItem((PyObject *)moduledict_%(module_identifier)s, %(var_name)s); %(result)s = %(res_name)s != -1; if (%(result)s == false) CLEAR_ERROR_OCCURRED(); """ template_del_global_known = """\ %(res_name)s = PyDict_DelItem((PyObject *)moduledict_%(module_identifier)s, %(var_name)s); if (%(res_name)s == -1) CLEAR_ERROR_OCCURRED(); """ template_update_locals_dict_value = """\ if (%(test_code)s) { PyObject *value; %(access_code)s UPDATE_STRING_DICT0((PyDictObject *)%(dict_name)s, (Nuitka_StringObject *)%(var_name)s, value); } else { int res = PyDict_DelItem(%(dict_name)s, %(var_name)s); if (res != 0) { CLEAR_ERROR_OCCURRED(); } } """ template_set_locals_dict_value = """\ if (%(test_code)s) { PyObject *value; %(access_code)s int res = PyDict_SetItem( %(dict_name)s, %(var_name)s, value ); assert(res == 0); } """ template_update_locals_mapping_value = """\ if (%(test_code)s) { PyObject *value; %(access_code)s int res = PyObject_SetItem( %(mapping_name)s, %(var_name)s, value ); %(tmp_name)s = res == 0; } else { PyObject *test_value = PyObject_GetItem( %(mapping_name)s, %(var_name)s ); if (test_value) { Py_DECREF(test_value); int res = PyObject_DelItem( %(mapping_name)s, %(var_name)s ); %(tmp_name)s = res == 0; } else { CLEAR_ERROR_OCCURRED(); %(tmp_name)s = true; } } """ template_set_locals_mapping_value = """\ if (%(test_code)s) { PyObject *value; %(access_code)s %(tmp_name)s = SET_SUBSCRIPT( %(mapping_name)s, %(var_name)s, value ); } else { %(tmp_name)s = true; } """ from . import TemplateDebugWrapper # isort:skip TemplateDebugWrapper.checkDebug(globals()) Nuitka-0.6.19.1/nuitka/codegen/SubscriptCodes.py0000600000372100037210000002000214166627112026466 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Subscript related code generation. There is special handling for integer indexes, which can be dealt with much faster than general subscript lookups. """ from nuitka import Options from .CodeHelpers import ( generateChildExpressionCode, generateExpressionCode, generateExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCodes def _decideIntegerSubscript(subscript): if subscript.isExpressionConstantRef(): if subscript.isIndexConstant(): constant_value = subscript.getIndexValue() if abs(constant_value) < 2 ** 31: return constant_value, True return None, False def generateAssignmentSubscriptCode(statement, emit, context): subscribed = statement.subnode_subscribed subscript = statement.subnode_subscript value = statement.subnode_source subscript_constant, integer_subscript = _decideIntegerSubscript(subscript) value_name = context.allocateTempName("ass_subvalue") generateExpressionCode( to_name=value_name, expression=value, emit=emit, context=context ) subscribed_name = context.allocateTempName("ass_subscribed") generateExpressionCode( to_name=subscribed_name, expression=subscribed, emit=emit, context=context ) subscript_name = context.allocateTempName("ass_subscript") generateExpressionCode( to_name=subscript_name, expression=subscript, emit=emit, context=context ) with context.withCurrentSourceCodeReference( value.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): if integer_subscript: _getIntegerSubscriptAssignmentCode( subscribed_name=subscribed_name, subscript_name=subscript_name, subscript_value=subscript_constant, value_name=value_name, emit=emit, context=context, ) else: _getSubscriptAssignmentCode( target_name=subscribed_name, subscript_name=subscript_name, value_name=value_name, emit=emit, context=context, ) def generateDelSubscriptCode(statement, emit, context): subscribed = statement.subnode_subscribed subscript = statement.subnode_subscript target_name, subscript_name = generateExpressionsCode( expressions=(subscribed, subscript), names=("delsubscr_target", "delsubscr_subscript"), emit=emit, context=context, ) with context.withCurrentSourceCodeReference( subscript.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): _getSubscriptDelCode( target_name=target_name, subscript_name=subscript_name, emit=emit, context=context, ) def generateSubscriptLookupCode(to_name, expression, emit, context): subscribed = expression.subnode_expression subscript = expression.subnode_subscript subscribed_name = generateChildExpressionCode( expression=subscribed, emit=emit, context=context ) subscript_name = generateChildExpressionCode( expression=subscript, emit=emit, context=context ) subscript_constant, integer_subscript = _decideIntegerSubscript(subscript) with withObjectCodeTemporaryAssignment( to_name, "subscript_result", expression, emit, context ) as value_name: if integer_subscript: _getIntegerSubscriptLookupCode( to_name=value_name, subscribed_name=subscribed_name, subscript_name=subscript_name, subscript_value=subscript_constant, emit=emit, context=context, ) else: _getSubscriptLookupCode( to_name=value_name, subscribed_name=subscribed_name, subscript_name=subscript_name, emit=emit, context=context, ) def generateSubscriptCheckCode(to_name, expression, emit, context): subscribed = expression.subnode_expression subscript = expression.subnode_subscript subscribed_name = generateChildExpressionCode( expression=subscribed, emit=emit, context=context ) subscript_name = generateChildExpressionCode( expression=subscript, emit=emit, context=context ) subscript_constant, integer_subscript = _decideIntegerSubscript(subscript) res_name = context.getBoolResName() if integer_subscript: emit( "%s = HAS_SUBSCRIPT_CONST(%s, %s, %s);" % (res_name, subscribed_name, subscript_name, subscript_constant) ) else: emit( "%s = HAS_SUBSCRIPT(%s, %s);" % (res_name, subscribed_name, subscript_name) ) getReleaseCodes((subscript_name, subscribed_name), emit, context) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition=res_name, emit=emit, ) def _getIntegerSubscriptLookupCode( to_name, subscribed_name, subscript_name, subscript_value, emit, context ): emit( "%s = LOOKUP_SUBSCRIPT_CONST(%s, %s, %s);" % (to_name, subscribed_name, subscript_name, subscript_value) ) getErrorExitCode( check_name=to_name, release_names=(subscribed_name, subscript_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getSubscriptLookupCode(to_name, subscript_name, subscribed_name, emit, context): emit("%s = LOOKUP_SUBSCRIPT(%s, %s);" % (to_name, subscribed_name, subscript_name)) getErrorExitCode( check_name=to_name, release_names=(subscribed_name, subscript_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getIntegerSubscriptAssignmentCode( subscribed_name, subscript_name, subscript_value, value_name, emit, context ): assert abs(subscript_value) < 2 ** 31 res_name = context.allocateTempName("ass_subscript_res", "int") emit( "%s = SET_SUBSCRIPT_CONST(%s, %s, %s, %s);" % (res_name, subscribed_name, subscript_name, subscript_value, value_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(subscribed_name, value_name), emit=emit, context=context, ) def _getSubscriptAssignmentCode(target_name, subscript_name, value_name, emit, context): res_name = context.getBoolResName() emit( "%s = SET_SUBSCRIPT(%s, %s, %s);" % (res_name, target_name, subscript_name, value_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(target_name, subscript_name, value_name), emit=emit, context=context, ) def _getSubscriptDelCode(target_name, subscript_name, emit, context): res_name = context.getBoolResName() emit("%s = DEL_SUBSCRIPT(%s, %s);" % (res_name, target_name, subscript_name)) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(target_name, subscript_name), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/ExceptionCodes.py0000600000372100037210000002126614166627112026463 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Exception handling. """ from nuitka.PythonVersions import python_version from .CodeHelpers import ( generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .templates.CodeTemplatesExceptions import ( template_publish_exception_to_handler, ) def getExceptionIdentifier(exception_type): assert "PyExc" not in exception_type, exception_type if exception_type == "NotImplemented": return "Py_NotImplemented" return "PyExc_%s" % exception_type def generateExceptionRefCode(to_name, expression, emit, context): exception_type = expression.getExceptionName() with withObjectCodeTemporaryAssignment( to_name, "exception_name", expression, emit, context ) as value_name: emit("%s = %s;" % (value_name, getExceptionIdentifier(exception_type))) def getTracebackMakingIdentifier(context, lineno_name): frame_handle = context.getFrameHandle() assert frame_handle is not None return "MAKE_TRACEBACK(%s, %s)" % (frame_handle, lineno_name) def generateExceptionCaughtTypeCode(to_name, expression, emit, context): keeper_variables = context.getExceptionKeeperVariables() with withObjectCodeTemporaryAssignment( to_name, "exception_caught_type", expression, emit, context ) as value_name: if keeper_variables[0] is None: emit("%s = EXC_TYPE(PyThreadState_GET());" % (value_name,)) else: emit("%s = %s;" % (value_name, keeper_variables[0])) def generateExceptionCaughtValueCode(to_name, expression, emit, context): keeper_variables = context.getExceptionKeeperVariables() with withObjectCodeTemporaryAssignment( to_name, "exception_caught_value", expression, emit, context ) as value_name: if keeper_variables[1] is None: emit("%s = EXC_VALUE(PyThreadState_GET());" % (value_name,)) else: if python_version >= 0x270: emit("%s = %s;" % (value_name, keeper_variables[1])) else: emit( "%s = %s ? %s : Py_None;" % (value_name, keeper_variables[1], keeper_variables[1]) ) def generateExceptionCaughtTracebackCode(to_name, expression, emit, context): keeper_variables = context.getExceptionKeeperVariables() with withObjectCodeTemporaryAssignment( to_name, "exception_caught_tb", expression, emit, context ) as value_name: if keeper_variables[2] is None: emit("%s = EXC_TRACEBACK(PyThreadState_GET());" % (value_name,)) else: emit( """\ if (%(keeper_tb)s != NULL) { %(to_name)s = (PyObject *)%(keeper_tb)s; Py_INCREF(%(to_name)s); } else { %(to_name)s = (PyObject *)%(tb_making)s; } """ % { "to_name": value_name, "keeper_tb": keeper_variables[2], "tb_making": getTracebackMakingIdentifier( context=context, lineno_name=keeper_variables[3] ), } ) context.addCleanupTempName(value_name) def getExceptionUnpublishedReleaseCode(emit, context): keeper_variables = context.getExceptionKeeperVariables() if keeper_variables[0] is not None: emit("Py_DECREF(%s);" % keeper_variables[0]) emit("Py_XDECREF(%s);" % keeper_variables[1]) emit("Py_XDECREF(%s);" % keeper_variables[2]) def generateExceptionPublishCode(statement, emit, context): # This statement has no attributes really, pylint: disable=unused-argument # Current variables cannot be used anymore now. ( keeper_type, keeper_value, keeper_tb, keeper_lineno, ) = context.setExceptionKeeperVariables((None, None, None, None)) emit( template_publish_exception_to_handler % { "tb_making": getTracebackMakingIdentifier( context=context, lineno_name=keeper_lineno ), "keeper_tb": keeper_tb, "keeper_lineno": keeper_lineno, "frame_identifier": context.getFrameHandle(), } ) # TODO: Make this one thing for performance with thread state shared, also for less code, # then we should not make it in header anymore. Might be more scalable too. emit("NORMALIZE_EXCEPTION(&%s, &%s, &%s);" % (keeper_type, keeper_value, keeper_tb)) emit("ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(%s, %s);" % (keeper_value, keeper_tb)) emit("PUBLISH_EXCEPTION(&%s, &%s, &%s);" % (keeper_type, keeper_value, keeper_tb)) def generateBuiltinMakeExceptionCode(to_name, expression, emit, context): # We try to make optimal code for various cases, pylint: disable=too-many-locals from .CallCodes import getCallCodeNoArgs, getCallCodePosArgsQuick exception_arg_names = [] for exception_arg in expression.subnode_args: exception_arg_name = context.allocateTempName("make_exception_arg") generateExpressionCode( to_name=exception_arg_name, expression=exception_arg, emit=emit, context=context, ) exception_arg_names.append(exception_arg_name) exception_type = expression.getExceptionName() with withObjectCodeTemporaryAssignment( to_name, "exception_made", expression, emit, context ) as value_name: if exception_arg_names: getCallCodePosArgsQuick( to_name=value_name, called_name=getExceptionIdentifier(exception_type), expression=expression, arg_names=exception_arg_names, needs_check=False, emit=emit, context=context, ) else: getCallCodeNoArgs( to_name=value_name, called_name=getExceptionIdentifier(exception_type), expression=expression, needs_check=False, emit=emit, context=context, ) if expression.getExceptionName() == "ImportError" and python_version >= 0x300: from .PythonAPICodes import getReferenceExportCode import_error_name_expression = expression.subnode_name if import_error_name_expression is not None: exception_importerror_name = context.allocateTempName( "make_exception_importerror_name" ) generateExpressionCode( to_name=exception_importerror_name, expression=import_error_name_expression, emit=emit, context=context, allow_none=True, ) getReferenceExportCode(exception_importerror_name, emit, context) if context.needsCleanup(exception_importerror_name): context.removeCleanupTempName(exception_importerror_name) emit( "((PyImportErrorObject *)%s)->name = %s;" % (to_name, exception_importerror_name) ) import_error_path_expression = expression.subnode_path if import_error_path_expression is not None: exception_importerror_path = context.allocateTempName( "make_exception_importerror_path" ) generateExpressionCode( to_name=exception_importerror_path, expression=import_error_path_expression, emit=emit, context=context, allow_none=True, ) getReferenceExportCode(exception_importerror_path, emit, context) if context.needsCleanup(exception_importerror_path): context.removeCleanupTempName(exception_importerror_path) emit( "((PyImportErrorObject *)%s)->path = %s;" % (to_name, exception_importerror_path) ) Nuitka-0.6.19.1/nuitka/codegen/ClassCodes.py0000600000372100037210000000527314166627112025572 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Codes for classes. Most the class specific stuff is solved in re-formulation. Only the selection of the metaclass remains as specific. """ from nuitka.PythonVersions import python_version from .CodeHelpers import ( generateChildExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitCode def generateSelectMetaclassCode(to_name, expression, emit, context): metaclass_name, bases_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # This is used for Python3 only. assert python_version >= 0x300 arg_names = [metaclass_name, bases_name] with withObjectCodeTemporaryAssignment( to_name, "metaclass_result", expression, emit, context ) as value_name: emit( "%s = SELECT_METACLASS(%s);" % (value_name, ", ".join(str(arg_name) for arg_name in arg_names)) ) getErrorExitCode( check_name=value_name, release_names=arg_names, emit=emit, context=context ) context.addCleanupTempName(value_name) def generateBuiltinSuperCode(to_name, expression, emit, context): type_name, object_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "super_value", expression, emit, context ) as value_name: emit( "%s = BUILTIN_SUPER%d(%s, %s);" % ( value_name, 2 if expression.isExpressionBuiltinSuper2() else 0, type_name if type_name is not None else "NULL", object_name if object_name is not None else "NULL", ) ) getErrorExitCode( check_name=value_name, release_names=(type_name, object_name), emit=emit, context=context, ) context.addCleanupTempName(value_name) Nuitka-0.6.19.1/nuitka/codegen/c_types/0000700000372100037210000000000014167275622024640 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeBools.py0000600000372100037210000000544614166627112027242 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ CType classes for C bool, this cannot represent unassigned, nor indicate exception. """ from .CTypeBases import CTypeBase, CTypeNotReferenceCountedMixin class CTypeBool(CTypeNotReferenceCountedMixin, CTypeBase): c_type = "bool" # Return value only obviously. helper_code = "CBOOL" @classmethod def emitValueAccessCode(cls, value_name, emit, context): # Nothing to do for this type, pylint: disable=unused-argument assert False @classmethod def emitValueAssertionCode(cls, value_name, emit): pass @classmethod def emitAssignConversionCode(cls, to_name, value_name, needs_check, emit, context): # Conversion cannot fail, pylint: disable=unused-argument if value_name.c_type == cls.c_type: emit("%s = %s;" % (to_name, value_name)) else: emit( "%s = %s;" % ( to_name, value_name.getCType().getTruthCheckCode(value_name=value_name), ) ) @classmethod def emitAssignmentCodeFromConstant( cls, to_name, constant, may_escape, emit, context ): # No context needed, pylint: disable=unused-argument emit("%s = %s;" % (to_name, "true" if constant else "false")) @classmethod def getInitValue(cls, init_from): return "" @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "" @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): assert False @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit("%s = (%s) ? true : false;" % (to_name, condition)) @classmethod def getExceptionCheckCondition(cls, value_name): # Expected to not be used, pylint: disable=unused-argument assert False @classmethod def getTruthCheckCode(cls, value_name): return "%s != false" % value_name Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeModuleDictVariables.py0000600000372100037210000000675114166627112032046 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Pseudo CType for module variables, object values contained in a dictionary. These are to integrate module variables with what is normally local stuff. Going from an to "PyObject *" is mostly its trick, then put into the dict. """ from nuitka.codegen.templates.CodeTemplatesVariables import ( template_del_global_known, template_del_global_unclear, template_read_mvar_unclear, ) from .CTypeBases import CTypeBase class CTypeModuleDictVariable(CTypeBase): @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): if in_place: orig_name = context.getInplaceLeftName() emit("if (%s != %s) {" % (orig_name, tmp_name)) emit( "UPDATE_STRING_DICT_INPLACE(moduledict_%s, (Nuitka_StringObject *)%s, %s);" % ( context.getModuleCodeName(), context.getConstantCode(constant=value_name.code_name), tmp_name, ) ) emit("}") else: emit( "UPDATE_STRING_DICT%s(moduledict_%s, (Nuitka_StringObject *)%s, %s);" % ( ref_count, context.getModuleCodeName(), context.getConstantCode(constant=value_name.code_name), tmp_name, ) ) @classmethod def emitValueAccessCode(cls, value_name, emit, context): tmp_name = context.allocateTempName("mvar_value") emit( template_read_mvar_unclear % { "module_identifier": context.getModuleCodeName(), "tmp_name": tmp_name, "var_name": context.getConstantCode(constant=value_name.code_name), } ) return tmp_name @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): if not needs_check or tolerant: emit( template_del_global_known % { "module_identifier": context.getModuleCodeName(), "res_name": context.getIntResName(), "var_name": context.getConstantCode(constant=value_name.code_name), } ) else: emit( template_del_global_unclear % { "module_identifier": context.getModuleCodeName(), "res_name": context.getIntResName(), "result": to_name, "var_name": context.getConstantCode(constant=value_name.code_name), } ) Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeVoids.py0000600000372100037210000000666514166627112027254 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ CType classes for void, a special value to represent discarding stuff. Cannot be read from obviously. Also drops references immediately when trying to assign to it. """ from nuitka import Options from .CTypeBases import CTypeBase, CTypeNotReferenceCountedMixin # This is going to not use arguments very commonly. For now disable # the warning all around, specialize one done, pylint: disable=unused-argument class CTypeVoid(CTypeNotReferenceCountedMixin, CTypeBase): c_type = "nuitka_void" # Return value only obviously. helper_code = "NVOID" @classmethod def emitValueAccessCode(cls, value_name, emit, context): # Nothing to do for this type, pylint: disable=unused-argument assert False @classmethod def emitValueAssertionCode(cls, value_name, emit): assert False @classmethod def emitReinitCode(cls, value_name, emit): emit("%s = NUITKA_VOID_OK;" % value_name) @classmethod def emitAssignConversionCode(cls, to_name, value_name, needs_check, emit, context): # We have no storage, the original user will cleanup after itself. This # is the main point of the whole type. from ..ErrorCodes import getReleaseCode getReleaseCode(value_name, emit, context) # The only possible value, and in this case never read, but the compiler hates # it being defined which is hard for us to know ahead of time. if Options.is_debug: emit("%s = NUITKA_VOID_OK;" % to_name) @classmethod def emitAssignmentCodeFromConstant( cls, to_name, constant, may_escape, emit, context ): # No context needed, pylint: disable=unused-argument # Everything else expresses missed compiled time optimization. assert constant is None # The only possible value, and in this case never read, but the compiler hates # it being defined which is hard for us to know ahead of time. if Options.is_debug: emit("%s = NUITKA_VOID_OK;" % to_name) @classmethod def getInitValue(cls, init_from): assert False @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): assert False @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): # The only possible value, and in this case never read, but the compiler hates # it being defined which is hard for us to know ahead of time. if Options.is_debug: emit("%s = NUITKA_VOID_OK;" % to_name) @classmethod def getExceptionCheckCondition(cls, value_name): return "%s == NUITKA_VOID_EXCEPTION" % value_name Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeNuitkaInts.py0000600000372100037210000001212614166627112030246 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ CType classes for nuitka_ilong, an struct to represent long values. """ from nuitka.codegen.templates.CodeTemplatesVariables import ( template_release_object_clear, template_release_object_unclear, ) from .CTypeBases import CTypeBase class CTypeNuitkaIntOrLongStruct(CTypeBase): c_type = "nuitka_ilong" helper_code = "NILONG" @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): assert not in_place if tmp_name.c_type == "nuitka_ilong": emit("%s = %s;" % (value_name, tmp_name)) if ref_count: emit("/* REFCOUNT ? */") else: if tmp_name.c_type == "PyObject *": emit("%s.validity = NUITKA_ILONG_OBJECT_VALID;" % value_name) emit("%s.ilong_object = %s;" % (value_name, tmp_name)) if ref_count: emit("/* REFCOUNT ? */") else: assert False, repr(tmp_name) @classmethod def emitVariantAssignmentCode(cls, int_name, value_name, int_value, emit, context): # needs no context, pylint: disable=unused-argument if value_name is None: assert int_value is not None assert False # TODO else: if int_value is None: emit("%s.validity = NUITKA_ILONG_OBJECT_VALID;" % int_name) emit("%s.ilong_object = %s;" % (int_name, value_name)) else: emit("%s.validity = NUITKA_ILONG_BOTH_VALID;" % int_name) emit("%s.ilong_object = %s;" % (int_name, value_name)) emit("%s.ilong_value = %s;" % (int_name, int_value)) @classmethod def getTruthCheckCode(cls, value_name): return "%s != 0" % value_name @classmethod def emitValueAccessCode(cls, value_name, emit, context): # Nothing to do for this type, pylint: disable=unused-argument return value_name @classmethod def emitValueAssertionCode(cls, value_name, emit): emit("assert(%s.validity != NUITKA_ILONG_UNASSIGNED);" % value_name) @classmethod def emitAssignConversionCode(cls, to_name, value_name, needs_check, emit, context): if value_name.c_type == cls.c_type: emit("%s = %s;" % (to_name, value_name)) else: value_name.getCType().emitAssignmentCodeToNuitkaIntOrLong( to_name=to_name, value_name=value_name, needs_check=needs_check, emit=emit, context=context, ) @classmethod def getInitValue(cls, init_from): if init_from is None: # TODO: In debug mode, use more crash prone maybe. return "{NUITKA_ILONG_UNASSIGNED, NULL, 0}" else: assert False, init_from return init_from @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "%s.validity %s NUITKA_ILONG_UNASSIGNED" % ( value_name, "==" if inverted else "!=", ) @classmethod def getReleaseCode(cls, value_name, needs_check, emit): emit( "if ((%s.validity & NUITKA_ILONG_OBJECT_VALID) == NUITKA_ILONG_OBJECT_VALID) {" % value_name ) # TODO: Have a derived C type that does it. if needs_check: template = template_release_object_unclear else: template = template_release_object_clear emit(template % {"identifier": "%s.ilong_object" % value_name}) emit("}") @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): assert False, "TODO" if not needs_check: emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) elif tolerant: emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) else: emit("%s = %s == NUITKA_BOOL_UNASSIGNED;" % (to_name, value_name)) emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): assert False, "TODO" emit( "%(to_name)s = (%(condition)s) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE;" % {"to_name": to_name, "condition": condition} ) Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeNuitkaBools.py0000600000372100037210000001072314166627112030410 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ CType classes for nuitka_bool, an enum to represent True, False, unassigned. """ from nuitka.codegen.ErrorCodes import getReleaseCode from .CTypeBases import CTypeBase, CTypeNotReferenceCountedMixin class CTypeNuitkaBoolEnum(CTypeNotReferenceCountedMixin, CTypeBase): c_type = "nuitka_bool" helper_code = "NBOOL" @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): assert not in_place if tmp_name.c_type == "nuitka_bool": emit("%s = %s;" % (value_name, tmp_name)) else: if tmp_name.c_type == "PyObject *": test_code = "%s == Py_True" % tmp_name else: assert False, tmp_name cls.emitAssignmentCodeFromBoolCondition( to_name=value_name, condition=test_code, emit=emit ) # TODO: Refcount and context needs release are redundant. if ref_count: getReleaseCode(tmp_name, emit, context) @classmethod def emitAssignmentCodeToNuitkaIntOrLong( cls, to_name, value_name, needs_check, emit, context ): assert False, to_name @classmethod def getTruthCheckCode(cls, value_name): return "%s == NUITKA_BOOL_TRUE" % value_name @classmethod def emitValueAccessCode(cls, value_name, emit, context): # Nothing to do for this type, pylint: disable=unused-argument return value_name @classmethod def emitValueAssertionCode(cls, value_name, emit): emit("assert(%s != NUITKA_BOOL_UNASSIGNED);" % value_name) @classmethod def emitAssignConversionCode(cls, to_name, value_name, needs_check, emit, context): if value_name.c_type == cls.c_type: emit("%s = %s;" % (to_name, value_name)) else: value_name.getCType().emitAssignmentCodeToNuitkaBool( to_name=to_name, value_name=value_name, needs_check=needs_check, emit=emit, context=context, ) @classmethod def emitAssignmentCodeFromConstant( cls, to_name, constant, may_escape, emit, context ): # No context needed, pylint: disable=unused-argument emit( "%s = %s;" % (to_name, "NUITKA_BOOL_TRUE" if constant else "NUITKA_BOOL_FALSE") ) @classmethod def getInitValue(cls, init_from): if init_from is None: return "NUITKA_BOOL_UNASSIGNED" else: assert False, init_from return init_from @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "%s %s NUITKA_BOOL_UNASSIGNED" % (value_name, "==" if inverted else "!=") @classmethod def emitReinitCode(cls, value_name, emit): emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): if not needs_check: emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) elif tolerant: emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) else: emit("%s = %s != NUITKA_BOOL_UNASSIGNED;" % (to_name, value_name)) emit("%s = NUITKA_BOOL_UNASSIGNED;" % value_name) @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit( "%(to_name)s = (%(condition)s) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE;" % {"to_name": to_name, "condition": condition} ) @classmethod def getExceptionCheckCondition(cls, value_name): return "%s == NUITKA_BOOL_EXCEPTION" % value_name Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypePyObjectPtrs.py0000600000372100037210000004116114166627112030546 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ CType classes for PyObject *, PyObject **, and struct Nuitka_CellObject * """ from nuitka.__past__ import iterItems from nuitka.codegen.ErrorCodes import getErrorExitBoolCode, getReleaseCode from nuitka.codegen.templates.CodeTemplatesVariables import ( template_del_local_intolerant, template_del_local_known, template_del_local_tolerant, template_del_shared_intolerant, template_del_shared_known, template_del_shared_tolerant, template_release_object_clear, template_release_object_unclear, template_write_local_clear_ref0, template_write_local_clear_ref1, template_write_local_empty_ref0, template_write_local_empty_ref1, template_write_local_inplace, template_write_local_unclear_ref0, template_write_local_unclear_ref1, template_write_shared_clear_ref0, template_write_shared_clear_ref1, template_write_shared_inplace, template_write_shared_unclear_ref0, template_write_shared_unclear_ref1, ) from nuitka.Constants import isMutable from .CTypeBases import CTypeBase class CPythonPyObjectPtrBase(CTypeBase): @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): if in_place: # Releasing is not an issue here, local variable reference never # gave a reference, and the in-place code deals with possible # replacement/release. template = template_write_local_inplace else: if ref_count: if needs_release is False: template = template_write_local_empty_ref0 elif needs_release is True: template = template_write_local_clear_ref0 else: template = template_write_local_unclear_ref0 else: if needs_release is False: template = template_write_local_empty_ref1 elif needs_release is True: template = template_write_local_clear_ref1 else: template = template_write_local_unclear_ref1 emit(template % {"identifier": value_name, "tmp_name": tmp_name}) @classmethod def emitAssignmentCodeToNuitkaIntOrLong( cls, to_name, value_name, needs_check, emit, context ): to_type = to_name.getCType() to_type.emitVariantAssignmentCode( int_name=to_name, value_name=value_name, int_value=None, emit=emit, context=context, ) @classmethod def getTruthCheckCode(cls, value_name): return "CHECK_IF_TRUE(%s) == 1" % value_name @classmethod def emitTruthCheckCode(cls, to_name, value_name, emit): assert to_name.c_type == "int", to_name emit("%s = CHECK_IF_TRUE(%s);" % (to_name, value_name)) @classmethod def getReleaseCode(cls, value_name, needs_check, emit): if needs_check: template = template_release_object_unclear else: template = template_release_object_clear emit(template % {"identifier": value_name}) @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit( "%(to_name)s = (%(condition)s) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE;" % {"to_name": to_name, "condition": condition} ) @classmethod def emitAssignmentCodeToNuitkaBool( cls, to_name, value_name, needs_check, emit, context ): truth_name = context.allocateTempName("truth_name", "int") emit("%s = CHECK_IF_TRUE(%s);" % (truth_name, value_name)) getErrorExitBoolCode( condition="%s == -1" % truth_name, needs_check=needs_check, emit=emit, context=context, ) emit( "%s = %s == 0 ? NUITKA_BOOL_FALSE : NUITKA_BOOL_TRUE;" % (to_name, truth_name) ) @classmethod def emitAssignmentCodeFromConstant( cls, to_name, constant, may_escape, emit, context ): # Many cases to deal with, pylint: disable=too-many-branches,too-many-statements if type(constant) is dict: if not may_escape: code = context.getConstantCode(constant) ref_count = 0 elif constant: for key, value in iterItems(constant): # key cannot be mutable. assert not isMutable(key) if isMutable(value): needs_deep = True break else: needs_deep = False if needs_deep: code = "DEEP_COPY_DICT(%s)" % context.getConstantCode( constant, deep_check=False ) ref_count = 1 else: code = "PyDict_Copy(%s)" % context.getConstantCode( constant, deep_check=False ) ref_count = 1 else: code = "PyDict_New()" ref_count = 1 elif type(constant) is set: if not may_escape: code = context.getConstantCode(constant) ref_count = 0 elif constant: code = "PySet_New(%s)" % context.getConstantCode(constant) ref_count = 1 else: code = "PySet_New(NULL)" ref_count = 1 elif type(constant) is list: if not may_escape: code = context.getConstantCode(constant) ref_count = 0 elif constant: for value in constant: if isMutable(value): needs_deep = True break else: needs_deep = False if needs_deep: code = "DEEP_COPY_LIST(%s)" % context.getConstantCode( constant, deep_check=False ) ref_count = 1 else: code = "LIST_COPY(%s)" % context.getConstantCode( constant, deep_check=False ) ref_count = 1 else: code = "PyList_New(0)" ref_count = 1 elif type(constant) is tuple: needs_deep = False if may_escape: for value in constant: if isMutable(value): needs_deep = True break if needs_deep: code = "DEEP_COPY_TUPLE(%s)" % context.getConstantCode( constant, deep_check=False ) ref_count = 1 else: code = context.getConstantCode(constant) ref_count = 0 elif type(constant) is bytearray: if may_escape: code = "BYTEARRAY_COPY(%s)" % context.getConstantCode(constant) ref_count = 1 else: code = context.getConstantCode(constant) ref_count = 0 else: code = context.getConstantCode(constant=constant) ref_count = 0 if to_name.c_type == "PyObject *": value_name = to_name else: value_name = context.allocateTempName("constant_value") emit("%s = %s;" % (value_name, code)) if to_name is not value_name: cls.emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=False, emit=emit, context=context, ) # Above is supposed to transfer ownership. if ref_count: getReleaseCode(value_name, emit, context) else: if ref_count: context.addCleanupTempName(value_name) class CTypePyObjectPtr(CPythonPyObjectPtrBase): c_type = "PyObject *" helper_code = "OBJECT" @classmethod def getInitValue(cls, init_from): if init_from is None: return "NULL" else: return init_from @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "%s %s NULL" % (value_name, "==" if inverted else "!=") @classmethod def emitReinitCode(cls, value_name, emit): emit("%s = NULL;" % value_name) @classmethod def getVariableArgDeclarationCode(cls, variable_code_name): return "PyObject *%s" % variable_code_name @classmethod def getVariableArgReferencePassingCode(cls, variable_code_name): return "&%s" % variable_code_name @classmethod def getCellObjectAssignmentCode(cls, target_cell_code, variable_code_name, emit): emit("%s = Nuitka_Cell_New0(%s);" % (target_cell_code, variable_code_name)) @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): if not needs_check: emit(template_del_local_known % {"identifier": value_name}) elif tolerant: emit(template_del_local_tolerant % {"identifier": value_name}) else: emit( template_del_local_intolerant % {"identifier": value_name, "result": to_name} ) @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit( "%(to_name)s = (%(condition)s) ? Py_True : Py_False;" % {"to_name": to_name, "condition": condition} ) @classmethod def emitValueAccessCode(cls, value_name, emit, context): # Nothing to do for this type, pylint: disable=unused-argument return value_name @classmethod def emitValueAssertionCode(cls, value_name, emit): emit("CHECK_OBJECT(%s);" % value_name) @classmethod def emitAssignConversionCode(cls, to_name, value_name, needs_check, emit, context): # Nothing done for this type yet, pylint: disable=unused-argument if value_name.c_type == cls.c_type: emit("%s = %s;" % (to_name, value_name)) elif value_name.c_type == "nuitka_bool": cls.emitAssignmentCodeFromBoolCondition( condition=value_name.getCType().getTruthCheckCode(value_name), to_name=to_name, emit=emit, ) elif value_name.c_type == "nuitka_ilong": emit("ENFORCE_ILONG_OBJECT_VALUE(&%s);" % value_name) emit("%s = %s.ilong_object;" % (to_name, value_name)) else: assert False, to_name.c_type @classmethod def getExceptionCheckCondition(cls, value_name): return "%s == NULL" % value_name @classmethod def getReleaseCode(cls, value_name, needs_check, emit): if needs_check: template = template_release_object_unclear else: template = template_release_object_clear emit(template % {"identifier": value_name}) @classmethod def getTakeReferenceCode(cls, value_name, emit): """Take reference code for given object.""" emit("Py_INCREF(%s);" % value_name) class CTypePyObjectPtrPtr(CPythonPyObjectPtrBase): c_type = "PyObject **" @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "*%s %s NULL" % (value_name, "==" if inverted else "!=") @classmethod def getVariableArgDeclarationCode(cls, variable_code_name): return "PyObject **%s" % variable_code_name @classmethod def getVariableArgReferencePassingCode(cls, variable_code_name): return variable_code_name @classmethod def emitValueAccessCode(cls, value_name, emit, context): # No code needed for this type, pylint: disable=unused-argument from ..VariableDeclarations import VariableDeclaration # Use the object pointed to. return VariableDeclaration("PyObject *", "*%s" % value_name, None, None) @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit( "*%(to_name)s = (%(condition)s) ? Py_True : Py_False;" % {"to_name": to_name, "condition": condition} ) class CTypeCellObject(CTypeBase): c_type = "struct Nuitka_CellObject *" @classmethod def getInitValue(cls, init_from): # TODO: Single out "init_from" only user, so it becomes sure that we # get a reference transferred here in these cases. if init_from is not None: return "Nuitka_Cell_New1(%s)" % init_from else: return "Nuitka_Cell_Empty()" @classmethod def getInitTestConditionCode(cls, value_name, inverted): return "%s->ob_ref %s NULL" % (value_name, "==" if inverted else "!=") @classmethod def getCellObjectAssignmentCode(cls, target_cell_code, variable_code_name, emit): emit("%s = %s;" % (target_cell_code, variable_code_name)) emit("Py_INCREF(%s);" % (target_cell_code)) @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): if in_place: # Releasing is not an issue here, local variable reference never # gave a reference, and the in-place code deals with possible # replacement/release. template = template_write_shared_inplace else: if ref_count: if needs_release is False: template = template_write_shared_clear_ref0 else: template = template_write_shared_unclear_ref0 else: if needs_release is False: template = template_write_shared_clear_ref1 else: template = template_write_shared_unclear_ref1 emit(template % {"identifier": value_name, "tmp_name": tmp_name}) @classmethod def emitValueAccessCode(cls, value_name, emit, context): # No code needed for this type, pylint: disable=unused-argument from ..VariableDeclarations import VariableDeclaration # Use the object pointed to. return VariableDeclaration( "PyObject *", "Nuitka_Cell_GET(%s)" % value_name, None, None ) @classmethod def getVariableArgDeclarationCode(cls, variable_code_name): return "struct Nuitka_CellObject *%s" % variable_code_name @classmethod def getVariableArgReferencePassingCode(cls, variable_code_name): return variable_code_name @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): emit( "%(to_name)s->ob_ref = (%(condition)s) ? Py_True : Py_False;" % {"to_name": to_name, "condition": condition} ) @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): if not needs_check: emit(template_del_shared_known % {"identifier": value_name}) elif tolerant: emit(template_del_shared_tolerant % {"identifier": value_name}) else: emit( template_del_shared_intolerant % {"identifier": value_name, "result": to_name} ) @classmethod def getReleaseCode(cls, value_name, needs_check, emit): if needs_check: template = template_release_object_unclear else: template = template_release_object_clear emit(template % {"identifier": value_name}) @classmethod def emitReinitCode(cls, value_name, emit): emit("%s = NULL;" % value_name) @classmethod def emitValueAssertionCode(cls, value_name, emit): emit("CHECK_OBJECT(%s->ob_ref);" % value_name) @classmethod def emitReleaseAssertionCode(cls, value_name, emit): emit("CHECK_OBJECT(%s);" % value_name) Nuitka-0.6.19.1/nuitka/codegen/c_types/CTypeBases.py0000600000372100037210000001331514166627112027213 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Base class for all C types. Defines the interface to use by code generation on C types. Different types then have to overload the class methods. """ type_indicators = { "PyObject *": "o", "PyObject **": "O", "struct Nuitka_CellObject *": "c", "nuitka_bool": "b", "nuitka_ilong": "L", } class CTypeBase(object): # For overload. c_type = None @classmethod def getTypeIndicator(cls): return type_indicators[cls.c_type] @classmethod def getInitValue(cls, init_from): """Convert to init value for the type.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getInitTestConditionCode(cls, value_name, inverted): """Get code to test for uninitialized.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitVariableAssignCode( cls, value_name, needs_release, tmp_name, ref_count, in_place, emit, context ): """Get code to assign local variable.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getDeleteObjectCode( cls, to_name, value_name, needs_check, tolerant, emit, context ): """Get code to delete (del) local variable.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getVariableArgReferencePassingCode(cls, variable_code_name): """Get code to pass variable as reference argument.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getVariableArgDeclarationCode(cls, variable_code_name): """Get variable declaration code with given name.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getCellObjectAssignmentCode(cls, target_cell_code, variable_code_name, emit): """Get assignment code to given cell object from object.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitAssignmentCodeFromBoolCondition(cls, to_name, condition, emit): """Get the assignment code from C boolean condition.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitAssignmentCodeToNuitkaIntOrLong( cls, to_name, value_name, needs_check, emit, context ): """Get the assignment code to int or long type.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, to_name @classmethod def getReleaseCode(cls, value_name, needs_check, emit): """Get release code for given object.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitReinitCode(cls, value_name, emit): """Get release code for given object.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def getTakeReferenceCode(cls, value_name, emit): """Take reference code for given object.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitTruthCheckCode(cls, to_name, value_name, emit): """Check the truth of a value and indicate exception to an int.""" assert to_name.c_type == "int", to_name emit("%s = %s ? 1 : 0;" % (to_name, cls.getTruthCheckCode(value_name))) @classmethod def emitValueAssertionCode(cls, value_name, emit): """Assert that the value is not unassigned.""" # Need to overload this for each type it is used for, pylint: disable=unused-argument assert False, cls.c_type @classmethod def emitReleaseAssertionCode(cls, value_name, emit): """Assert that the container of the value is not released already of unassigned.""" cls.emitValueAssertionCode(value_name, emit) class CTypeNotReferenceCountedMixin(object): """Mixin for C types, that have no reference counting mechanism.""" @classmethod def getReleaseCode(cls, value_name, needs_check, emit): # If no check is needed, assert it for debug mode. if not needs_check: cls.emitValueAssertionCode(value_name, emit=emit) @classmethod def getTakeReferenceCode(cls, value_name, emit): pass @classmethod def emitReleaseAssertionCode(cls, value_name, emit): pass Nuitka-0.6.19.1/nuitka/codegen/c_types/__init__.py0000600000372100037210000000150114166627112026742 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/codegen/Contexts.py0000600000372100037210000007435314166627112025363 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation contexts. """ import collections import hashlib from abc import abstractmethod from contextlib import contextmanager from nuitka import Options from nuitka.__past__ import getMetaClassBase, iterItems from nuitka.Constants import isMutable from nuitka.constants.Serialization import ConstantAccessor from nuitka.PythonVersions import python_version from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) from .VariableDeclarations import VariableDeclaration, VariableStorage # Many methods won't use self, but it's the interface. pylint: disable=no-self-use class TempMixin(object): # Lots of details, everything gets to store bits here, to indicate # code generation states, and there are many, pylint: disable=too-many-instance-attributes def __init__(self): self.tmp_names = {} self.labels = {} # For exception and loop handling self.exception_escape = None self.loop_continue = None self.loop_break = None # For branches self.true_target = None self.false_target = None self.keeper_variable_count = 0 self.exception_keepers = (None, None, None, None) self.preserver_variable_declaration = {} self.cleanup_names = [] def _formatTempName(self, base_name, number): if number is None: return "tmp_{name}".format(name=base_name) else: return "tmp_{name}_{number:d}".format(name=base_name, number=number) def allocateTempName(self, base_name, type_name="PyObject *", unique=False): # We might be hard coding too many details for special temps # here, pylint: disable=too-many-branches if unique: number = None else: number = self.tmp_names.get(base_name, 0) number += 1 self.tmp_names[base_name] = number formatted_name = self._formatTempName(base_name=base_name, number=number) if unique: result = self.variable_storage.getVariableDeclarationTop(formatted_name) if result is None: if base_name == "outline_return_value": init_value = "NULL" elif base_name == "return_value": init_value = "NULL" elif base_name == "generator_return": init_value = "false" else: init_value = None if base_name == "unused": result = self.variable_storage.addVariableDeclarationFunction( c_type=type_name, code_name=formatted_name, init_value=init_value, ) else: result = self.variable_storage.addVariableDeclarationTop( c_type=type_name, code_name=formatted_name, init_value=init_value, ) else: if type_name.startswith("NUITKA_MAY_BE_UNUSED"): type_name = type_name[21:] assert result.c_type == type_name else: result = self.variable_storage.addVariableDeclarationLocal( c_type=type_name, code_name=formatted_name ) return result def skipTempName(self, base_name): number = self.tmp_names.get(base_name, 0) number += 1 self.tmp_names[base_name] = number def getIntResName(self): return self.allocateTempName("res", "int", unique=True) def getBoolResName(self): return self.allocateTempName("result", "bool", unique=True) def hasTempName(self, base_name): return base_name in self.tmp_names def getExceptionEscape(self): return self.exception_escape def setExceptionEscape(self, label): result = self.exception_escape self.exception_escape = label return result def getLoopBreakTarget(self): return self.loop_break def setLoopBreakTarget(self, label): result = self.loop_break self.loop_break = label return result def getLoopContinueTarget(self): return self.loop_continue def setLoopContinueTarget(self, label): result = self.loop_continue self.loop_continue = label return result def allocateLabel(self, label): result = self.labels.get(label, 0) result += 1 self.labels[label] = result return "{name}_{number:d}".format(name=label, number=result) def getLabelCount(self, label): return self.labels.get(label, 0) def allocateExceptionKeeperVariables(self): self.keeper_variable_count += 1 # For finally handlers of Python3, which have conditions on assign and # use, the NULL init is needed. debug = Options.is_debug and python_version >= 0x300 if debug: keeper_obj_init = "NULL" else: keeper_obj_init = None return ( self.variable_storage.addVariableDeclarationTop( "PyObject *", "exception_keeper_type_%d" % self.keeper_variable_count, keeper_obj_init, ), self.variable_storage.addVariableDeclarationTop( "PyObject *", "exception_keeper_value_%d" % self.keeper_variable_count, keeper_obj_init, ), self.variable_storage.addVariableDeclarationTop( "PyTracebackObject *", "exception_keeper_tb_%d" % self.keeper_variable_count, keeper_obj_init, ), self.variable_storage.addVariableDeclarationTop( "NUITKA_MAY_BE_UNUSED int", "exception_keeper_lineno_%d" % self.keeper_variable_count, "0" if debug else None, ), ) def getExceptionKeeperVariables(self): return self.exception_keepers def setExceptionKeeperVariables(self, keeper_vars): result = self.exception_keepers self.exception_keepers = tuple(keeper_vars) return result def addExceptionPreserverVariables(self, preserver_id): # For finally handlers of Python3, which have conditions on assign and # use. if preserver_id not in self.preserver_variable_declaration: debug = Options.is_debug and python_version >= 0x300 if debug: preserver_obj_init = "NULL" else: preserver_obj_init = None self.preserver_variable_declaration[preserver_id] = ( self.variable_storage.addVariableDeclarationTop( "PyObject *", "exception_preserved_type_%d" % preserver_id, preserver_obj_init, ), self.variable_storage.addVariableDeclarationTop( "PyObject *", "exception_preserved_value_%d" % preserver_id, preserver_obj_init, ), self.variable_storage.addVariableDeclarationTop( "PyTracebackObject *", "exception_preserved_tb_%d" % preserver_id, preserver_obj_init, ), ) return self.preserver_variable_declaration[preserver_id] def getTrueBranchTarget(self): return self.true_target def getFalseBranchTarget(self): return self.false_target def setTrueBranchTarget(self, label): self.true_target = label def setFalseBranchTarget(self, label): self.false_target = label def getCleanupTempnames(self): return self.cleanup_names[-1] def addCleanupTempName(self, tmp_name): assert tmp_name not in self.cleanup_names[-1], tmp_name assert ( tmp_name.c_type != "nuitka_void" or tmp_name.code_name == "tmp_unused" ), tmp_name self.cleanup_names[-1].append(tmp_name) def removeCleanupTempName(self, tmp_name): assert tmp_name in self.cleanup_names[-1], tmp_name self.cleanup_names[-1].remove(tmp_name) def needsCleanup(self, tmp_name): return tmp_name in self.cleanup_names[-1] def pushCleanupScope(self): self.cleanup_names.append([]) def popCleanupScope(self): assert not self.cleanup_names[-1] del self.cleanup_names[-1] CodeObjectHandle = collections.namedtuple( "CodeObjectHandle", ( "co_name", "co_kind", "co_varnames", "co_argcount", "co_posonlyargcount", "co_kwonlyargcount", "co_has_starlist", "co_has_stardict", "co_filename", "line_number", "future_flags", "co_new_locals", "co_freevars", "is_optimized", ), ) class CodeObjectsMixin(object): def __init__(self): # Code objects needed made unique by a key. self.code_objects = {} def getCodeObjects(self): return sorted(iterItems(self.code_objects)) def getCodeObjectHandle(self, code_object): key = CodeObjectHandle( co_filename=code_object.getFilename(), co_name=code_object.getCodeObjectName(), line_number=code_object.getLineNumber(), co_varnames=code_object.getVarNames(), co_argcount=code_object.getArgumentCount(), co_freevars=code_object.getFreeVarNames(), co_posonlyargcount=code_object.getPosOnlyParameterCount(), co_kwonlyargcount=code_object.getKwOnlyParameterCount(), co_kind=code_object.getCodeObjectKind(), is_optimized=code_object.getFlagIsOptimizedValue(), co_new_locals=code_object.getFlagNewLocalsValue(), co_has_starlist=code_object.hasStarListArg(), co_has_stardict=code_object.hasStarDictArg(), future_flags=code_object.getFutureSpec().asFlags(), ) if key not in self.code_objects: self.code_objects[key] = "codeobj_%s" % self._calcHash(key) return self.code_objects[key] if python_version < 0x300: def _calcHash(self, key): hash_value = hashlib.md5("-".join(str(s) for s in key)) return hash_value.hexdigest() else: def _calcHash(self, key): hash_value = hashlib.md5("-".join(str(s) for s in key).encode("utf8")) return hash_value.hexdigest() class PythonContextBase(getMetaClassBase("Context")): @counted_init def __init__(self): self.source_ref = None self.current_source_ref = None if isCountingInstances(): __del__ = counted_del() def getCurrentSourceCodeReference(self): return self.current_source_ref def setCurrentSourceCodeReference(self, value): result = self.current_source_ref self.current_source_ref = value return result @contextmanager def withCurrentSourceCodeReference(self, value): old_source_ref = self.setCurrentSourceCodeReference(value) yield old_source_ref self.setCurrentSourceCodeReference(value) def getInplaceLeftName(self): return self.allocateTempName("inplace_orig", "PyObject *", True) @abstractmethod def getConstantCode(self, constant, deep_check=False): pass @abstractmethod def getModuleCodeName(self): pass @abstractmethod def getModuleName(self): pass @abstractmethod def addHelperCode(self, key, code): pass @abstractmethod def hasHelperCode(self, key): pass @abstractmethod def addDeclaration(self, key, code): pass @abstractmethod def pushFrameVariables(self, frame_variables): pass @abstractmethod def popFrameVariables(self): pass @abstractmethod def getFrameVariableTypeDescriptions(self): pass @abstractmethod def getFrameVariableTypeDescription(self): pass @abstractmethod def getFrameTypeDescriptionDeclaration(self): pass @abstractmethod def getFrameVariableCodeNames(self): pass @abstractmethod def allocateTempName(self, base_name, type_name="PyObject *", unique=False): pass @abstractmethod def skipTempName(self, base_name): pass @abstractmethod def getIntResName(self): pass @abstractmethod def getBoolResName(self): pass @abstractmethod def hasTempName(self, base_name): pass @abstractmethod def getExceptionEscape(self): pass @abstractmethod def setExceptionEscape(self, label): pass @abstractmethod def getLoopBreakTarget(self): pass @abstractmethod def setLoopBreakTarget(self, label): pass @abstractmethod def getLoopContinueTarget(self): pass @abstractmethod def setLoopContinueTarget(self, label): pass @abstractmethod def allocateLabel(self, label): pass @abstractmethod def allocateExceptionKeeperVariables(self): pass @abstractmethod def getExceptionKeeperVariables(self): pass @abstractmethod def setExceptionKeeperVariables(self, keeper_vars): pass @abstractmethod def addExceptionPreserverVariables(self, count): pass @abstractmethod def getTrueBranchTarget(self): pass @abstractmethod def getFalseBranchTarget(self): pass @abstractmethod def setTrueBranchTarget(self, label): pass @abstractmethod def setFalseBranchTarget(self, label): pass @abstractmethod def getCleanupTempnames(self): pass @abstractmethod def addCleanupTempName(self, tmp_name): pass @abstractmethod def removeCleanupTempName(self, tmp_name): pass @abstractmethod def needsCleanup(self, tmp_name): pass @abstractmethod def pushCleanupScope(self): pass @abstractmethod def popCleanupScope(self): pass class PythonChildContextBase(PythonContextBase): # Base classes can be abstract, pylint: disable=I0021,abstract-method def __init__(self, parent): PythonContextBase.__init__(self) self.parent = parent def getConstantCode(self, constant, deep_check=False): return self.parent.getConstantCode(constant, deep_check=deep_check) def getModuleCodeName(self): return self.parent.getModuleCodeName() def getModuleName(self): return self.parent.getModuleName() def addHelperCode(self, key, code): return self.parent.addHelperCode(key, code) def hasHelperCode(self, key): return self.parent.hasHelperCode(key) def addDeclaration(self, key, code): self.parent.addDeclaration(key, code) def pushFrameVariables(self, frame_variables): return self.parent.pushFrameVariables(frame_variables) def popFrameVariables(self): return self.parent.popFrameVariables() def getFrameVariableTypeDescriptions(self): return self.parent.getFrameVariableTypeDescriptions() def getFrameVariableTypeDescription(self): return self.parent.getFrameVariableTypeDescription() def getFrameTypeDescriptionDeclaration(self): return self.parent.getFrameTypeDescriptionDeclaration() def getFrameVariableCodeNames(self): return self.parent.getFrameVariableCodeNames() def addFunctionCreationInfo(self, creation_info): return self.parent.addFunctionCreationInfo(creation_info) class FrameDeclarationsMixin(object): def __init__(self): # Frame is active or not, default not. self.frame_variables_stack = [""] # Type descriptions of the current frame. self.frame_type_descriptions = [()] # Types of variables for current frame. self.frame_variable_types = {} self.frames_used = 0 # Currently active frame stack inside the context. self.frame_stack = [None] self.locals_dict_names = None def getFrameHandle(self): return self.frame_stack[-1] def pushFrameHandle(self, code_identifier, is_light): self.frames_used += 1 if is_light: frame_identifier = VariableDeclaration( "struct Nuitka_FrameObject *", "m_frame", None, self.getContextObjectName(), ) else: frame_handle = code_identifier.replace("codeobj_", "frame_") if self.frames_used > 1: frame_handle += "_%d" % self.frames_used frame_identifier = self.variable_storage.addVariableDeclarationTop( "struct Nuitka_FrameObject *", frame_handle, None ) self.variable_storage.addVariableDeclarationTop( "NUITKA_MAY_BE_UNUSED char const *", "type_description_%d" % self.frames_used, "NULL", ) self.frame_stack.append(frame_identifier) return frame_identifier def popFrameHandle(self): result = self.frame_stack[-1] del self.frame_stack[-1] return result def getFramesCount(self): return self.frames_used def pushFrameVariables(self, frame_variables): """Set current the frame variables.""" self.frame_variables_stack.append(frame_variables) self.frame_type_descriptions.append(set()) def popFrameVariables(self): """End of frame, restore previous ones.""" del self.frame_variables_stack[-1] del self.frame_type_descriptions[-1] def setVariableType(self, variable, variable_declaration): assert variable.isLocalVariable(), variable # TODO: Change value of that dict to take advantage of declaration. self.frame_variable_types[variable] = ( str(variable_declaration), variable_declaration.getCType().getTypeIndicator(), ) def getFrameVariableTypeDescriptions(self): return self.frame_type_descriptions[-1] def getFrameTypeDescriptionDeclaration(self): return self.variable_storage.getVariableDeclarationTop( "type_description_%d" % (len(self.frame_stack) - 1) ) def getFrameVariableTypeDescription(self): result = "".join( self.frame_variable_types.get(variable, ("NULL", "N"))[1] for variable in self.frame_variables_stack[-1] ) if result: self.frame_type_descriptions[-1].add(result) return result def getFrameVariableCodeNames(self): result = [] for variable in self.frame_variables_stack[-1]: variable_code_name, variable_code_type = self.frame_variable_types.get( variable, ("NULL", "N") ) if variable_code_type in ("b",): result.append("(int)" + variable_code_name) else: result.append(variable_code_name) return result def getLocalsDictNames(self): return self.locals_dict_names or () def addLocalsDictName(self, locals_dict_name): result = self.variable_storage.getVariableDeclarationTop(locals_dict_name) if result is None: result = self.variable_storage.addVariableDeclarationTop( "PyObject *", locals_dict_name, "NULL" ) if self.locals_dict_names is None: self.locals_dict_names = set() self.locals_dict_names.add(result) return result class ReturnReleaseModeMixin(object): def __init__(self): self.return_release_mode = False self.return_exit = None def setReturnReleaseMode(self, value): result = self.return_release_mode self.return_release_mode = value return result def getReturnReleaseMode(self): return self.return_release_mode def setReturnTarget(self, label): result = self.return_exit self.return_exit = label return result def getReturnTarget(self): return self.return_exit class ReturnValueNameMixin(object): def __init__(self): self.return_name = None def getReturnValueName(self): if self.return_name is None: self.return_name = self.allocateTempName("return_value", unique=True) return self.return_name def setReturnValueName(self, value): result = self.return_name self.return_name = value return result class PythonModuleContext( TempMixin, CodeObjectsMixin, FrameDeclarationsMixin, ReturnReleaseModeMixin, ReturnValueNameMixin, PythonContextBase, ): # Plenty of attributes, because it's storing so many different things. # pylint: disable=too-many-instance-attributes def __init__(self, module, data_filename): PythonContextBase.__init__(self) TempMixin.__init__(self) CodeObjectsMixin.__init__(self) FrameDeclarationsMixin.__init__(self) ReturnReleaseModeMixin.__init__(self) # TODO: For outlines bodies. ReturnValueNameMixin.__init__(self) self.module = module self.name = module.getFullName() self.code_name = module.getCodeName() self.declaration_codes = {} self.helper_codes = {} self.frame_handle = None self.variable_storage = VariableStorage(heap_name=None) self.function_table_entries = [] self.constant_accessor = ConstantAccessor( top_level_name="mod_consts", data_filename=data_filename ) def __repr__(self): return "" % self.name def getOwner(self): return self.module def getEntryPoint(self): return self.module def isCompiledPythonModule(self): return True def getName(self): return self.name def mayRaiseException(self): body = self.module.subnode_body return body is not None and body.mayRaiseException(BaseException) getModuleName = getName def getModuleCodeName(self): return self.code_name def setFrameGuardMode(self, guard_mode): assert guard_mode == "once" def addHelperCode(self, key, code): assert key not in self.helper_codes, key self.helper_codes[key] = code def hasHelperCode(self, key): return key in self.helper_codes def getHelperCodes(self): return self.helper_codes def addDeclaration(self, key, code): assert key not in self.declaration_codes self.declaration_codes[key] = code def getDeclarations(self): return self.declaration_codes def mayRecurse(self): return False def getConstantCode(self, constant, deep_check=False): if deep_check and Options.is_debug: assert not isMutable(constant) return self.constant_accessor.getConstantCode(constant) def getConstantsCount(self): return self.constant_accessor.getConstantsCount() def addFunctionCreationInfo(self, creation_info): self.function_table_entries.append(creation_info) def getFunctionCreationInfos(self): result = self.function_table_entries # Release the memory once possible. del self.function_table_entries return result class PythonFunctionContext( FrameDeclarationsMixin, TempMixin, ReturnReleaseModeMixin, ReturnValueNameMixin, PythonChildContextBase, ): def __init__(self, parent, function): PythonChildContextBase.__init__(self, parent=parent) TempMixin.__init__(self) FrameDeclarationsMixin.__init__(self) ReturnReleaseModeMixin.__init__(self) ReturnValueNameMixin.__init__(self) self.function = function self.setExceptionEscape("function_exception_exit") self.setReturnTarget("function_return_exit") self.frame_handle = None self.variable_storage = self._makeVariableStorage() def _makeVariableStorage(self): return VariableStorage(heap_name=None) def __repr__(self): return "<%s for %s '%s'>" % ( self.__class__.__name__, "function" if not self.function.isExpressionClassBody() else "class", self.function.getName(), ) def getFunction(self): return self.function def getOwner(self): return self.function def getEntryPoint(self): return self.function def mayRecurse(self): # TODO: Determine this at compile time for enhanced optimizations. return True def getCodeObjectHandle(self, code_object): return self.parent.getCodeObjectHandle(code_object) class PythonFunctionDirectContext(PythonFunctionContext): def isForDirectCall(self): return True def isForCreatedFunction(self): return False class PythonGeneratorObjectContext(PythonFunctionContext): def _makeVariableStorage(self): return VariableStorage(heap_name="%s_heap" % self.getContextObjectName()) def isForDirectCall(self): return False def isForCreatedFunction(self): return False def getContextObjectName(self): return "generator" def getGeneratorReturnValueName(self): if python_version >= 0x300: return self.allocateTempName("return_value", "PyObject *", unique=True) else: return self.allocateTempName("generator_return", "bool", unique=True) class PythonCoroutineObjectContext(PythonGeneratorObjectContext): def getContextObjectName(self): return "coroutine" class PythonAsyncgenObjectContext(PythonGeneratorObjectContext): def getContextObjectName(self): return "asyncgen" class PythonFunctionCreatedContext(PythonFunctionContext): def isForDirectCall(self): return False def isForCreatedFunction(self): return True class PythonFunctionOutlineContext( ReturnReleaseModeMixin, ReturnValueNameMixin, PythonChildContextBase ): def __init__(self, parent, outline): PythonChildContextBase.__init__(self, parent=parent) ReturnReleaseModeMixin.__init__(self) ReturnValueNameMixin.__init__(self) self.outline = outline self.variable_storage = parent.variable_storage def getOwner(self): return self.outline def getEntryPoint(self): return self.outline.getEntryPoint() def allocateLabel(self, label): return self.parent.allocateLabel(label) def allocateTempName(self, base_name, type_name="PyObject *", unique=False): return self.parent.allocateTempName(base_name, type_name, unique) def skipTempName(self, base_name): return self.parent.skipTempName(base_name) def hasTempName(self, base_name): return self.parent.hasTempName(base_name) def getCleanupTempnames(self): return self.parent.getCleanupTempnames() def addCleanupTempName(self, tmp_name): self.parent.addCleanupTempName(tmp_name) def removeCleanupTempName(self, tmp_name): self.parent.removeCleanupTempName(tmp_name) def needsCleanup(self, tmp_name): return self.parent.needsCleanup(tmp_name) def pushCleanupScope(self): return self.parent.pushCleanupScope() def popCleanupScope(self): self.parent.popCleanupScope() def getCodeObjectHandle(self, code_object): return self.parent.getCodeObjectHandle(code_object) def getExceptionEscape(self): return self.parent.getExceptionEscape() def setExceptionEscape(self, label): return self.parent.setExceptionEscape(label) def getLoopBreakTarget(self): return self.parent.getLoopBreakTarget() def setLoopBreakTarget(self, label): return self.parent.setLoopBreakTarget(label) def getLoopContinueTarget(self): return self.parent.getLoopContinueTarget() def setLoopContinueTarget(self, label): return self.parent.setLoopContinueTarget(label) def getTrueBranchTarget(self): return self.parent.getTrueBranchTarget() def getFalseBranchTarget(self): return self.parent.getFalseBranchTarget() def setTrueBranchTarget(self, label): self.parent.setTrueBranchTarget(label) def setFalseBranchTarget(self, label): self.parent.setFalseBranchTarget(label) def getFrameHandle(self): return self.parent.getFrameHandle() def pushFrameHandle(self, code_identifier, is_light): return self.parent.pushFrameHandle(code_identifier, is_light) def popFrameHandle(self): return self.parent.popFrameHandle() def getExceptionKeeperVariables(self): return self.parent.getExceptionKeeperVariables() def setExceptionKeeperVariables(self, keeper_vars): return self.parent.setExceptionKeeperVariables(keeper_vars) def setVariableType(self, variable, variable_declaration): self.parent.setVariableType(variable, variable_declaration) def getIntResName(self): return self.parent.getIntResName() def getBoolResName(self): return self.parent.getBoolResName() def allocateExceptionKeeperVariables(self): return self.parent.allocateExceptionKeeperVariables() def isForDirectCall(self): return self.parent.isForDirectCall() def mayRecurse(self): # The outline is only accessible via its parent. return self.parent.mayRecurse() def addLocalsDictName(self, locals_dict_name): return self.parent.addLocalsDictName(locals_dict_name) def addExceptionPreserverVariables(self, count): return self.parent.addExceptionPreserverVariables(count) def getContextObjectName(self): return self.parent.getContextObjectName() Nuitka-0.6.19.1/nuitka/codegen/YieldCodes.py0000600000372100037210000001764314166627112025577 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Yield related codes. The normal "yield", and the Python 3.3 or higher "yield from" variant. """ from .CodeHelpers import ( generateChildExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitCode from .PythonAPICodes import getReferenceExportCode from .VariableDeclarations import VariableDeclaration def _getYieldPreserveCode( to_name, value_name, preserve_exception, yield_code, resume_code, emit, context ): yield_return_label = context.allocateLabel("yield_return") yield_return_index = yield_return_label.split("_")[-1] locals_preserved = context.variable_storage.getLocalPreservationDeclarations() # Need not preserve it, if we are not going to use it for the purpose # of releasing it. if type(value_name) is tuple: value_names = value_name else: value_names = (value_name,) for name in value_names: if not context.needsCleanup(name): locals_preserved.remove(name) # Target name is not assigned, no need to preserve it. if to_name in locals_preserved: locals_preserved.remove(to_name) if locals_preserved: yield_tmp_storage = context.variable_storage.getVariableDeclarationTop( "yield_tmps" ) if yield_tmp_storage is None: yield_tmp_storage = context.variable_storage.addVariableDeclarationTop( "char[1024]", "yield_tmps", None ) emit( "Nuitka_PreserveHeap(%s, %s, NULL);" % ( yield_tmp_storage, ", ".join( "&%s, sizeof(%s)" % (local_preserved, local_preserved.c_type) for local_preserved in locals_preserved ), ) ) if preserve_exception: emit( "SAVE_%s_EXCEPTION(%s);" % (context.getContextObjectName().upper(), context.getContextObjectName()) ) emit( """\ %(context_object_name)s->m_yield_return_index = %(yield_return_index)s;""" % { "context_object_name": context.getContextObjectName(), "yield_return_index": yield_return_index, } ) emit(yield_code) emit("%(yield_return_label)s:" % {"yield_return_label": yield_return_label}) if preserve_exception: emit( "RESTORE_%s_EXCEPTION(%s);" % (context.getContextObjectName().upper(), context.getContextObjectName()) ) if locals_preserved: emit( "Nuitka_RestoreHeap(%s, %s, NULL);" % ( yield_tmp_storage, ", ".join( "&%s, sizeof(%s)" % (local_preserved, local_preserved.c_type) for local_preserved in locals_preserved ), ) ) if resume_code: emit(resume_code) yield_return_name = VariableDeclaration( "PyObject *", "yield_return_value", None, None ) getErrorExitCode(check_name=yield_return_name, emit=emit, context=context) # Called with object emit("%s = %s;" % (to_name, yield_return_name)) def generateYieldCode(to_name, expression, emit, context): (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # In handlers, we must preserve/restore the exception. preserve_exception = expression.isExceptionPreserving() getReferenceExportCode(value_name, emit, context) if context.needsCleanup(value_name): context.removeCleanupTempName(value_name) yield_code = "return %(yielded_value)s;" % {"yielded_value": value_name} with withObjectCodeTemporaryAssignment( to_name, "yield_result", expression, emit, context ) as result_name: _getYieldPreserveCode( to_name=result_name, value_name=value_name, yield_code=yield_code, resume_code=None, preserve_exception=preserve_exception, emit=emit, context=context, ) # This conversion will not use it, and since it is borrowed, debug mode # would otherwise complain. if to_name.c_type == "nuitka_void": result_name.maybe_unused = True # Comes as only borrowed. # context.addCleanupTempName(result_name) def generateYieldFromCode(to_name, expression, emit, context): (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # In handlers, we must preserve/restore the exception. preserve_exception = expression.isExceptionPreserving() getReferenceExportCode(value_name, emit, context) if context.needsCleanup(value_name): context.removeCleanupTempName(value_name) yield_code = """\ generator->m_yieldfrom = %(yield_from)s; return NULL; """ % { "yield_from": value_name } with withObjectCodeTemporaryAssignment( to_name, "yieldfrom_result", expression, emit, context ) as result_name: _getYieldPreserveCode( to_name=result_name, value_name=value_name, yield_code=yield_code, resume_code=None, preserve_exception=preserve_exception, emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateYieldFromWaitableCode(to_name, expression, emit, context): # In handlers, we must preserve/restore the exception. preserve_exception = expression.isExceptionPreserving() (awaited_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) yield_code = """\ %(object_name)s->m_yieldfrom = %(yield_from)s; %(object_name)s->m_awaiting = true; return NULL; """ % { "object_name": context.getContextObjectName(), "yield_from": awaited_name, } resume_code = """\ %(object_name)s->m_awaiting = false; """ % { "object_name": context.getContextObjectName() } getReferenceExportCode(awaited_name, emit, context) if context.needsCleanup(awaited_name): context.removeCleanupTempName(awaited_name) with withObjectCodeTemporaryAssignment( to_name, "await_result", expression, emit, context ) as result_name: _getYieldPreserveCode( to_name=result_name, value_name=awaited_name, yield_code=yield_code, resume_code=resume_code, preserve_exception=preserve_exception, emit=emit, context=context, ) # TODO: Seems to be redundant with and _getYieldPreserveCode doing # it and could be removed getErrorExitCode(check_name=result_name, emit=emit, context=context) context.addCleanupTempName(result_name) def getYieldReturnDispatchCode(context): function_dispatch = [ "case %(index)d: goto yield_return_%(index)d;" % {"index": yield_index} for yield_index in range(context.getLabelCount("yield_return"), 0, -1) ] if function_dispatch: function_dispatch.insert( 0, "switch(%s->m_yield_return_index) {" % context.getContextObjectName() ) function_dispatch.append("}") return function_dispatch Nuitka-0.6.19.1/nuitka/codegen/GeneratorCodes.py0000600000372100037210000001670614166627112026456 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with compiled function objects. """ from nuitka.PythonVersions import python_version from .CodeHelpers import generateStatementSequenceCode from .Emission import SourceCodeCollector from .FunctionCodes import ( finalizeFunctionLocalVariables, getClosureCopyCode, getFunctionCreationArgs, getFunctionQualnameObj, setupFunctionLocalVariables, ) from .Indentation import indented from .ModuleCodes import getModuleAccessCode from .templates.CodeTemplatesGeneratorFunction import ( template_generator_exception_exit, template_generator_noexception_exit, template_generator_return_exit, template_genfunc_yielder_body_template, template_genfunc_yielder_maker_decl, template_make_empty_generator, template_make_generator, ) from .YieldCodes import getYieldReturnDispatchCode def _getGeneratorMakerIdentifier(function_identifier): return "MAKE_GENERATOR_" + function_identifier def getGeneratorObjectDeclCode(function_identifier, closure_variables): generator_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_genfunc_yielder_maker_decl % { "generator_maker_identifier": _getGeneratorMakerIdentifier(function_identifier), "generator_creation_args": ", ".join(generator_creation_args), } def getGeneratorObjectCode( context, function_identifier, closure_variables, user_variables, outline_variables, temp_variables, needs_exception_exit, needs_generator_return, ): # A bit of details going on here, pylint: disable=too-many-locals setupFunctionLocalVariables( context=context, parameters=None, closure_variables=closure_variables, user_variables=user_variables + outline_variables, temp_variables=temp_variables, ) function_codes = SourceCodeCollector() generateStatementSequenceCode( statement_sequence=context.getOwner().subnode_body, allow_none=True, emit=function_codes, context=context, ) function_cleanup = finalizeFunctionLocalVariables(context) if needs_exception_exit: ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() generator_exit = template_generator_exception_exit % { "function_cleanup": indented(function_cleanup), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, } else: generator_exit = template_generator_noexception_exit % { "function_cleanup": indented(function_cleanup) } if needs_generator_return: generator_exit += template_generator_return_exit % { "return_value": context.getReturnValueName() if python_version >= 0x300 else None } function_locals = context.variable_storage.makeCFunctionLevelDeclarations() local_type_decl = context.variable_storage.makeCStructLevelDeclarations() function_locals += context.variable_storage.makeCStructInits() generator_object_body = context.getOwner() if local_type_decl: heap_declaration = """\ struct %(function_identifier)s_locals *generator_heap = \ (struct %(function_identifier)s_locals *)generator->m_heap_storage;""" % { "function_identifier": function_identifier } else: heap_declaration = "" generator_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_genfunc_yielder_body_template % { "function_identifier": function_identifier, "function_body": indented(function_codes.codes), "heap_declaration": indented(heap_declaration), "function_local_types": indented(local_type_decl), "function_var_inits": indented(function_locals), "function_dispatch": indented(getYieldReturnDispatchCode(context)), "generator_maker_identifier": _getGeneratorMakerIdentifier(function_identifier), "generator_creation_args": ", ".join(generator_creation_args), "generator_exit": generator_exit, "generator_module": getModuleAccessCode(context), "generator_name_obj": context.getConstantCode( constant=generator_object_body.getFunctionName() ), "generator_qualname_obj": getFunctionQualnameObj( generator_object_body, context ), "code_identifier": context.getCodeObjectHandle( code_object=generator_object_body.getCodeObject() ), "closure_name": "closure" if closure_variables else "NULL", "closure_count": len(closure_variables), } def generateMakeGeneratorObjectCode(to_name, expression, emit, context): generator_object_body = expression.subnode_generator_ref.getFunctionBody() closure_variables = expression.getClosureVariableVersions() closure_name, closure_copy = getClosureCopyCode( closure_variables=closure_variables, context=context ) args = [] if closure_name: args.append(closure_name) # Special case empty generators. if generator_object_body.subnode_body is None: emit( template_make_empty_generator % { "closure_copy": indented(closure_copy, 0, True), "to_name": to_name, "generator_module": getModuleAccessCode(context), "generator_name_obj": context.getConstantCode( constant=generator_object_body.getFunctionName() ), "generator_qualname_obj": getFunctionQualnameObj( generator_object_body, context ), "code_identifier": context.getCodeObjectHandle( code_object=generator_object_body.getCodeObject() ), "closure_name": closure_name if closure_name is not None else "NULL", "closure_count": len(closure_variables), } ) else: emit( template_make_generator % { "generator_maker_identifier": _getGeneratorMakerIdentifier( generator_object_body.getCodeName() ), "to_name": to_name, "args": ", ".join(str(arg) for arg in args), "closure_copy": indented(closure_copy, 0, True), } ) context.addCleanupTempName(to_name) Nuitka-0.6.19.1/nuitka/codegen/PrintCodes.py0000600000372100037210000000571514166627112025622 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Print related codes. This is broken down to to level on printing one individual item, and a new line potentially. The heavy lifting for 'softspace', etc. is happening in the C helper functions. """ from .CodeHelpers import generateExpressionCode from .ErrorCodes import getErrorExitBoolCode def generatePrintValueCode(statement, emit, context): destination = statement.subnode_dest value = statement.subnode_value if destination is not None: dest_name = context.allocateTempName("print_dest", unique=True) generateExpressionCode( expression=destination, to_name=dest_name, emit=emit, context=context ) else: dest_name = None value_name = context.allocateTempName("print_value", unique=True) generateExpressionCode( expression=value, to_name=value_name, emit=emit, context=context ) with context.withCurrentSourceCodeReference(statement.getSourceReference()): res_name = context.getBoolResName() if dest_name is not None: print_code = "%s = PRINT_ITEM_TO(%s, %s);" % ( res_name, dest_name, value_name, ) else: print_code = "%s = PRINT_ITEM(%s);" % (res_name, value_name) emit(print_code) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(dest_name, value_name), emit=emit, context=context, ) def generatePrintNewlineCode(statement, emit, context): destination = statement.subnode_dest if destination is not None: dest_name = context.allocateTempName("print_dest", unique=True) generateExpressionCode( expression=destination, to_name=dest_name, emit=emit, context=context ) else: dest_name = None with context.withCurrentSourceCodeReference(statement.getSourceReference()): if dest_name is not None: print_code = "PRINT_NEW_LINE_TO(%s) == false" % (dest_name,) else: print_code = "PRINT_NEW_LINE() == false" getErrorExitBoolCode( condition=print_code, release_name=dest_name, emit=emit, context=context ) Nuitka-0.6.19.1/nuitka/codegen/IndexCodes.py0000600000372100037210000000274214166627112025572 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for index values. This is not for actual subscripts (see SubscriptCodes), but to convert generic values to indexes. Also the maximum and minimum index values are abstracted here. """ from .ErrorCodes import getErrorExitBoolCode def getMaxIndexCode(to_name, emit): emit("%s = PY_SSIZE_T_MAX;" % to_name) def getMinIndexCode(to_name, emit): emit("%s = 0;" % to_name) def getIndexCode(to_name, value_name, emit, context): emit("%s = CONVERT_TO_INDEX(%s);" % (to_name, value_name)) getErrorExitBoolCode( condition="%s == -1 && ERROR_OCCURRED()" % to_name, emit=emit, context=context ) def getIndexValueCode(to_name, value, emit): emit("%s = %d;" % (to_name, value)) Nuitka-0.6.19.1/nuitka/codegen/GlobalConstants.py0000600000372100037210000001141614166627112026640 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Global constant values. """ from nuitka import Options from nuitka.__past__ import long from nuitka.PythonVersions import python_version def getConstantDefaultPopulation(): """These are values for non-trivial constants. Constants that have a direct name, e.g. Py_True are trivial, these are for things that must be constructed through code. """ # Lots of cases, pylint: disable=too-many-branches # Note: Can't work with set here, because we need to put in some values that # cannot be hashed. result = [ # Basic values that the helper code uses all the times. (), {}, 0, 1, -1, # Some math operations shortcut to these 0.0, -0.0, 1.0, -1.0, long(0), "", # For Python3 empty bytes, no effect for Python2, same as "", used for # code objects. b"", # Python mechanics, used in various helpers. "__module__", "__class__", "__name__", "__package__", "__metaclass__", "__abstractmethods__", "__dict__", "__doc__", "__file__", "__path__", "__enter__", "__exit__", "__builtins__", "__all__", "__init__", "__cmp__", "__iter__", # Nuitka specific "__compiled__", # Patched module name. "inspect", # Names of built-ins used in helper code. "compile", "range", "open", "sum", "format", "__import__", "bytearray", "staticmethod", "classmethod", "keys", # Arguments of __import__ built-in used in helper code. "name", "globals", "locals", "fromlist", "level", # Meta path based loader. "read", "rb", ] # Pickling of instance methods. if python_version < 0x340: result += ("__newobj__",) else: result += ("getattr",) if python_version >= 0x300: # For Python3 modules result += ("__cached__", "__loader__") # For Python3 print result += ("print", "end", "file") # For Python3 "bytes" built-in. result.append("bytes") # For meta path based loader, iter_modules and Python3 "__name__" to # "__package__" parsing result.append(".") if python_version >= 0x300: # Modules have that attribute starting with Python3 result.append("__loader__") if python_version >= 0x340: result.append( # YIELD_FROM uses this starting 3.4, with 3.3 other code is used. "send" ) if python_version >= 0x300: result += ( # YIELD_FROM uses this "throw", "close", ) if python_version < 0x300: # For patching Python2 internal class type result += ("__getattr__", "__setattr__", "__delattr__") # For setting Python2 "sys" attributes for current exception result += ("exc_type", "exc_value", "exc_traceback") # Abstract base classes need to call the method result.append("join") # The xrange built-in is Python2 only. if python_version < 0x300: result.append("xrange") # Executables only if not Options.shallMakeModule(): # The "site" module is referenced in inspect patching. result.append("site") # Built-in original values if not Options.shallMakeModule(): result += ("type", "len", "range", "repr", "int", "iter") if python_version < 0x300: result.append("long") if python_version >= 0x340: # Work with the __spec__ module attribute. result += ("__spec__", "_initializing", "parent") if python_version >= 0x350: # Patching the types module. result.append("types") if not Options.shallMakeModule(): result.append("__main__") if python_version >= 0x370: result.append("__class_getitem__") return result Nuitka-0.6.19.1/nuitka/codegen/IdCodes.py0000600000372100037210000000340214166627112025051 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Codes for id and hash """ from .CodeHelpers import decideConversionCheckNeeded from .PythonAPICodes import generateCAPIObjectCode def generateBuiltinIdCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PyLong_FromVoidPtr", arg_desc=(("id_arg", expression.subnode_value),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinHashCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_HASH", arg_desc=(("hash_arg", expression.subnode_value),), may_raise=expression.mayRaiseExceptionOperation(), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/GlobalsLocalsCodes.py0000600000372100037210000001627314166627112027250 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for locals and globals handling. This also includes writing back to locals for exec statements. """ from .CodeHelpers import ( decideConversionCheckNeeded, withObjectCodeTemporaryAssignment, ) from .Emission import SourceCodeCollector from .ErrorCodes import getErrorExitBoolCode from .Indentation import indented from .PythonAPICodes import generateCAPIObjectCode from .templates.CodeTemplatesVariables import ( template_set_locals_dict_value, template_set_locals_mapping_value, template_update_locals_dict_value, template_update_locals_mapping_value, ) from .VariableCodes import ( getLocalVariableDeclaration, getVariableReferenceCode, ) from .VariableDeclarations import VariableDeclaration def generateBuiltinLocalsRefCode(to_name, expression, emit, context): locals_scope = expression.getLocalsScope() locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) with withObjectCodeTemporaryAssignment( to_name, "locals_ref_value", expression, emit, context ) as value_name: emit("%s = %s;" % (value_name, locals_declaration)) def generateBuiltinLocalsCode(to_name, expression, emit, context): variable_traces = expression.getVariableTraces() updated = expression.isExpressionBuiltinLocalsUpdated() locals_scope = expression.getLocalsScope() # Locals is sorted of course. def _sorted(variables): variable_order = tuple(locals_scope.getProvidedVariables()) return sorted( variables, key=lambda variable_desc: variable_order.index(variable_desc[0]) ) with withObjectCodeTemporaryAssignment( to_name, "locals_ref_value", expression, emit, context ) as value_name: if updated: locals_declaration = context.addLocalsDictName(locals_scope.getCodeName()) is_dict = locals_scope.hasShapeDictionaryExact() # For Python3 it may really not be a dictionary. # TODO: Creation is not needed for classes. emit( """\ if (%(locals_dict)s == NULL) %(locals_dict)s = PyDict_New(); %(to_name)s = %(locals_dict)s; Py_INCREF(%(to_name)s);""" % {"to_name": value_name, "locals_dict": locals_declaration} ) context.addCleanupTempName(value_name) initial = False else: emit("%s = PyDict_New();" % (to_name,)) context.addCleanupTempName(value_name) initial = True is_dict = True for local_var, variable_trace in _sorted(variable_traces): _getVariableDictUpdateCode( target_name=value_name, variable=local_var, variable_trace=variable_trace, is_dict=is_dict, initial=initial, emit=emit, context=context, ) def generateBuiltinGlobalsCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "globals_value", expression, emit, context ) as value_name: emit( "%(to_name)s = (PyObject *)moduledict_%(module_identifier)s;" % {"to_name": value_name, "module_identifier": context.getModuleCodeName()} ) def _getLocalVariableList(provider): if provider.isExpressionFunctionBody(): include_closure = not provider.isUnoptimized() elif provider.isExpressionClassBody(): include_closure = False else: include_closure = True return [ variable for variable in provider.getProvidedVariables() if not variable.isModuleVariable() if (include_closure or variable.getOwner() is provider) ] def _getVariableDictUpdateCode( target_name, variable, variable_trace, initial, is_dict, emit, context ): # TODO: Variable could known to be set here, get a hand at that # information. variable_declaration = getLocalVariableDeclaration( context, variable, variable_trace ) variable_c_type = variable_declaration.getCType() test_code = variable_c_type.getInitTestConditionCode( value_name=variable_declaration, inverted=False ) access_code = SourceCodeCollector() getVariableReferenceCode( to_name=VariableDeclaration("PyObject *", "value", None, None), variable=variable, variable_trace=variable_trace, needs_check=False, conversion_check=True, emit=access_code, context=context, ) if is_dict: if initial: template = template_set_locals_dict_value else: template = template_update_locals_dict_value emit( template % { "dict_name": target_name, "var_name": context.getConstantCode(constant=variable.getName()), "test_code": test_code, "access_code": indented(access_code.codes), } ) else: if initial: template = template_set_locals_mapping_value else: template = template_update_locals_mapping_value res_name = context.getBoolResName() emit( template % { "mapping_name": target_name, "var_name": context.getConstantCode(constant=variable.getName()), "test_code": test_code, "access_code": access_code, "tmp_name": res_name, } ) getErrorExitBoolCode( condition="%s == false" % res_name, emit=emit, context=context ) def generateBuiltinDir1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PyObject_Dir", arg_desc=(("dir_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinVarsCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="LOOKUP_VARS", arg_desc=(("vars_arg", expression.subnode_source),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/ListCodes.py0000600000372100037210000001364514166627112025442 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for lists. Right now only the creation is done here. But more should be added later on. """ from .CodeHelpers import ( assignConstantNoneResult, decideConversionCheckNeeded, generateChildExpressionsCode, generateExpressionCode, withCleanupFinally, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode from .PythonAPICodes import generateCAPIObjectCode def generateListCreationCode(to_name, expression, emit, context): elements = expression.subnode_elements assert elements with withObjectCodeTemporaryAssignment( to_name, "list_result", expression, emit, context ) as result_name: element_name = context.allocateTempName("list_element") def generateElementCode(element): generateExpressionCode( to_name=element_name, expression=element, emit=emit, context=context ) # Use helper that makes sure we provide a reference. if context.needsCleanup(element_name): context.removeCleanupTempName(element_name) helper_code = "PyList_SET_ITEM" else: helper_code = "PyList_SET_ITEM0" return helper_code helper_code = generateElementCode(elements[0]) emit("%s = PyList_New(%d);" % (result_name, len(elements))) needs_exception_exit = any( element.mayRaiseException(BaseException) for element in elements[1:] ) with withCleanupFinally( "list_build", result_name, needs_exception_exit, emit, context ) as guarded_emit: emit = guarded_emit.emit for count, element in enumerate(elements): if count > 0: helper_code = generateElementCode(element) emit( "%s(%s, %d, %s);" % (helper_code, result_name, count, element_name) ) def generateListOperationAppendCode(statement, emit, context): list_arg_name = context.allocateTempName("append_list") generateExpressionCode( to_name=list_arg_name, expression=statement.subnode_list_arg, emit=emit, context=context, ) value_arg_name = context.allocateTempName("append_value") generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_value, emit=emit, context=context, ) context.setCurrentSourceCodeReference(statement.getSourceReference()) res_name = context.getBoolResName() emit("assert(PyList_Check(%s));" % list_arg_name) if context.needsCleanup(value_arg_name): emit("%s = LIST_APPEND1(%s, %s);" % (res_name, list_arg_name, value_arg_name)) context.removeCleanupTempName(value_arg_name) else: emit("%s = LIST_APPEND0(%s, %s);" % (res_name, list_arg_name, value_arg_name)) # TODO: Only really MemoryError, which we often ignore. getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(list_arg_name, value_arg_name), emit=emit, context=context, ) def generateListOperationExtendCode(to_name, expression, emit, context): list_arg_name, value_arg_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) emit("assert(PyList_Check(%s));" % list_arg_name) # These give different error messages. is_unpack = expression.isExpressionListOperationExtendForUnpack() res_name = context.getBoolResName() emit( "%s = %s(%s, %s);" % ( res_name, "LIST_EXTEND_FOR_UNPACK" if is_unpack else "LIST_EXTEND", list_arg_name, value_arg_name, ) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(list_arg_name, value_arg_name), emit=emit, context=context, ) assignConstantNoneResult(to_name, emit, context) def generateListOperationPopCode(to_name, expression, emit, context): (list_arg_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) emit("assert(PyList_Check(%s));" % list_arg_name) with withObjectCodeTemporaryAssignment( to_name, "list_pop_result", expression, emit, context ) as result_name: # TODO: Have a dedicated helper instead, this could be more efficient. emit( '%s = PyObject_CallMethod(%s, (char *)"pop", NULL);' % (result_name, list_arg_name) ) getErrorExitCode( check_name=result_name, release_name=list_arg_name, emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateBuiltinListCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="MAKE_LIST", arg_desc=(("list_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/IteratorCodes.py0000600000372100037210000002441714166627112026317 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Iteration related codes. Next variants and unpacking with related checks. """ from nuitka.PythonVersions import python_version from .CodeHelpers import ( decideConversionCheckNeeded, generateChildExpressionsCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import ( getErrorExitCode, getErrorExitReleaseCode, getFrameVariableTypeDescriptionCode, getReleaseCode, ) from .Indentation import indented from .LineNumberCodes import getErrorLineNumberUpdateCode from .PythonAPICodes import generateCAPIObjectCode from .templates.CodeTemplatesIterators import ( template_iterator_check, template_loop_break_next, ) def generateBuiltinNext1Code(to_name, expression, emit, context): (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "next_value", expression, emit, context ) as result_name: emit("%s = %s;" % (result_name, "ITERATOR_NEXT(%s)" % value_name)) getErrorExitCode( check_name=result_name, release_name=value_name, quick_exception="StopIteration", emit=emit, context=context, ) context.addCleanupTempName(result_name) def getBuiltinLoopBreakNextCode(to_name, value, emit, context): emit("%s = %s;" % (to_name, "ITERATOR_NEXT(%s)" % value)) getReleaseCode(release_name=value, emit=emit, context=context) break_target = context.getLoopBreakTarget() if type(break_target) is tuple: break_indicator_code = "%s = true;" % break_target[1] break_target = break_target[0] else: break_indicator_code = "" ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit( template_loop_break_next % { "to_name": to_name, "break_indicator_code": break_indicator_code, "break_target": break_target, "release_temps": indented(getErrorExitReleaseCode(context), 2), "var_description_code": indented( getFrameVariableTypeDescriptionCode(context), 2 ), "line_number_code": indented(getErrorLineNumberUpdateCode(context), 2), "exception_target": context.getExceptionEscape(), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, } ) context.addCleanupTempName(to_name) def generateSpecialUnpackCode(to_name, expression, emit, context): value_name = context.allocateTempName("unpack") generateExpressionCode( to_name=value_name, expression=expression.subnode_value, emit=emit, context=context, ) with withObjectCodeTemporaryAssignment( to_name, "unpack_value", expression, emit, context ) as result_name: needs_check = expression.mayRaiseExceptionOperation() if not needs_check: emit("%s = UNPACK_NEXT_INFALLIBLE(%s);" % (result_name, value_name)) elif python_version < 0x350: emit( "%s = UNPACK_NEXT(%s, %s);" % (result_name, value_name, expression.getCount() - 1) ) else: starred = expression.getStarred() expected = expression.getExpected() emit( "%s = UNPACK_NEXT%s(%s, %s, %s);" % ( result_name, "_STARRED" if starred else "", value_name, expression.getCount() - 1, expected, ) ) getErrorExitCode( check_name=result_name, release_name=value_name, quick_exception="StopIteration", needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def generateUnpackCheckCode(statement, emit, context): iterator_name = context.allocateTempName("iterator_name") generateExpressionCode( to_name=iterator_name, expression=statement.subnode_iterator, emit=emit, context=context, ) # These variable cannot collide, as it's used very locally. attempt_name = context.allocateTempName("iterator_attempt", unique=True) release_code = getErrorExitReleaseCode(context) var_description_code = getFrameVariableTypeDescriptionCode(context) with context.withCurrentSourceCodeReference(statement.getSourceReference()): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit( template_iterator_check % { "iterator_name": iterator_name, "attempt_name": attempt_name, "exception_exit": context.getExceptionEscape(), "release_temps_1": indented(release_code, 3), "line_number_code_1": indented( getErrorLineNumberUpdateCode(context), 3 ), "var_description_code_1": indented(var_description_code, 3), "release_temps_2": indented(release_code), "var_description_code_2": indented(var_description_code), "line_number_code_2": indented(getErrorLineNumberUpdateCode(context)), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "too_many_values_error": context.getConstantCode( "too many values to unpack" if python_version < 0x300 else "too many values to unpack (expected %d)" % statement.getCount() ), } ) getReleaseCode(release_name=iterator_name, emit=emit, context=context) def generateBuiltinNext2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_NEXT2", arg_desc=( ("next_arg", expression.subnode_iterator), ("next_default", expression.subnode_default), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinIter1Code(to_name, expression, emit, context): may_raise = expression.mayRaiseExceptionOperation() generateCAPIObjectCode( to_name=to_name, capi="MAKE_ITERATOR" if may_raise else "MAKE_ITERATOR_INFALLIBLE", arg_desc=(("iter_arg", expression.subnode_value),), may_raise=may_raise, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinIterForUnpackCode(to_name, expression, emit, context): may_raise = expression.mayRaiseExceptionOperation() generateCAPIObjectCode( to_name=to_name, capi="MAKE_UNPACK_ITERATOR" if may_raise else "MAKE_ITERATOR_INFALLIBLE", arg_desc=(("iter_arg", expression.subnode_value),), may_raise=may_raise, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinIter2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_ITER2", arg_desc=( ("iter_callable", expression.subnode_callable_arg), ("iter_sentinel", expression.subnode_sentinel), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinLenCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_LEN", arg_desc=(("len_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinAnyCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_ANY", arg_desc=(("any_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinAllCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_ALL", arg_desc=(("all_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/CoroutineCodes.py0000600000372100037210000002034014166627112026464 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with compiled coroutine objects. """ from .CodeHelpers import ( generateChildExpressionsCode, generateStatementSequenceCode, withObjectCodeTemporaryAssignment, ) from .Emission import SourceCodeCollector from .ErrorCodes import getErrorExitCode from .FunctionCodes import ( finalizeFunctionLocalVariables, getClosureCopyCode, getFunctionCreationArgs, getFunctionQualnameObj, setupFunctionLocalVariables, ) from .Indentation import indented from .LineNumberCodes import emitLineNumberUpdateCode from .ModuleCodes import getModuleAccessCode from .templates.CodeTemplatesCoroutines import ( template_coroutine_exception_exit, template_coroutine_noexception_exit, template_coroutine_object_body, template_coroutine_object_maker, template_coroutine_return_exit, template_make_coroutine, ) from .YieldCodes import getYieldReturnDispatchCode def _getCoroutineMakerIdentifier(function_identifier): return "MAKE_COROUTINE_" + function_identifier def getCoroutineObjectDeclCode(function_identifier, closure_variables): coroutine_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_coroutine_object_maker % { "coroutine_maker_identifier": _getCoroutineMakerIdentifier(function_identifier), "coroutine_creation_args": ", ".join(coroutine_creation_args), } def getCoroutineObjectCode( context, function_identifier, closure_variables, user_variables, outline_variables, temp_variables, needs_exception_exit, needs_generator_return, ): # A bit of details going on here, pylint: disable=too-many-locals setupFunctionLocalVariables( context=context, parameters=None, closure_variables=closure_variables, user_variables=user_variables + outline_variables, temp_variables=temp_variables, ) function_codes = SourceCodeCollector() coroutine_object_body = context.getOwner() generateStatementSequenceCode( statement_sequence=coroutine_object_body.subnode_body, allow_none=True, emit=function_codes, context=context, ) function_cleanup = finalizeFunctionLocalVariables(context) if needs_exception_exit: ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() generator_exit = template_coroutine_exception_exit % { "function_cleanup": indented(function_cleanup), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, } else: generator_exit = template_coroutine_noexception_exit % { "function_cleanup": indented(function_cleanup) } if needs_generator_return: generator_exit += template_coroutine_return_exit % { "return_value": context.getReturnValueName() } function_locals = context.variable_storage.makeCFunctionLevelDeclarations() local_type_decl = context.variable_storage.makeCStructLevelDeclarations() function_locals += context.variable_storage.makeCStructInits() if local_type_decl: heap_declaration = """\ struct %(function_identifier)s_locals *coroutine_heap = \ (struct %(function_identifier)s_locals *)coroutine->m_heap_storage;""" % { "function_identifier": function_identifier } else: heap_declaration = "" coroutine_creation_args = getFunctionCreationArgs( defaults_name=None, kw_defaults_name=None, annotations_name=None, closure_variables=closure_variables, ) return template_coroutine_object_body % { "function_identifier": function_identifier, "function_body": indented(function_codes.codes), "heap_declaration": indented(heap_declaration), "function_local_types": indented(local_type_decl), "function_var_inits": indented(function_locals), "function_dispatch": indented(getYieldReturnDispatchCode(context)), "coroutine_maker_identifier": _getCoroutineMakerIdentifier(function_identifier), "coroutine_creation_args": ", ".join(coroutine_creation_args), "coroutine_exit": generator_exit, "coroutine_module": getModuleAccessCode(context), "coroutine_name_obj": context.getConstantCode( constant=coroutine_object_body.getFunctionName() ), "coroutine_qualname_obj": getFunctionQualnameObj( coroutine_object_body, context ), "code_identifier": context.getCodeObjectHandle( code_object=coroutine_object_body.getCodeObject() ), "closure_name": "closure" if closure_variables else "NULL", "closure_count": len(closure_variables), } def generateMakeCoroutineObjectCode(to_name, expression, emit, context): coroutine_object_body = expression.subnode_coroutine_ref.getFunctionBody() closure_variables = expression.getClosureVariableVersions() closure_name, closure_copy = getClosureCopyCode( closure_variables=closure_variables, context=context ) args = [] if closure_name: args.append(closure_name) emit( template_make_coroutine % { "to_name": to_name, "coroutine_maker_identifier": _getCoroutineMakerIdentifier( coroutine_object_body.getCodeName() ), "args": ", ".join(str(arg) for arg in args), "closure_copy": indented(closure_copy, 0, True), } ) context.addCleanupTempName(to_name) def generateAsyncWaitCode(to_name, expression, emit, context): emitLineNumberUpdateCode(expression, emit, context) (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) if expression.isExpressionAsyncWaitEnter(): wait_kind = "await_enter" elif expression.isExpressionAsyncWaitExit(): wait_kind = "await_exit" else: wait_kind = "await_normal" emit("%s = ASYNC_AWAIT(%s, %s);" % (to_name, value_name, wait_kind)) getErrorExitCode( check_name=to_name, release_name=value_name, emit=emit, context=context ) context.addCleanupTempName(to_name) def generateAsyncIterCode(to_name, expression, emit, context): (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "aiter_result", expression, emit, context ) as result_name: emit("%s = ASYNC_MAKE_ITERATOR(%s);" % (result_name, value_name)) getErrorExitCode( check_name=result_name, release_name=value_name, emit=emit, context=context ) context.addCleanupTempName(result_name) def generateAsyncNextCode(to_name, expression, emit, context): (value_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "anext_result", expression, emit, context ) as result_name: emit("%s = ASYNC_ITERATOR_NEXT(%s);" % (result_name, value_name)) getErrorExitCode( check_name=result_name, release_name=value_name, emit=emit, context=context ) context.addCleanupTempName(result_name) Nuitka-0.6.19.1/nuitka/codegen/BranchCodes.py0000600000372100037210000000444314166627112025720 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Branch related codes. """ from .CodeHelpers import generateStatementSequenceCode from .ConditionalCodes import generateConditionCode from .Emission import withSubCollector from .LabelCodes import getGotoCode, getLabelCode def generateBranchCode(statement, emit, context): true_target = context.allocateLabel("branch_yes") false_target = context.allocateLabel("branch_no") end_target = context.allocateLabel("branch_end") old_true_target = context.getTrueBranchTarget() old_false_target = context.getFalseBranchTarget() context.setTrueBranchTarget(true_target) context.setFalseBranchTarget(false_target) # Have own declaration scope for condition, to limit visibility from branches # which can be huge. with withSubCollector(emit, context) as condition_emit: generateConditionCode( condition=statement.subnode_condition, emit=condition_emit, context=context ) context.setTrueBranchTarget(old_true_target) context.setFalseBranchTarget(old_false_target) getLabelCode(true_target, emit) generateStatementSequenceCode( statement_sequence=statement.subnode_yes_branch, emit=emit, context=context ) if statement.subnode_no_branch is not None: getGotoCode(end_target, emit) getLabelCode(false_target, emit) generateStatementSequenceCode( statement_sequence=statement.subnode_no_branch, emit=emit, context=context ) getLabelCode(end_target, emit) else: getLabelCode(false_target, emit) Nuitka-0.6.19.1/nuitka/codegen/CodeGeneration.py0000600000372100037210000011367714166627112026445 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ The code generation. No language specifics at all are supposed to be present here. Instead it is using primitives from the given generator to build code sequences (list of strings). As such this is the place that knows how to take a condition and two code branches and make a code block out of it. But it doesn't contain any target language syntax. """ from nuitka.nodes.AttributeNodesGenerated import ( attribute_classes, attribute_typed_classes, ) from nuitka.nodes.StrNodes import getStrOperationClasses from nuitka.plugins.Plugins import Plugins from nuitka.utils.CStrings import encodePythonStringToC from . import Contexts from .AsyncgenCodes import ( generateMakeAsyncgenObjectCode, getAsyncgenObjectCode, getAsyncgenObjectDeclCode, ) from .AttributeCodes import ( generateAssignmentAttributeCode, generateAttributeCheckCode, generateAttributeLookupCode, generateAttributeLookupSpecialCode, generateBuiltinGetattrCode, generateBuiltinHasattrCode, generateBuiltinSetattrCode, generateDelAttributeCode, ) from .BranchCodes import generateBranchCode from .BuiltinCodes import ( generateBuiltinAbsCode, generateBuiltinAnonymousRefCode, generateBuiltinBinCode, generateBuiltinBoolCode, generateBuiltinBytearray1Code, generateBuiltinBytearray3Code, generateBuiltinClassmethodCode, generateBuiltinComplex1Code, generateBuiltinComplex2Code, generateBuiltinFloatCode, generateBuiltinHexCode, generateBuiltinOctCode, generateBuiltinOpenCode, generateBuiltinRange1Code, generateBuiltinRange2Code, generateBuiltinRange3Code, generateBuiltinRefCode, generateBuiltinStaticmethodCode, generateBuiltinSum1Code, generateBuiltinSum2Code, generateBuiltinType1Code, generateBuiltinType3Code, generateBuiltinXrange1Code, generateBuiltinXrange2Code, generateBuiltinXrange3Code, ) from .CallCodes import generateCallCode, getCallsCode from .ClassCodes import generateBuiltinSuperCode, generateSelectMetaclassCode from .CodeHelpers import addExpressionDispatchDict, setStatementDispatchDict from .ComparisonCodes import ( generateBuiltinIsinstanceCode, generateBuiltinIssubclassCode, generateComparisonExpressionCode, generateMatchTypeCheckMappingCode, generateMatchTypeCheckSequenceCode, generateTypeCheckCode, ) from .ConditionalCodes import ( generateConditionalAndOrCode, generateConditionalCode, ) from .ConstantCodes import ( generateConstantGenericAliasCode, generateConstantReferenceCode, getConstantsDefinitionCode, ) from .CoroutineCodes import ( generateAsyncIterCode, generateAsyncNextCode, generateAsyncWaitCode, generateMakeCoroutineObjectCode, getCoroutineObjectCode, getCoroutineObjectDeclCode, ) from .DictCodes import ( generateBuiltinDictCode, generateDictionaryCreationCode, generateDictOperationClearCode, generateDictOperationCopyCode, generateDictOperationGet2Code, generateDictOperationGet3Code, generateDictOperationInCode, generateDictOperationItemCode, generateDictOperationItemsCode, generateDictOperationIteritemsCode, generateDictOperationIterkeysCode, generateDictOperationItervaluesCode, generateDictOperationKeysCode, generateDictOperationPop2Code, generateDictOperationPop3Code, generateDictOperationRemoveCode, generateDictOperationSetCode, generateDictOperationSetCodeKeyValue, generateDictOperationSetdefault2Code, generateDictOperationSetdefault3Code, generateDictOperationUpdate2Code, generateDictOperationUpdate3Code, generateDictOperationUpdateCode, generateDictOperationValuesCode, generateDictOperationViewitemsCode, generateDictOperationViewkeysCode, generateDictOperationViewvaluesCode, ) from .EvalCodes import ( generateBuiltinCompileCode, generateEvalCode, generateExecCode, generateExecfileCode, generateLocalsDictSyncCode, ) from .ExceptionCodes import ( generateBuiltinMakeExceptionCode, generateExceptionCaughtTracebackCode, generateExceptionCaughtTypeCode, generateExceptionCaughtValueCode, generateExceptionPublishCode, generateExceptionRefCode, ) from .ExpressionCodes import ( generateExpressionOnlyCode, generateSideEffectsCode, ) from .FrameCodes import ( generateFramePreserveExceptionCode, generateFrameRestoreExceptionCode, ) from .FunctionCodes import ( generateFunctionCallCode, generateFunctionCreationCode, generateFunctionErrorStrCode, generateFunctionOutlineCode, getExportScopeCode, getFunctionCode, getFunctionDirectDecl, ) from .GeneratorCodes import ( generateMakeGeneratorObjectCode, getGeneratorObjectCode, getGeneratorObjectDeclCode, ) from .GlobalsLocalsCodes import ( generateBuiltinDir1Code, generateBuiltinGlobalsCode, generateBuiltinLocalsCode, generateBuiltinLocalsRefCode, generateBuiltinVarsCode, ) from .IdCodes import generateBuiltinHashCode, generateBuiltinIdCode from .ImportCodes import ( generateBuiltinImportCode, generateConstantSysVersionInfoCode, generateImportlibImportCallCode, generateImportModuleFixedCode, generateImportModuleHardCode, generateImportModuleNameHardCode, generateImportNameCode, generateImportStarCode, ) from .IntegerCodes import ( generateBuiltinInt1Code, generateBuiltinInt2Code, generateBuiltinLong1Code, generateBuiltinLong2Code, ) from .IteratorCodes import ( generateBuiltinAllCode, generateBuiltinAnyCode, generateBuiltinIter1Code, generateBuiltinIter2Code, generateBuiltinIterForUnpackCode, generateBuiltinLenCode, generateBuiltinNext1Code, generateBuiltinNext2Code, generateSpecialUnpackCode, generateUnpackCheckCode, ) from .ListCodes import ( generateBuiltinListCode, generateListCreationCode, generateListOperationAppendCode, generateListOperationExtendCode, generateListOperationPopCode, ) from .LocalsDictCodes import ( generateLocalsDictDelCode, generateLocalsDictSetCode, generateLocalsDictVariableCheckCode, generateLocalsDictVariableRefCode, generateLocalsDictVariableRefOrFallbackCode, generateReleaseLocalsDictCode, generateSetLocalsDictCode, ) from .LoopCodes import ( generateLoopBreakCode, generateLoopCode, generateLoopContinueCode, ) from .ModuleCodes import ( generateModuleAttributeCode, generateModuleAttributeFileCode, generateNuitkaLoaderCreationCode, getModuleCode, ) from .OperationCodes import ( generateOperationBinaryCode, generateOperationNotCode, generateOperationUnaryCode, ) from .PrintCodes import generatePrintNewlineCode, generatePrintValueCode from .RaisingCodes import ( generateRaiseCode, generateRaiseExpressionCode, generateReraiseCode, ) from .ReturnCodes import ( generateGeneratorReturnNoneCode, generateGeneratorReturnValueCode, generateReturnCode, generateReturnConstantCode, generateReturnedValueCode, ) from .SetCodes import ( generateBuiltinFrozensetCode, generateBuiltinSetCode, generateSetCreationCode, generateSetLiteralCreationCode, generateSetOperationAddCode, generateSetOperationUpdateCode, ) from .SliceCodes import ( generateAssignmentSliceCode, generateBuiltinSlice1Code, generateBuiltinSlice2Code, generateBuiltinSlice3Code, generateDelSliceCode, generateSliceLookupCode, ) from .StringCodes import ( generateBuiltinAsciiCode, generateBuiltinBytes1Code, generateBuiltinBytes3Code, generateBuiltinChrCode, generateBuiltinFormatCode, generateBuiltinOrdCode, generateBuiltinStrCode, generateBuiltinUnicodeCode, generateStringContenationCode, generateStrOperationCode, ) from .SubscriptCodes import ( generateAssignmentSubscriptCode, generateDelSubscriptCode, generateSubscriptCheckCode, generateSubscriptLookupCode, ) from .TryCodes import generateTryCode from .TupleCodes import generateBuiltinTupleCode, generateTupleCreationCode from .VariableCodes import ( generateAssignmentVariableCode, generateDelVariableCode, generateVariableReferenceCode, generateVariableReleaseCode, ) from .YieldCodes import ( generateYieldCode, generateYieldFromCode, generateYieldFromWaitableCode, ) _generated_functions = {} def generateFunctionBodyCode(function_body, context): # TODO: Generate both codes, and base direct/etc. decisions on context. # pylint: disable=too-many-branches function_identifier = function_body.getCodeName() if function_identifier in _generated_functions: return _generated_functions[function_identifier] if function_body.isExpressionGeneratorObjectBody(): function_context = Contexts.PythonGeneratorObjectContext( parent=context, function=function_body ) elif function_body.isExpressionClassBody(): function_context = Contexts.PythonFunctionDirectContext( parent=context, function=function_body ) elif function_body.isExpressionCoroutineObjectBody(): function_context = Contexts.PythonCoroutineObjectContext( parent=context, function=function_body ) elif function_body.isExpressionAsyncgenObjectBody(): function_context = Contexts.PythonAsyncgenObjectContext( parent=context, function=function_body ) elif function_body.needsCreation(): function_context = Contexts.PythonFunctionCreatedContext( parent=context, function=function_body ) else: function_context = Contexts.PythonFunctionDirectContext( parent=context, function=function_body ) needs_exception_exit = function_body.mayRaiseException(BaseException) if function_body.isExpressionGeneratorObjectBody(): function_code = getGeneratorObjectCode( context=function_context, function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), user_variables=function_body.getUserLocalVariables(), outline_variables=function_body.getOutlineLocalVariables(), temp_variables=function_body.getTempVariables(), needs_exception_exit=needs_exception_exit, needs_generator_return=function_body.needsGeneratorReturnExit(), ) function_decl = getGeneratorObjectDeclCode( function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), ) elif function_body.isExpressionCoroutineObjectBody(): function_code = getCoroutineObjectCode( context=function_context, function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), user_variables=function_body.getUserLocalVariables(), outline_variables=function_body.getOutlineLocalVariables(), temp_variables=function_body.getTempVariables(), needs_exception_exit=needs_exception_exit, needs_generator_return=function_body.needsGeneratorReturnExit(), ) function_decl = getCoroutineObjectDeclCode( function_identifier=function_body.getCodeName(), closure_variables=function_body.getClosureVariables(), ) elif function_body.isExpressionAsyncgenObjectBody(): function_code = getAsyncgenObjectCode( context=function_context, function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), user_variables=function_body.getUserLocalVariables(), outline_variables=function_body.getOutlineLocalVariables(), temp_variables=function_body.getTempVariables(), needs_exception_exit=needs_exception_exit, needs_generator_return=function_body.needsGeneratorReturnExit(), ) function_decl = getAsyncgenObjectDeclCode( function_identifier=function_body.getCodeName(), closure_variables=function_body.getClosureVariables(), ) elif function_body.isExpressionClassBody(): function_code = getFunctionCode( context=function_context, function_identifier=function_identifier, parameters=None, closure_variables=function_body.getClosureVariables(), user_variables=function_body.getUserLocalVariables() + function_body.getOutlineLocalVariables(), temp_variables=function_body.getTempVariables(), function_doc=function_body.getDoc(), needs_exception_exit=needs_exception_exit, file_scope=getExportScopeCode(cross_module=False), ) function_decl = getFunctionDirectDecl( function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), file_scope=getExportScopeCode(cross_module=False), context=function_context, ) else: function_code = getFunctionCode( context=function_context, function_identifier=function_identifier, parameters=function_body.getParameters(), closure_variables=function_body.getClosureVariables(), user_variables=function_body.getUserLocalVariables() + function_body.getOutlineLocalVariables(), temp_variables=function_body.getTempVariables(), function_doc=function_body.getDoc(), needs_exception_exit=needs_exception_exit, file_scope=getExportScopeCode( cross_module=function_body.isCrossModuleUsed() ), ) if function_body.needsDirectCall(): function_decl = getFunctionDirectDecl( function_identifier=function_identifier, closure_variables=function_body.getClosureVariables(), file_scope=getExportScopeCode( cross_module=function_body.isCrossModuleUsed() ), context=function_context, ) else: function_decl = None return function_code, function_decl def _generateModuleCode(module, data_filename): # As this not only creates all modules, but also functions, it deals # also with its functions. assert module.isCompiledPythonModule(), module context = Contexts.PythonModuleContext( module=module, data_filename=data_filename, ) context.setExceptionEscape("module_exception_exit") function_decl_codes = [] function_body_codes = [] for function_body in module.getUsedFunctions(): # Constant function returners get no code. ( is_constant_returning, _constant_return_value, ) = function_body.getConstantReturnValue() if is_constant_returning: continue function_code, function_decl = generateFunctionBodyCode( function_body=function_body, context=context ) function_body_codes.append(function_code) if function_decl is not None: function_decl_codes.append(function_decl) # These are for functions used from other modules. Due to cyclic # dependencies, we cannot rely on those to be already created. for function_body in module.getCrossUsedFunctions(): assert function_body.isCrossModuleUsed() function_decl = getFunctionDirectDecl( function_identifier=function_body.getCodeName(), closure_variables=function_body.getClosureVariables(), file_scope=getExportScopeCode( cross_module=function_body.isCrossModuleUsed() ), context=Contexts.PythonFunctionDirectContext( parent=context, function=function_body ), ) function_decl_codes.append(function_decl) return getModuleCode( module=module, function_decl_codes=function_decl_codes, function_body_codes=function_body_codes, module_const_blob_name=encodePythonStringToC( Plugins.deriveModuleConstantsBlobName(data_filename) ), context=context, ) def generateModuleCode(module, data_filename): try: return _generateModuleCode(module=module, data_filename=data_filename) except KeyboardInterrupt: raise KeyboardInterrupt("Interrupted while working on", module) def generateHelpersCode(): calls_decl_code, calls_body_code = getCallsCode() constants_header_code, constants_body_code = getConstantsDefinitionCode() return ( calls_decl_code, calls_body_code, constants_header_code, constants_body_code, ) addExpressionDispatchDict( { "EXPRESSION_ATTRIBUTE_CHECK": generateAttributeCheckCode, "EXPRESSION_ATTRIBUTE_LOOKUP": generateAttributeLookupCode, "EXPRESSION_ATTRIBUTE_LOOKUP_SPECIAL": generateAttributeLookupSpecialCode, "EXPRESSION_BUILTIN_SLICE3": generateBuiltinSlice3Code, "EXPRESSION_BUILTIN_SLICE2": generateBuiltinSlice2Code, "EXPRESSION_BUILTIN_SLICE1": generateBuiltinSlice1Code, "EXPRESSION_BUILTIN_HASH": generateBuiltinHashCode, "EXPRESSION_BUILTIN_ID": generateBuiltinIdCode, "EXPRESSION_BUILTIN_COMPILE": generateBuiltinCompileCode, "EXPRESSION_BUILTIN_EXECFILE": generateExecfileCode, "EXPRESSION_BUILTIN_EVAL": generateEvalCode, "EXPRESSION_BUILTIN_EXEC": generateEvalCode, "EXPRESSION_BUILTIN_ITER_FOR_UNPACK": generateBuiltinIterForUnpackCode, "EXPRESSION_BUILTIN_ITER1": generateBuiltinIter1Code, "EXPRESSION_BUILTIN_ITER2": generateBuiltinIter2Code, "EXPRESSION_BUILTIN_NEXT1": generateBuiltinNext1Code, "EXPRESSION_BUILTIN_NEXT2": generateBuiltinNext2Code, "EXPRESSION_BUILTIN_SUM1": generateBuiltinSum1Code, "EXPRESSION_BUILTIN_SUM2": generateBuiltinSum2Code, "EXPRESSION_BUILTIN_TYPE1": generateBuiltinType1Code, "EXPRESSION_BUILTIN_TYPE3": generateBuiltinType3Code, "EXPRESSION_BUILTIN_IMPORT": generateBuiltinImportCode, "EXPRESSION_BUILTIN_BOOL": generateBuiltinBoolCode, "EXPRESSION_BUILTIN_BYTEARRAY1": generateBuiltinBytearray1Code, "EXPRESSION_BUILTIN_BYTEARRAY3": generateBuiltinBytearray3Code, "EXPRESSION_BUILTIN_INT1": generateBuiltinInt1Code, "EXPRESSION_BUILTIN_INT2": generateBuiltinInt2Code, "EXPRESSION_BUILTIN_LONG1": generateBuiltinLong1Code, "EXPRESSION_BUILTIN_LONG2": generateBuiltinLong2Code, "EXPRESSION_BUILTIN_FLOAT": generateBuiltinFloatCode, "EXPRESSION_BUILTIN_COMPLEX1": generateBuiltinComplex1Code, "EXPRESSION_BUILTIN_COMPLEX2": generateBuiltinComplex2Code, "EXPRESSION_BUILTIN_LEN": generateBuiltinLenCode, "EXPRESSION_BUILTIN_STR_P2": generateBuiltinStrCode, "EXPRESSION_BUILTIN_STR_P3": generateBuiltinStrCode, "EXPRESSION_BUILTIN_BYTES1": generateBuiltinBytes1Code, "EXPRESSION_BUILTIN_BYTES3": generateBuiltinBytes3Code, "EXPRESSION_BUILTIN_UNICODE_P2": generateBuiltinUnicodeCode, "EXPRESSION_BUILTIN_CHR": generateBuiltinChrCode, "EXPRESSION_BUILTIN_ORD": generateBuiltinOrdCode, "EXPRESSION_BUILTIN_BIN": generateBuiltinBinCode, "EXPRESSION_BUILTIN_OCT": generateBuiltinOctCode, "EXPRESSION_BUILTIN_HEX": generateBuiltinHexCode, "EXPRESSION_BUILTIN_TUPLE": generateBuiltinTupleCode, "EXPRESSION_BUILTIN_LIST": generateBuiltinListCode, "EXPRESSION_BUILTIN_SET": generateBuiltinSetCode, "EXPRESSION_BUILTIN_ANY": generateBuiltinAnyCode, "EXPRESSION_BUILTIN_FROZENSET": generateBuiltinFrozensetCode, "EXPRESSION_BUILTIN_ALL": generateBuiltinAllCode, "EXPRESSION_BUILTIN_DICT": generateBuiltinDictCode, "EXPRESSION_BUILTIN_LOCALS_COPY": generateBuiltinLocalsCode, "EXPRESSION_BUILTIN_LOCALS_UPDATED": generateBuiltinLocalsCode, "EXPRESSION_BUILTIN_LOCALS_REF": generateBuiltinLocalsRefCode, "EXPRESSION_BUILTIN_GLOBALS": generateBuiltinGlobalsCode, "EXPRESSION_BUILTIN_SUPER0": generateBuiltinSuperCode, "EXPRESSION_BUILTIN_SUPER2": generateBuiltinSuperCode, "EXPRESSION_BUILTIN_ISINSTANCE": generateBuiltinIsinstanceCode, "EXPRESSION_BUILTIN_ISSUBCLASS": generateBuiltinIssubclassCode, "EXPRESSION_TYPE_CHECK": generateTypeCheckCode, "EXPRESSION_MATCH_TYPE_CHECK_SEQUENCE": generateMatchTypeCheckSequenceCode, "EXPRESSION_MATCH_TYPE_CHECK_MAPPING": generateMatchTypeCheckMappingCode, "EXPRESSION_BUILTIN_DIR1": generateBuiltinDir1Code, "EXPRESSION_BUILTIN_VARS": generateBuiltinVarsCode, "EXPRESSION_BUILTIN_HASATTR": generateBuiltinHasattrCode, "EXPRESSION_BUILTIN_GETATTR": generateBuiltinGetattrCode, "EXPRESSION_BUILTIN_SETATTR": generateBuiltinSetattrCode, "EXPRESSION_BUILTIN_OPEN": generateBuiltinOpenCode, "EXPRESSION_BUILTIN_STATICMETHOD": generateBuiltinStaticmethodCode, "EXPRESSION_BUILTIN_CLASSMETHOD": generateBuiltinClassmethodCode, "EXPRESSION_BUILTIN_RANGE1": generateBuiltinRange1Code, "EXPRESSION_BUILTIN_RANGE2": generateBuiltinRange2Code, "EXPRESSION_BUILTIN_RANGE3": generateBuiltinRange3Code, "EXPRESSION_BUILTIN_XRANGE1": generateBuiltinXrange1Code, "EXPRESSION_BUILTIN_XRANGE2": generateBuiltinXrange2Code, "EXPRESSION_BUILTIN_XRANGE3": generateBuiltinXrange3Code, "EXPRESSION_BUILTIN_MAKE_EXCEPTION": generateBuiltinMakeExceptionCode, "EXPRESSION_BUILTIN_MAKE_EXCEPTION_IMPORT_ERROR": generateBuiltinMakeExceptionCode, "EXPRESSION_BUILTIN_REF": generateBuiltinRefCode, "EXPRESSION_BUILTIN_WITH_CONTEXT_REF": generateBuiltinRefCode, "EXPRESSION_BUILTIN_EXCEPTION_REF": generateExceptionRefCode, "EXPRESSION_BUILTIN_ANONYMOUS_REF": generateBuiltinAnonymousRefCode, "EXPRESSION_CAUGHT_EXCEPTION_TYPE_REF": generateExceptionCaughtTypeCode, "EXPRESSION_CAUGHT_EXCEPTION_VALUE_REF": generateExceptionCaughtValueCode, "EXPRESSION_CAUGHT_EXCEPTION_TRACEBACK_REF": generateExceptionCaughtTracebackCode, "EXPRESSION_CALL_EMPTY": generateCallCode, "EXPRESSION_CALL_KEYWORDS_ONLY": generateCallCode, "EXPRESSION_CALL_NO_KEYWORDS": generateCallCode, "EXPRESSION_CALL": generateCallCode, "EXPRESSION_CONSTANT_NONE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TRUE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_FALSE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_STR_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_STR_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_UNICODE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_UNICODE_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_BYTES_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_BYTES_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_INT_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_LONG_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_FLOAT_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_COMPLEX_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_ELLIPSIS_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_DICT_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_DICT_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TUPLE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TUPLE_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TUPLE_MUTABLE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_LIST_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_LIST_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_SET_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_SET_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_FROZENSET_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_FROZENSET_EMPTY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_SLICE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_XRANGE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TYPE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_TYPE_SUBSCRIPTABLE_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_BYTEARRAY_REF": generateConstantReferenceCode, "EXPRESSION_CONSTANT_GENERIC_ALIAS": generateConstantGenericAliasCode, "EXPRESSION_CONSTANT_UNION_TYPE": generateConstantReferenceCode, "EXPRESSION_CONSTANT_SYS_VERSION_INFO_REF": generateConstantSysVersionInfoCode, "EXPRESSION_CONDITIONAL": generateConditionalCode, "EXPRESSION_CONDITIONAL_OR": generateConditionalAndOrCode, "EXPRESSION_CONDITIONAL_AND": generateConditionalAndOrCode, "EXPRESSION_COMPARISON": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_IS": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_IS_NOT": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_IN": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_NOT_IN": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_EXCEPTION_MATCH": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_EXCEPTION_MISMATCH": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_LT": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_LTE": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_GT": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_GTE": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_EQ": generateComparisonExpressionCode, "EXPRESSION_COMPARISON_NEQ": generateComparisonExpressionCode, "EXPRESSION_DICT_OPERATION_ITEM": generateDictOperationItemCode, "EXPRESSION_DICT_OPERATION_GET2": generateDictOperationGet2Code, "EXPRESSION_DICT_OPERATION_GET3": generateDictOperationGet3Code, "EXPRESSION_DICT_OPERATION_HASKEY": generateDictOperationInCode, "EXPRESSION_DICT_OPERATION_IN": generateDictOperationInCode, "EXPRESSION_DICT_OPERATION_NOT_IN": generateDictOperationInCode, "EXPRESSION_DICT_OPERATION_COPY": generateDictOperationCopyCode, "EXPRESSION_DICT_OPERATION_CLEAR": generateDictOperationClearCode, "EXPRESSION_DICT_OPERATION_ITEMS": generateDictOperationItemsCode, "EXPRESSION_DICT_OPERATION_ITERITEMS": generateDictOperationIteritemsCode, "EXPRESSION_DICT_OPERATION_VIEWITEMS": generateDictOperationViewitemsCode, "EXPRESSION_DICT_OPERATION_KEYS": generateDictOperationKeysCode, "EXPRESSION_DICT_OPERATION_ITERKEYS": generateDictOperationIterkeysCode, "EXPRESSION_DICT_OPERATION_VIEWKEYS": generateDictOperationViewkeysCode, "EXPRESSION_DICT_OPERATION_VALUES": generateDictOperationValuesCode, "EXPRESSION_DICT_OPERATION_ITERVALUES": generateDictOperationItervaluesCode, "EXPRESSION_DICT_OPERATION_VIEWVALUES": generateDictOperationViewvaluesCode, "EXPRESSION_DICT_OPERATION_SETDEFAULT2": generateDictOperationSetdefault2Code, "EXPRESSION_DICT_OPERATION_SETDEFAULT3": generateDictOperationSetdefault3Code, "EXPRESSION_DICT_OPERATION_POP2": generateDictOperationPop2Code, "EXPRESSION_DICT_OPERATION_POP3": generateDictOperationPop3Code, "EXPRESSION_DICT_OPERATION_UPDATE2": generateDictOperationUpdate2Code, "EXPRESSION_DICT_OPERATION_UPDATE3": generateDictOperationUpdate3Code, "EXPRESSION_FUNCTION_CREATION": generateFunctionCreationCode, "EXPRESSION_FUNCTION_CALL": generateFunctionCallCode, "EXPRESSION_FUNCTION_ERROR_STR": generateFunctionErrorStrCode, "EXPRESSION_IMPORT_MODULE_FIXED": generateImportModuleFixedCode, "EXPRESSION_IMPORT_MODULE_HARD": generateImportModuleHardCode, "EXPRESSION_IMPORT_MODULE_NAME_HARD": generateImportModuleNameHardCode, "EXPRESSION_IMPORTLIB_IMPORT_MODULE_REF": generateImportModuleNameHardCode, "EXPRESSION_IMPORTLIB_IMPORT_MODULE_CALL": generateImportlibImportCallCode, "EXPRESSION_IMPORT_NAME": generateImportNameCode, "EXPRESSION_LIST_OPERATION_EXTEND": generateListOperationExtendCode, "EXPRESSION_LIST_OPERATION_EXTEND_FOR_UNPACK": generateListOperationExtendCode, "EXPRESSION_LIST_OPERATION_POP": generateListOperationPopCode, "EXPRESSION_MODULE_ATTRIBUTE_FILE_REF": generateModuleAttributeFileCode, "EXPRESSION_MODULE_ATTRIBUTE_NAME_REF": generateModuleAttributeCode, "EXPRESSION_MODULE_ATTRIBUTE_PACKAGE_REF": generateModuleAttributeCode, "EXPRESSION_MODULE_ATTRIBUTE_LOADER_REF": generateModuleAttributeCode, "EXPRESSION_MODULE_ATTRIBUTE_SPEC_REF": generateModuleAttributeCode, "EXPRESSION_MAKE_GENERATOR_OBJECT": generateMakeGeneratorObjectCode, "EXPRESSION_MAKE_COROUTINE_OBJECT": generateMakeCoroutineObjectCode, "EXPRESSION_MAKE_ASYNCGEN_OBJECT": generateMakeAsyncgenObjectCode, "EXPRESSION_MAKE_SET": generateSetCreationCode, "EXPRESSION_MAKE_SET_LITERAL": generateSetLiteralCreationCode, "EXPRESSION_MAKE_TUPLE": generateTupleCreationCode, "EXPRESSION_MAKE_LIST": generateListCreationCode, "EXPRESSION_MAKE_DICT": generateDictionaryCreationCode, "EXPRESSION_OPERATION_BINARY_ADD": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_SUB": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_MULT": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_FLOOR_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_OLD_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_TRUE_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_DIVMOD": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_MOD": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_POW": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_LSHIFT": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_RSHIFT": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_BIT_OR": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_BIT_AND": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_BIT_XOR": generateOperationBinaryCode, "EXPRESSION_OPERATION_BINARY_MAT_MULT": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_ADD": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_SUB": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_MULT": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_FLOOR_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_OLD_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_TRUE_DIV": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_MOD": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_POW": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_LSHIFT": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_RSHIFT": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_BIT_OR": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_BIT_AND": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_BIT_XOR": generateOperationBinaryCode, "EXPRESSION_OPERATION_INPLACE_MAT_MULT": generateOperationBinaryCode, "EXPRESSION_OPERATION_UNARY_REPR": generateOperationUnaryCode, "EXPRESSION_OPERATION_UNARY_SUB": generateOperationUnaryCode, "EXPRESSION_OPERATION_UNARY_ADD": generateOperationUnaryCode, "EXPRESSION_OPERATION_UNARY_INVERT": generateOperationUnaryCode, "EXPRESSION_OPERATION_UNARY_ABS": generateBuiltinAbsCode, "EXPRESSION_OPERATION_NOT": generateOperationNotCode, "EXPRESSION_OUTLINE_BODY": generateFunctionOutlineCode, "EXPRESSION_OUTLINE_FUNCTION": generateFunctionOutlineCode, # TODO: Rename to make more clear it is an outline "EXPRESSION_CLASS_BODY": generateFunctionOutlineCode, "EXPRESSION_SUBSCRIPT_LOOKUP": generateSubscriptLookupCode, "EXPRESSION_SUBSCRIPT_CHECK": generateSubscriptCheckCode, "EXPRESSION_SLICE_LOOKUP": generateSliceLookupCode, "EXPRESSION_SET_OPERATION_UPDATE": generateSetOperationUpdateCode, "EXPRESSION_SIDE_EFFECTS": generateSideEffectsCode, "EXPRESSION_SPECIAL_UNPACK": generateSpecialUnpackCode, "EXPRESSION_TEMP_VARIABLE_REF": generateVariableReferenceCode, "EXPRESSION_VARIABLE_REF": generateVariableReferenceCode, "EXPRESSION_VARIABLE_OR_BUILTIN_REF": generateVariableReferenceCode, "EXPRESSION_YIELD": generateYieldCode, "EXPRESSION_YIELD_FROM": generateYieldFromCode, "EXPRESSION_YIELD_FROM_WAITABLE": generateYieldFromWaitableCode, "EXPRESSION_ASYNC_WAIT": generateAsyncWaitCode, "EXPRESSION_ASYNC_WAIT_ENTER": generateAsyncWaitCode, "EXPRESSION_ASYNC_WAIT_EXIT": generateAsyncWaitCode, "EXPRESSION_ASYNC_ITER": generateAsyncIterCode, "EXPRESSION_ASYNC_NEXT": generateAsyncNextCode, "EXPRESSION_SELECT_METACLASS": generateSelectMetaclassCode, "EXPRESSION_STRING_CONCATENATION": generateStringContenationCode, "EXPRESSION_BUILTIN_FORMAT": generateBuiltinFormatCode, "EXPRESSION_BUILTIN_ASCII": generateBuiltinAsciiCode, "EXPRESSION_LOCALS_VARIABLE_CHECK": generateLocalsDictVariableCheckCode, "EXPRESSION_LOCALS_VARIABLE_REF_OR_FALLBACK": generateLocalsDictVariableRefOrFallbackCode, "EXPRESSION_LOCALS_VARIABLE_REF": generateLocalsDictVariableRefCode, "EXPRESSION_RAISE_EXCEPTION": generateRaiseExpressionCode, "EXPRESSION_NUITKA_LOADER_CREATION": generateNuitkaLoaderCreationCode, } ) # Add code generation for the EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_* variety addExpressionDispatchDict( dict((cls.kind, generateAttributeLookupCode) for cls in attribute_classes.values()) ) # Add code generation for the EXPRESSION_ATTRIBUTE_LOOKUP_DICT|LIST|STR_* variety addExpressionDispatchDict( dict((cls.kind, generateAttributeLookupCode) for cls in attribute_typed_classes) ) addExpressionDispatchDict( dict((cls.kind, generateStrOperationCode) for cls in getStrOperationClasses()) ) setStatementDispatchDict( { "STATEMENT_ASSIGNMENT_VARIABLE": generateAssignmentVariableCode, "STATEMENT_ASSIGNMENT_ATTRIBUTE": generateAssignmentAttributeCode, "STATEMENT_ASSIGNMENT_SUBSCRIPT": generateAssignmentSubscriptCode, "STATEMENT_ASSIGNMENT_SLICE": generateAssignmentSliceCode, "STATEMENT_DEL_VARIABLE": generateDelVariableCode, "STATEMENT_DEL_ATTRIBUTE": generateDelAttributeCode, "STATEMENT_DEL_SUBSCRIPT": generateDelSubscriptCode, "STATEMENT_DEL_SLICE": generateDelSliceCode, "STATEMENT_DICT_OPERATION_REMOVE": generateDictOperationRemoveCode, "STATEMENT_DICT_OPERATION_UPDATE": generateDictOperationUpdateCode, "STATEMENT_RELEASE_VARIABLE": generateVariableReleaseCode, "STATEMENT_EXPRESSION_ONLY": generateExpressionOnlyCode, "STATEMENT_RETURN": generateReturnCode, "STATEMENT_RETURN_TRUE": generateReturnConstantCode, "STATEMENT_RETURN_FALSE": generateReturnConstantCode, "STATEMENT_RETURN_NONE": generateReturnConstantCode, "STATEMENT_RETURN_CONSTANT": generateReturnConstantCode, "STATEMENT_RETURN_RETURNED_VALUE": generateReturnedValueCode, "STATEMENT_GENERATOR_RETURN": generateGeneratorReturnValueCode, "STATEMENT_GENERATOR_RETURN_NONE": generateGeneratorReturnNoneCode, "STATEMENT_CONDITIONAL": generateBranchCode, "STATEMENT_TRY": generateTryCode, "STATEMENT_PRINT_VALUE": generatePrintValueCode, "STATEMENT_PRINT_NEWLINE": generatePrintNewlineCode, "STATEMENT_IMPORT_STAR": generateImportStarCode, "STATEMENT_LIST_OPERATION_APPEND": generateListOperationAppendCode, "STATEMENT_SET_OPERATION_ADD": generateSetOperationAddCode, "STATEMENT_DICT_OPERATION_SET": generateDictOperationSetCode, "STATEMENT_DICT_OPERATION_SET_KEY_VALUE": generateDictOperationSetCodeKeyValue, "STATEMENT_LOCALS_DICT_OPERATION_SET": generateLocalsDictSetCode, "STATEMENT_LOCALS_DICT_OPERATION_DEL": generateLocalsDictDelCode, "STATEMENT_LOOP": generateLoopCode, "STATEMENT_LOOP_BREAK": generateLoopBreakCode, "STATEMENT_LOOP_CONTINUE": generateLoopContinueCode, "STATEMENT_RAISE_EXCEPTION": generateRaiseCode, "STATEMENT_RAISE_EXCEPTION_IMPLICIT": generateRaiseCode, "STATEMENT_RERAISE_EXCEPTION": generateReraiseCode, "STATEMENT_SPECIAL_UNPACK_CHECK": generateUnpackCheckCode, "STATEMENT_EXEC": generateExecCode, "STATEMENT_LOCALS_DICT_SYNC": generateLocalsDictSyncCode, "STATEMENT_SET_LOCALS": generateSetLocalsDictCode, "STATEMENT_SET_LOCALS_DICTIONARY": generateSetLocalsDictCode, "STATEMENT_RELEASE_LOCALS": generateReleaseLocalsDictCode, "STATEMENT_PRESERVE_FRAME_EXCEPTION": generateFramePreserveExceptionCode, "STATEMENT_RESTORE_FRAME_EXCEPTION": generateFrameRestoreExceptionCode, "STATEMENT_PUBLISH_EXCEPTION": generateExceptionPublishCode, } ) Nuitka-0.6.19.1/nuitka/codegen/LineNumberCodes.py0000600000372100037210000000476614166627112026573 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Generate code that updates the source code line. """ def getCurrentLineNumberCode(context): frame_handle = context.getFrameHandle() if frame_handle is None: return "" else: source_ref = context.getCurrentSourceCodeReference() if source_ref.isInternal(): return "" else: return str(source_ref.getLineNumber()) def getLineNumberUpdateCode(context): lineno_value = getCurrentLineNumberCode(context) if lineno_value: frame_handle = context.getFrameHandle() return "%s->m_frame.f_lineno = %s;" % (frame_handle, lineno_value) else: return "" def getErrorLineNumberUpdateCode(context): ( _exception_type, _exception_value, _exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() lineno_value = getCurrentLineNumberCode(context) if lineno_value: return "%s = %s;" % (exception_lineno, lineno_value) else: return "" def emitErrorLineNumberUpdateCode(emit, context): update_code = getErrorLineNumberUpdateCode(context) if update_code: emit(update_code) def emitLineNumberUpdateCode(expression, emit, context): context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) code = getLineNumberUpdateCode(context) if code: emit(code) def getSetLineNumberCodeRaw(to_name, emit, context): assert context.getFrameHandle() is not None emit("%s->m_frame.f_lineno = %s;" % (context.getFrameHandle(), to_name)) def getLineNumberCode(to_name, emit, context): assert context.getFrameHandle() is not None emit("%s = %s->m_frame.f_lineno;" % (to_name, context.getFrameHandle())) Nuitka-0.6.19.1/nuitka/codegen/Indentation.py0000600000372100037210000000256414166627112026023 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Indentation of code. Language independent, the amount of the spaces is not configurable, as it needs to be the same as in templates. """ def _indentedCode(codes, count): return "\n".join( " " * count + line if (line and not line.startswith("#")) else line for line in codes ) def indented(codes, level=1, vert_block=False): if type(codes) is str: codes = codes.split("\n") if vert_block and codes != [""]: codes.insert(0, "") codes.append("") return _indentedCode(codes, level * 4) def getCommentCode(comment, emit): emit("// " + comment) Nuitka-0.6.19.1/nuitka/codegen/IntegerCodes.py0000600000372100037210000000655014166627112026121 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Integer related codes, long and int. """ from nuitka.PythonVersions import python_version from .CodeHelpers import ( decideConversionCheckNeeded, generateChildExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitCode from .PythonAPICodes import generateCAPIObjectCode def generateBuiltinLong1Code(to_name, expression, emit, context): assert python_version < 0x300 # TODO: Have dedicated helper that inlines. generateCAPIObjectCode( to_name=to_name, capi="PyNumber_Long", arg_desc=(("long_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinLong2Code(to_name, expression, emit, context): assert python_version < 0x300 value_name, base_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "long_value", expression, emit, context ) as result_name: emit("%s = BUILTIN_LONG2(%s, %s);" % (result_name, value_name, base_name)) getErrorExitCode( check_name=result_name, release_names=(value_name, base_name), emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateBuiltinInt1Code(to_name, expression, emit, context): # TODO: Have dedicated helper that inlines. generateCAPIObjectCode( to_name=to_name, capi="PyNumber_Int", arg_desc=(("int_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinInt2Code(to_name, expression, emit, context): value_name, base_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "int_value", expression, emit, context ) as result_name: emit("%s = BUILTIN_INT2(%s, %s);" % (result_name, value_name, base_name)) getErrorExitCode( check_name=result_name, release_names=(value_name, base_name), emit=emit, context=context, ) context.addCleanupTempName(result_name) Nuitka-0.6.19.1/nuitka/codegen/ConditionalCodes.py0000600000372100037210000001624714166627112026773 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Conditional statements related codes. Branches, conditions, truth checks. """ from .CodeHelpers import decideConversionCheckNeeded, generateExpressionCode from .Emission import SourceCodeCollector from .ErrorCodes import ( getErrorExitBoolCode, getReleaseCode, getTakeReferenceCode, ) from .LabelCodes import getBranchingCode, getGotoCode, getLabelCode def generateConditionCode(condition, emit, context): if condition.mayRaiseExceptionBool(BaseException): compare_name = context.allocateTempName("condition_result", "nuitka_bool") else: compare_name = context.allocateTempName("condition_result", "bool") generateExpressionCode( to_name=compare_name, expression=condition, emit=emit, context=context ) getBranchingCode( condition=compare_name.getCType().getTruthCheckCode(compare_name), emit=emit, context=context, ) getReleaseCode(compare_name, emit, context) def generateConditionalAndOrCode(to_name, expression, emit, context): # This is a complex beast, handling both "or" and "and" expressions, # and it needs to micro manage details. # pylint: disable=too-many-locals if expression.isExpressionConditionalOr(): prefix = "or_" else: prefix = "and_" true_target = context.allocateLabel(prefix + "left") false_target = context.allocateLabel(prefix + "right") end_target = context.allocateLabel(prefix + "end") old_true_target = context.getTrueBranchTarget() old_false_target = context.getFalseBranchTarget() truth_name = context.allocateTempName(prefix + "left_truth", "int") left_name = context.allocateTempName(prefix + "left_value", to_name.c_type) right_name = context.allocateTempName(prefix + "right_value", to_name.c_type) left_value = expression.subnode_left generateExpressionCode( to_name=left_name, expression=left_value, emit=emit, context=context ) # We need to treat this mostly manually here. We remember to release # this, and we better do this manually later. needs_ref1 = context.needsCleanup(left_name) if expression.isExpressionConditionalOr(): context.setTrueBranchTarget(true_target) context.setFalseBranchTarget(false_target) else: context.setTrueBranchTarget(false_target) context.setFalseBranchTarget(true_target) left_name.getCType().emitTruthCheckCode( to_name=truth_name, value_name=left_name, emit=emit, ) needs_check = left_value.mayRaiseExceptionBool(BaseException) if needs_check: getErrorExitBoolCode( condition="%s == -1" % truth_name, needs_check=True, emit=emit, context=context, ) getBranchingCode(condition="%s == 1" % truth_name, emit=emit, context=context) getLabelCode(false_target, emit) # So it's not the left value, then lets release that one right away, it # is not needed, but we remember if it should be added above. getReleaseCode(release_name=left_name, emit=emit, context=context) right_value = expression.subnode_right # Evaluate the "right" value then. generateExpressionCode( to_name=right_name, expression=right_value, emit=emit, context=context ) # Again, remember the reference count to manage it manually. needs_ref2 = context.needsCleanup(right_name) if needs_ref2: context.removeCleanupTempName(right_name) if not needs_ref2 and needs_ref1: getTakeReferenceCode(right_name, emit) to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=right_name, needs_check=decideConversionCheckNeeded(to_name, right_value), emit=emit, context=context, ) getGotoCode(end_target, emit) getLabelCode(true_target, emit) if not needs_ref1 and needs_ref2: getTakeReferenceCode(left_name, emit) to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=left_name, needs_check=decideConversionCheckNeeded(to_name, left_value), emit=emit, context=context, ) getLabelCode(end_target, emit) if needs_ref1 or needs_ref2: context.addCleanupTempName(to_name) context.setTrueBranchTarget(old_true_target) context.setFalseBranchTarget(old_false_target) def generateConditionalCode(to_name, expression, emit, context): true_target = context.allocateLabel("condexpr_true") false_target = context.allocateLabel("condexpr_false") end_target = context.allocateLabel("condexpr_end") old_true_target = context.getTrueBranchTarget() old_false_target = context.getFalseBranchTarget() context.setTrueBranchTarget(true_target) context.setFalseBranchTarget(false_target) generateConditionCode( condition=expression.subnode_condition, emit=emit, context=context ) getLabelCode(true_target, emit) generateExpressionCode( to_name=to_name, expression=expression.subnode_expression_yes, emit=emit, context=context, ) needs_ref1 = context.needsCleanup(to_name) # Must not clean this up in other expression. if needs_ref1: context.removeCleanupTempName(to_name) real_emit = emit emit = SourceCodeCollector() generateExpressionCode( to_name=to_name, expression=expression.subnode_expression_no, emit=emit, context=context, ) needs_ref2 = context.needsCleanup(to_name) # TODO: Need to buffer generated code, so we can emit extra reference if # not same. if needs_ref1 and not needs_ref2: getGotoCode(end_target, real_emit) getLabelCode(false_target, real_emit) for line in emit.codes: real_emit(line) emit = real_emit getTakeReferenceCode(to_name, emit) context.addCleanupTempName(to_name) elif not needs_ref1 and needs_ref2: getTakeReferenceCode(to_name, real_emit) getGotoCode(end_target, real_emit) getLabelCode(false_target, real_emit) for line in emit.codes: real_emit(line) emit = real_emit else: getGotoCode(end_target, real_emit) getLabelCode(false_target, real_emit) for line in emit.codes: real_emit(line) emit = real_emit getLabelCode(end_target, emit) context.setTrueBranchTarget(old_true_target) context.setFalseBranchTarget(old_false_target) Nuitka-0.6.19.1/nuitka/codegen/OperationCodes.py0000600000372100037210000001366514166627112026471 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Codes for operations. There are unary and binary operations. Many of them have specializations and of course types could play into it. Then there is also the added difficulty of in-place assignments, which have other operation variants. """ from . import HelperDefinitions, OperatorCodes from .CodeHelpers import ( generateChildExpressionsCode, pickCodeHelper, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import ( getErrorExitBoolCode, getErrorExitCode, getTakeReferenceCode, ) def generateOperationBinaryCode(to_name, expression, emit, context): left_arg_name, right_arg_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) # TODO: Decide and use one single spelling, inplace or in_place inplace = expression.isInplaceSuspect() _getBinaryOperationCode( to_name=to_name, expression=expression, operator=expression.getOperator(), arg_names=(left_arg_name, right_arg_name), in_place=inplace, emit=emit, context=context, ) def generateOperationNotCode(to_name, expression, emit, context): (arg_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getIntResName() emit("%s = CHECK_IF_TRUE(%s);" % (res_name, arg_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_name=arg_name, needs_check=expression.subnode_operand.mayRaiseExceptionBool(BaseException), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s == 0" % res_name, emit=emit ) def generateOperationUnaryCode(to_name, expression, emit, context): (arg_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) _getUnaryOperationCode( to_name=to_name, expression=expression, operator=expression.getOperator(), arg_name=arg_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) def _getBinaryOperationCode( to_name, expression, operator, arg_names, in_place, emit, context ): left = expression.subnode_left ref_count = 1 needs_check = expression.mayRaiseExceptionOperation() helper = pickCodeHelper( prefix="BINARY_OPERATION_%s" % HelperDefinitions.getCodeNameForOperation(operator), suffix="INPLACE" if operator[0] == "I" else "", target_type=None if operator[0] == "I" else to_name.getCType(), left_shape=left.getTypeShape(), right_shape=expression.subnode_right.getTypeShape(), helpers=HelperDefinitions.getSpecializedOperations(operator), nonhelpers=HelperDefinitions.getNonSpecializedOperations(operator), source_ref=expression.source_ref, ) # We must assume to write to a variable is "in_place" is active, not e.g. # a constant reference. That was asserted before calling us. if in_place or "INPLACE" in helper.helper_name: res_name = context.getBoolResName() # For module variable C type to reference later. if left.isExpressionVariableRef() and left.getVariable().isModuleVariable(): emit("%s = %s;" % (context.getInplaceLeftName(), arg_names[0])) if ( not left.isExpressionVariableRef() and not left.isExpressionTempVariableRef() ): if not context.needsCleanup(arg_names[0]): getTakeReferenceCode(arg_names[0], emit) emit("%s = %s(&%s, %s);" % (res_name, helper, arg_names[0], arg_names[1])) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=arg_names, needs_check=needs_check, emit=emit, context=context, ) emit("%s = %s;" % (to_name, arg_names[0])) if ( not left.isExpressionVariableRef() and not left.isExpressionTempVariableRef() ): context.addCleanupTempName(to_name) else: helper.emitHelperCall( to_name=to_name, arg_names=arg_names, ref_count=ref_count, needs_check=needs_check, emit=emit, context=context, ) def _getUnaryOperationCode( to_name, expression, operator, arg_name, needs_check, emit, context ): impl_helper, ref_count = OperatorCodes.unary_operator_codes[operator] helper = "UNARY_OPERATION" prefix_args = (impl_helper,) with withObjectCodeTemporaryAssignment( to_name, "op_%s_res" % operator.lower(), expression, emit, context ) as value_name: emit( "%s = %s(%s);" % ( value_name, helper, ", ".join(str(arg_name) for arg_name in prefix_args + (arg_name,)), ) ) getErrorExitCode( check_name=value_name, release_name=arg_name, needs_check=needs_check, emit=emit, context=context, ) if ref_count: context.addCleanupTempName(value_name) Nuitka-0.6.19.1/nuitka/codegen/PythonAPICodes.py0000600000372100037210000001246114166627112026335 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for standard CPython/API calls. This is generic stuff, geared at calling functions that accept Python objects and return Python objects. As these all work in a similar way, it makes sense to concentrate the best way to do to make those calls here. Also, many Nuitka helper codes turn out to be very similar to Python C/API and then can use the same code. """ from .CodeHelpers import generateExpressionCode from .ErrorCodes import ( getErrorExitBoolCode, getErrorExitCode, getReleaseCode, getReleaseCodes, ) def makeArgDescFromExpression(expression): """Helper for providing arg_desc consistently for generateCAPIObject methods.""" return tuple( (child_name + "_value", child_value) for child_name, child_value in expression.getVisitableNodesNamed() ) def generateCAPIObjectCodeCommon( to_name, capi, arg_desc, may_raise, conversion_check, ref_count, source_ref, emit, context, none_null=False, ): arg_names = [] for arg_name, arg_expression in arg_desc: if arg_expression is None and none_null: arg_names.append("NULL") else: arg_name = context.allocateTempName(arg_name) generateExpressionCode( to_name=arg_name, expression=arg_expression, emit=emit, context=context ) arg_names.append(arg_name) context.setCurrentSourceCodeReference(source_ref) getCAPIObjectCode( to_name=to_name, capi=capi, arg_names=arg_names, may_raise=may_raise, conversion_check=conversion_check, ref_count=ref_count, emit=emit, context=context, ) def generateCAPIObjectCode( to_name, capi, arg_desc, may_raise, conversion_check, source_ref, emit, context, none_null=False, ): generateCAPIObjectCodeCommon( to_name=to_name, capi=capi, arg_desc=arg_desc, may_raise=may_raise, conversion_check=conversion_check, ref_count=1, source_ref=source_ref, emit=emit, context=context, none_null=none_null, ) def generateCAPIObjectCode0( to_name, capi, arg_desc, may_raise, conversion_check, source_ref, emit, context, none_null=False, ): generateCAPIObjectCodeCommon( to_name=to_name, capi=capi, arg_desc=arg_desc, may_raise=may_raise, conversion_check=conversion_check, ref_count=0, source_ref=source_ref, emit=emit, context=context, none_null=none_null, ) def getCAPIObjectCode( to_name, capi, arg_names, may_raise, conversion_check, ref_count, emit, context ): release_names = tuple(arg_name for arg_name in arg_names if arg_name != "NULL") if to_name is not None: # TODO: Use context manager here too. if to_name.c_type == "PyObject *": value_name = to_name else: value_name = context.allocateTempName("capi_result") emit( "%s = %s(%s);" % (value_name, capi, ", ".join(str(arg_name) for arg_name in arg_names)) ) getErrorExitCode( check_name=value_name, release_names=release_names, needs_check=may_raise, emit=emit, context=context, ) if ref_count: context.addCleanupTempName(value_name) if to_name is not value_name: to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=conversion_check, emit=emit, context=context, ) if ref_count: getReleaseCode(value_name, emit, context) else: if may_raise: res_name = context.getIntResName() emit( "%s = %s(%s);" % (res_name, capi, ", ".join(str(arg_name) for arg_name in arg_names)) ) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=release_names, emit=emit, context=context, ) else: emit("%s(%s);" % (capi, ", ".join(str(arg_name) for arg_name in arg_names))) getReleaseCodes(release_names, emit, context) assert not ref_count def getReferenceExportCode(base_name, emit, context): if not context.needsCleanup(base_name): emit("Py_INCREF(%s);" % base_name) Nuitka-0.6.19.1/nuitka/codegen/EvalCodes.py0000600000372100037210000002775414166627112025424 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Eval/exec/execfile/compile built-in related codes. """ from nuitka import Options from nuitka.PythonVersions import python_version from .CodeHelpers import ( generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCode from .PythonAPICodes import getReferenceExportCode from .VariableCodes import getVariableAssignmentCode def _getStoreLocalsCode(locals_name, variable_traces, is_dict, emit, context): for variable, variable_trace in sorted( variable_traces, key=lambda x: x[0].getName() ): if not variable.isModuleVariable(): key_name = context.getConstantCode(constant=variable.getName()) value_name = context.allocateTempName("locals_value", unique=True) if is_dict: emit( "%s = DICT_GET_ITEM0(%s, %s);" % (value_name, locals_name, key_name) ) else: emit( "%s = PyObject_GetItem(%s, %s);" % (value_name, locals_name, key_name) ) getErrorExitBoolCode( condition="""\ %s == NULL && !EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_KeyError)""" % value_name, emit=emit, context=context, ) emit("CLEAR_ERROR_OCCURRED();") context.addCleanupTempName(value_name) emit("if (%s != NULL)" % value_name) emit("{") getVariableAssignmentCode( variable=variable, variable_trace=variable_trace, tmp_name=value_name, needs_release=None, # TODO: Could be known maybe. in_place=False, emit=emit, context=context, ) emit("}") def generateBuiltinCompileCode(to_name, expression, emit, context): source_name = context.allocateTempName("compile_source") filename_name = context.allocateTempName("compile_filename") mode_name = context.allocateTempName("compile_mode") generateExpressionCode( to_name=source_name, expression=expression.subnode_source, emit=emit, context=context, ) generateExpressionCode( to_name=filename_name, expression=expression.subnode_filename, emit=emit, context=context, ) generateExpressionCode( to_name=mode_name, expression=expression.subnode_mode, emit=emit, context=context, ) if expression.subnode_flags is not None: flags_name = context.allocateTempName("compile_flags") generateExpressionCode( to_name=flags_name, expression=expression.subnode_flags, emit=emit, context=context, ) else: flags_name = "NULL" if expression.subnode_dont_inherit is not None: dont_inherit_name = context.allocateTempName("compile_dont_inherit") generateExpressionCode( to_name=dont_inherit_name, expression=expression.subnode_dont_inherit, emit=emit, context=context, ) else: dont_inherit_name = "NULL" if expression.subnode_optimize is not None: optimize_name = context.allocateTempName("compile_optimize") generateExpressionCode( to_name=optimize_name, expression=expression.subnode_optimize, emit=emit, context=context, ) else: optimize_name = "NULL" context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) with withObjectCodeTemporaryAssignment( to_name, "compile_result", expression, emit, context ) as value_name: _getBuiltinCompileCode( to_name=value_name, source_name=source_name, filename_name=filename_name, mode_name=mode_name, flags_name=flags_name, dont_inherit_name=dont_inherit_name, optimize_name=optimize_name, emit=emit, context=context, ) def _getBuiltinCompileCode( to_name, source_name, filename_name, mode_name, flags_name, dont_inherit_name, optimize_name, emit, context, ): if python_version < 0x300: args = (source_name, filename_name, mode_name, flags_name, dont_inherit_name) else: args = ( source_name, filename_name, mode_name, flags_name, dont_inherit_name, optimize_name, ) emit("%s = COMPILE_CODE(%s);" % (to_name, ", ".join(str(arg) for arg in args))) getErrorExitCode( check_name=to_name, release_names=( source_name, filename_name, mode_name, flags_name, dont_inherit_name, optimize_name, ), emit=emit, context=context, ) context.addCleanupTempName(to_name) def getBuiltinEvalCode( to_name, source_name, filename_name, globals_name, locals_name, mode_name, emit, context, ): compiled_name = context.allocateTempName("eval_compiled") _getBuiltinCompileCode( to_name=compiled_name, source_name=source_name, filename_name=filename_name, mode_name=mode_name, flags_name="NULL", dont_inherit_name="NULL", optimize_name="NULL", emit=emit, context=context, ) emit( "%s = EVAL_CODE(%s, %s, %s);" % (to_name, compiled_name, globals_name, locals_name) ) getErrorExitCode( check_name=to_name, release_names=(compiled_name, globals_name, locals_name), emit=emit, context=context, ) context.addCleanupTempName(to_name) def generateExecCode(statement, emit, context): source_arg = statement.subnode_source globals_arg = statement.subnode_globals_arg locals_arg = statement.subnode_locals_arg source_name = context.allocateTempName("exec_source") globals_name = context.allocateTempName("exec_globals") locals_name = context.allocateTempName("exec_locals") generateExpressionCode( to_name=source_name, expression=source_arg, emit=emit, context=context ) generateExpressionCode( to_name=globals_name, expression=globals_arg, emit=emit, context=context ) generateExpressionCode( to_name=locals_name, expression=locals_arg, emit=emit, context=context ) source_ref = statement.getSourceReference() filename_name = context.allocateTempName("exec_filename") # Default filename with origin in improved mode. filename_name.getCType().emitAssignmentCodeFromConstant( to_name=filename_name, constant="" if Options.is_fullcompat else "" % source_ref.getAsString(), may_escape=False, emit=emit, context=context, ) getReferenceExportCode(filename_name, emit, context) context.addCleanupTempName(filename_name) getReferenceExportCode(source_name, emit, context) context.addCleanupTempName(source_name) with context.withCurrentSourceCodeReference( locals_arg.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): res_name = context.getBoolResName() emit( "%s = EXEC_FILE_ARG_HANDLING(&%s, &%s);" % (res_name, source_name, filename_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, emit=emit, context=context ) compiled_name = context.allocateTempName("exec_compiled") _getBuiltinCompileCode( to_name=compiled_name, source_name=source_name, filename_name=filename_name, mode_name=context.getConstantCode(constant="exec"), flags_name="NULL", dont_inherit_name="NULL", optimize_name="NULL", emit=emit, context=context, ) to_name = context.allocateTempName("exec_result") emit( "%s = EVAL_CODE(%s, %s, %s);" % (to_name, compiled_name, globals_name, locals_name) ) getErrorExitCode( check_name=to_name, release_names=( compiled_name, globals_name, locals_name, source_name, filename_name, ), emit=emit, context=context, ) # Immediately release the exec result, no point in keeping it, it's a # statement. context.addCleanupTempName(to_name) getReleaseCode(release_name=to_name, emit=emit, context=context) def _generateEvalCode(to_name, node, emit, context): source_name = context.allocateTempName("eval_source") globals_name = context.allocateTempName("eval_globals") locals_name = context.allocateTempName("eval_locals") generateExpressionCode( to_name=source_name, expression=node.subnode_source, emit=emit, context=context ) generateExpressionCode( to_name=globals_name, expression=node.subnode_globals_arg, emit=emit, context=context, ) generateExpressionCode( to_name=locals_name, expression=node.subnode_locals_arg, emit=emit, context=context, ) if node.isExpressionBuiltinEval() or ( python_version >= 0x300 and node.isExpressionBuiltinExec() ): filename = "" else: filename = "" getBuiltinEvalCode( to_name=to_name, source_name=source_name, globals_name=globals_name, locals_name=locals_name, filename_name=context.getConstantCode(constant=filename), mode_name=context.getConstantCode( constant="eval" if node.isExpressionBuiltinEval() else "exec" ), emit=emit, context=context, ) def generateEvalCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "eval_result", expression, emit, context ) as value_name: _generateEvalCode( to_name=value_name, node=expression, emit=emit, context=context ) def generateExecfileCode(to_name, expression, emit, context): assert python_version < 0x300 with withObjectCodeTemporaryAssignment( to_name, "execfile_result", expression, emit, context ) as value_name: _generateEvalCode( to_name=value_name, node=expression, emit=emit, context=context ) def generateLocalsDictSyncCode(statement, emit, context): locals_arg = statement.subnode_locals_arg locals_name = context.allocateTempName("sync_locals") generateExpressionCode( to_name=locals_name, expression=locals_arg, emit=emit, context=context ) with context.withCurrentSourceCodeReference(statement.getSourceReference()): _getStoreLocalsCode( locals_name=locals_name, variable_traces=statement.getPreviousVariablesTraces(), is_dict=locals_arg.hasShapeDictionaryExact(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/Namify.py0000600000372100037210000001752014166627112024770 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Namify constants. This determines the identifier names of constants in the generated code. We try to have readable names where possible, and resort to hash codes only when it is really necessary. """ import hashlib import math import re import sys from types import BuiltinFunctionType from nuitka.__past__ import GenericAlias, UnionType, long, unicode, xrange from nuitka.Builtins import builtin_anon_values, builtin_named_values_list from nuitka.Tracing import general class ExceptionCannotNamify(Exception): pass def namifyConstant(constant): # Many branches, statements and every case has a return, this is a huge case # statement, that encodes the naming policy of constants, with often complex # conditions, pylint: disable=too-many-branches,too-many-return-statements,too-many-statements constant_type = type(constant) if constant_type is int: if constant == 0: result = "int_0" elif constant > 0: result = "int_pos_%d" % constant else: result = "int_neg_%d" % abs(constant) if len(result) > 32: result = _digest(result) return result elif constant_type is long: if constant == 0: result = "long_0" elif constant > 0: result = "long_pos_%d" % constant else: result = "long_neg_%d" % abs(constant) if len(result) > 32: result = _digest(result) return result elif constant is None: return "none" elif constant is True: return "true" elif constant is False: return "false" elif constant is Ellipsis: return "ellipsis" elif constant_type is str: return "str_" + _namifyString(constant) elif constant_type is bytes: return "bytes_" + _namifyString(constant) elif constant_type is unicode: if _isAscii(constant): return "unicode_" + _namifyString(str(constant)) else: # Others are better digested to not cause compiler trouble return "unicode_digest_" + _digest(repr(constant)) elif constant_type is float: if math.isnan(constant): return "float_%s_nan" % ( "minus" if math.copysign(1, constant) < 0 else "plus" ) return "float_%s" % repr(constant).replace(".", "_").replace( "-", "minus_" ).replace("+", "") elif constant_type is complex: value = "%s__%s" % (constant.real, constant.imag) value = value.replace("+", "p").replace("-", "m").replace(".", "_") if value.startswith("(") and value.endswith(")"): value = value[1:-1] return "complex_%s" % value elif constant_type is dict: if constant == {}: return "dict_empty" else: return "dict_" + _digest(repr(constant)) elif constant_type is set: if constant == set(): return "set_empty" else: return "set_" + _digest(repr(constant)) elif constant_type is frozenset: if constant == frozenset(): return "frozenset_empty" else: return "frozenset_" + _digest(repr(constant)) elif constant_type is tuple: if constant == (): return "tuple_empty" else: try: result = "_".join(namifyConstant(value) for value in constant) if len(result) > 60: result = _digest(repr(constant)) return "tuple_" + result + "_tuple" except ExceptionCannotNamify: general.warning("Couldn't namify '%r'" % (constant,)) return "tuple_" + _digest(repr(constant)) elif constant_type is list: if constant == []: return "list_empty" else: try: result = "_".join(namifyConstant(value) for value in constant) if len(result) > 60: result = _digest(repr(constant)) return "list_" + result + "_list" except ExceptionCannotNamify: general.warning("Couldn't namify '%r'" % value) return "list_" + _digest(repr(constant)) elif constant_type is bytearray: return "bytearray_" + _digest(repr(constant)) elif constant_type is xrange: return "xrange_%s" % ( str(constant)[7 if str is bytes else 6 : -1] .replace(" ", "") .replace(",", "_") .replace("-", "neg") ) elif constant_type is slice: return "slice_%s_%s_%s" % ( namifyConstant(constant.start), namifyConstant(constant.stop), namifyConstant(constant.step), ) elif constant in builtin_anon_values: return "anon_%s" % builtin_anon_values[constant] elif constant_type is type: return "type_%s" % constant.__name__ elif constant_type is BuiltinFunctionType: assert constant in builtin_named_values_list return "builtin_%s" % constant.__name__ elif constant is NotImplemented: return "type_notimplemented" elif constant_type is GenericAlias: return "genalias_%s_%s" % ( namifyConstant(constant.__origin__), namifyConstant(constant.__args__), ) elif constant_type is UnionType: return "uniontype_%s" % namifyConstant(constant.__args__) elif constant is sys.version_info: return "sys_version_info" else: raise ExceptionCannotNamify("%r" % (constant,), constant_type) _re_str_needs_no_digest = re.compile(r"^([a-z]|[A-Z]|[0-9]|_){1,40}$", re.S) def _namifyString(string): # Many branches case has a return, encodes the naming policy of strings # constants, with often complex decisions to make, pylint: disable=too-many-return-statements if string in ("", b""): return "empty" elif string == " ": return "space" elif string == ".": return "dot" elif string == "\n": return "newline" elif ( type(string) is str and _re_str_needs_no_digest.match(string) and "\n" not in string ): # Some strings can be left intact for source code readability. return "plain_" + string elif len(string) == 1: return "chr_%d" % ord(string) elif ( len(string) > 2 and string[0] == "<" and string[-1] == ">" and _re_str_needs_no_digest.match(string[1:-1]) and "\n" not in string ): return "angle_" + string[1:-1] else: # Others are better digested to not cause compiler trouble return "digest_" + _digest(repr(string)) def _isAscii(string): try: _unused = str(string) return True except UnicodeEncodeError: return False def _digest(value): if str is bytes: # Python2 is simple return hashlib.md5(value).hexdigest() else: # Python3 needs to encode the string if it is one. if type(value) is bytes: return hashlib.md5(value).hexdigest() else: return hashlib.md5(value.encode("utf8")).hexdigest() Nuitka-0.6.19.1/nuitka/codegen/ErrorCodes.py0000600000372100037210000002215114166627112025610 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Error codes These are the helper functions that will emit the error exit codes. They can abstractly check conditions or values directly. The release of statement temporaries from context is automatic. Also formatting errors is done here, avoiding PyErr_Format as much as possible. And releasing of values, as this is what the error case commonly does. """ from nuitka.PythonVersions import python_version from .ExceptionCodes import getExceptionIdentifier from .Indentation import indented from .LineNumberCodes import getErrorLineNumberUpdateCode from .templates.CodeTemplatesExceptions import ( template_error_catch_exception, template_error_catch_quick_exception, template_error_format_name_error_exception, template_error_format_string_exception, ) def getErrorExitReleaseCode(context): temp_release = "\n".join( "Py_DECREF(%s);" % tmp_name for tmp_name in context.getCleanupTempnames() ) keeper_variables = context.getExceptionKeeperVariables() if keeper_variables[0] is not None: temp_release += "\nPy_DECREF(%s);" % keeper_variables[0] temp_release += "\nPy_XDECREF(%s);" % keeper_variables[1] temp_release += "\nPy_XDECREF(%s);" % keeper_variables[2] return temp_release def getFrameVariableTypeDescriptionCode(context): type_description = context.getFrameVariableTypeDescription() if type_description: return '%s = "%s";' % ( context.getFrameTypeDescriptionDeclaration(), type_description, ) else: return "" def getErrorExitBoolCode( condition, emit, context, release_names=(), release_name=None, needs_check=True, quick_exception=None, ): assert not condition.endswith(";") if release_names: getReleaseCodes(release_names, emit, context) assert not release_name if release_name is not None: assert type(release_name) is not tuple getReleaseCode(release_name, emit, context) assert not release_names if not needs_check: getAssertionCode("!(%s)" % condition, emit) return ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() if quick_exception: emit( indented( template_error_catch_quick_exception % { "condition": condition, "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "exception_exit": context.getExceptionEscape(), "quick_exception": getExceptionIdentifier(quick_exception), "release_temps": indented(getErrorExitReleaseCode(context)), "var_description_code": indented( getFrameVariableTypeDescriptionCode(context) ), "line_number_code": indented(getErrorLineNumberUpdateCode(context)), }, 0, ) ) else: emit( indented( template_error_catch_exception % { "condition": condition, "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, "exception_exit": context.getExceptionEscape(), "release_temps": indented(getErrorExitReleaseCode(context)), "var_description_code": indented( getFrameVariableTypeDescriptionCode(context) ), "line_number_code": indented(getErrorLineNumberUpdateCode(context)), }, 0, ) ) def getErrorExitCode( check_name, emit, context, release_names=(), release_name=None, quick_exception=None, needs_check=True, ): getErrorExitBoolCode( condition=check_name.getCType().getExceptionCheckCondition(check_name), release_names=release_names, release_name=release_name, needs_check=needs_check, quick_exception=quick_exception, emit=emit, context=context, ) def _getExceptionChainingCode(context): ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() keeper_vars = context.getExceptionKeeperVariables() if keeper_vars[0] is not None: return ("ADD_EXCEPTION_CONTEXT(&%s, &%s);" % (keeper_vars[0], keeper_vars[1]),) else: return ( "NORMALIZE_EXCEPTION(&%s, &%s, &%s);" % (exception_type, exception_value, exception_tb), "CHAIN_EXCEPTION(%s);" % exception_value, ) def getTakeReferenceCode(value_name, emit): value_name.getCType().getTakeReferenceCode(value_name=value_name, emit=emit) def getReleaseCode(release_name, emit, context): if context.needsCleanup(release_name): release_name.getCType().getReleaseCode( value_name=release_name, needs_check=False, emit=emit ) context.removeCleanupTempName(release_name) def getReleaseCodes(release_names, emit, context): for release_name in release_names: getReleaseCode(release_name=release_name, emit=emit, context=context) def getMustNotGetHereCode(reason, emit): emit( """\ NUITKA_CANNOT_GET_HERE("%s"); return NULL;""" % reason ) def getAssertionCode(check, emit): emit("assert(%s);" % check) def getLocalVariableReferenceErrorCode(variable, condition, emit, context): variable_name = variable.getName() ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() if variable.getOwner() is not context.getOwner(): helper_code = "FORMAT_UNBOUND_CLOSURE_ERROR" else: helper_code = "FORMAT_UNBOUND_LOCAL_ERROR" set_exception = [ "%s(&%s, &%s, %s);" % ( helper_code, exception_type, exception_value, context.getConstantCode(variable_name), ), "%s = NULL;" % exception_tb, ] # TODO: Move this into the helper code. if python_version >= 0x300: set_exception.extend(_getExceptionChainingCode(context)) emit( template_error_format_string_exception % { "condition": condition, "exception_exit": context.getExceptionEscape(), "set_exception": indented(set_exception), "release_temps": indented(getErrorExitReleaseCode(context)), "var_description_code": indented( getFrameVariableTypeDescriptionCode(context) ), "line_number_code": indented(getErrorLineNumberUpdateCode(context)), } ) # TODO: Get rid of this function entirely. def getNameReferenceErrorCode(variable_name, condition, emit, context): helper_code = "FORMAT_NAME_ERROR" if python_version < 0x340: owner = context.getOwner() if not owner.isCompiledPythonModule() and not owner.isExpressionClassBody(): helper_code = "FORMAT_GLOBAL_NAME_ERROR" ( exception_type, exception_value, _exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() set_exception = "%s(&%s, &%s, %s);" % ( helper_code, exception_type, exception_value, context.getConstantCode(variable_name), ) # TODO: Make this part of the helper code as well. if python_version >= 0x300: set_exception = [set_exception] set_exception.extend(_getExceptionChainingCode(context)) emit( template_error_format_name_error_exception % { "condition": condition, "exception_exit": context.getExceptionEscape(), "set_exception": indented(set_exception), "release_temps": indented(getErrorExitReleaseCode(context)), "var_description_code": indented( getFrameVariableTypeDescriptionCode(context) ), "line_number_code": indented(getErrorLineNumberUpdateCode(context)), } ) Nuitka-0.6.19.1/nuitka/codegen/Emission.py0000600000372100037210000000411514166627112025327 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Emission of source code. Code generation is driven via "emit", which is to receive lines of code and this is to collect them, providing the emit implementation. Sometimes nested use of these will occur. """ import contextlib from .Indentation import indented class SourceCodeCollector(object): def __init__(self): self.codes = [] def __call__(self, code): self.emit(code) def emit(self, code): for line in code.split("\n"): self.codes.append(line) def emitTo(self, emit, level): for code in self.codes: emit(indented(code, level)) self.codes = None @contextlib.contextmanager def withSubCollector(emit, context): context.pushCleanupScope() with context.variable_storage.withLocalStorage(): sub_emit = SourceCodeCollector() # To use the collector and put code in it and C declarations on the context. yield sub_emit local_declarations = context.variable_storage.makeCLocalDeclarations() if local_declarations: emit("{") for local_declaration in local_declarations: emit(indented(local_declaration)) sub_emit.emitTo(emit, level=1) emit("}") else: sub_emit.emitTo(emit, level=0) context.popCleanupScope() Nuitka-0.6.19.1/nuitka/codegen/StringCodes.py0000600000372100037210000002027714166627112025774 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ String related codes, str and unicode. """ from nuitka.PythonVersions import python_version from .CodeHelpers import ( decideConversionCheckNeeded, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitCode from .PythonAPICodes import generateCAPIObjectCode, makeArgDescFromExpression from .TupleCodes import getTupleCreationCode def generateBuiltinBytes1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_BYTES1", arg_desc=(("bytes_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinBytes3Code(to_name, expression, emit, context): encoding = expression.subnode_encoding errors = expression.subnode_errors generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_BYTES3", arg_desc=( ("bytes_arg", expression.subnode_value), ("bytes_encoding", encoding), ("bytes_errors", errors), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinUnicodeCode(to_name, expression, emit, context): encoding = expression.subnode_encoding errors = expression.subnode_errors if encoding is None and errors is None: generateCAPIObjectCode( to_name=to_name, capi="PyObject_Unicode", arg_desc=( ( "str_arg" if python_version < 0x300 else "unicode_arg", expression.subnode_value, ), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) else: generateCAPIObjectCode( to_name=to_name, capi="TO_UNICODE3", arg_desc=( ("unicode_arg", expression.subnode_value), ("unicode_encoding", encoding), ("unicode_errors", errors), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinStrCode(to_name, expression, emit, context): if python_version < 0x300: generateCAPIObjectCode( to_name=to_name, capi="PyObject_Str", arg_desc=(("str_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) else: return generateBuiltinUnicodeCode( to_name=to_name, expression=expression, emit=emit, context=context ) def generateBuiltinChrCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_CHR", arg_desc=(("chr_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinOrdCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_ORD", arg_desc=(("ord_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateStringContenationCode(to_name, expression, emit, context): values = expression.subnode_values with withObjectCodeTemporaryAssignment( to_name, "string_concat_result", expression, emit, context ) as value_name: tuple_temp_name = context.allocateTempName("string_concat_values") # TODO: Consider using _PyUnicode_JoinArray which avoids the tuple, # but got all to be able to release arrays. getTupleCreationCode( to_name=tuple_temp_name, elements=values, emit=emit, context=context ) emit( "%s = PyUnicode_Join(%s, %s);" % (value_name, context.getConstantCode(""), tuple_temp_name) ) getErrorExitCode( check_name=value_name, release_name=tuple_temp_name, emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateBuiltinFormatCode(to_name, expression, emit, context): value_name = context.allocateTempName("format_value") generateExpressionCode( to_name=value_name, expression=expression.subnode_value, emit=emit, context=context, ) format_spec_name = context.allocateTempName("format_spec") format_spec = expression.subnode_format_spec if format_spec is None: emit("%s = %s;" % (format_spec_name, context.getConstantCode(""))) else: generateExpressionCode( to_name=format_spec_name, expression=format_spec, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "format_result", expression, emit, context ) as result_name: emit( "%s = BUILTIN_FORMAT(%s, %s);" % (result_name, value_name, format_spec_name) ) getErrorExitCode( check_name=result_name, release_names=(value_name, format_spec_name), emit=emit, context=context, ) context.addCleanupTempName(result_name) def generateBuiltinAsciiCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PyObject_ASCII", arg_desc=(("ascii_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateStrOperationCode(to_name, expression, emit, context): api_name = expression.kind.rsplit("_")[-1] if str is bytes: api_name = "STR_" + api_name else: api_name = "UNICODE_" + api_name generateCAPIObjectCode( to_name=to_name, capi=api_name, arg_desc=makeArgDescFromExpression(expression), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/FrameCodes.py0000600000372100037210000004156714166627112025565 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Frame codes This is about frame stacks and their management. There are different kinds of frames for different uses. """ from nuitka.PythonVersions import python_version from .CodeHelpers import _generateStatementSequenceCode from .Emission import SourceCodeCollector from .ErrorCodes import getFrameVariableTypeDescriptionCode from .ExceptionCodes import getTracebackMakingIdentifier from .Indentation import indented from .LabelCodes import getGotoCode, getLabelCode from .ModuleCodes import getModuleAccessCode from .templates.CodeTemplatesFrames import ( template_frame_attach_locals, template_frame_guard_full_block, template_frame_guard_full_exception_handler, template_frame_guard_full_return_handler, template_frame_guard_generator, template_frame_guard_generator_exception_handler, template_frame_guard_generator_return_handler, template_frame_guard_once_block, template_frame_guard_once_exception_handler, ) def getFrameLocalsStorageSize(type_descriptions): candidates = set() for type_description in type_descriptions: candidate = "+".join( getTypeSizeOf(type_indicator) for type_indicator in sorted(type_description) ) candidates.add(candidate) if not candidates: return "0" candidates = list(sorted(candidates)) result = candidates.pop() while candidates: # assert False, (type_descriptions, context.frame_variables_stack[-1]) result = "MAX(%s, %s)" % (result, candidates.pop()) return result def _searchLocalVariableByName(local_variables, variable_name): for local_variable in local_variables: if local_variable.getName() == variable_name: return local_variable return None def generateStatementsFrameCode(statement_sequence, emit, context): # This is a wrapper that provides also handling of frames, which got a # lot of variants and details, therefore lots of branches and details. # pylint: disable=too-many-branches,too-many-locals,too-many-statements context.pushCleanupScope() guard_mode = statement_sequence.getGuardMode() code_object = statement_sequence.getCodeObject() code_identifier = context.getCodeObjectHandle(code_object=code_object) parent_exception_exit = context.getExceptionEscape() # For nested frames, make sure to restore set the type description. if context.getFrameHandle() is not None: real_parent_exception_exit = parent_exception_exit parent_exception_exit = context.allocateLabel("nested_frame_exit") # Allow stacking of frame handles. context.pushFrameHandle(code_identifier, statement_sequence.hasStructureMember()) context.setExceptionEscape(context.allocateLabel("frame_exception_exit")) needs_preserve = statement_sequence.needsFrameExceptionPreserving() if statement_sequence.mayReturn(): parent_return_exit = context.getReturnTarget() context.setReturnTarget(context.allocateLabel("frame_return_exit")) else: parent_return_exit = None # We need to define that all the variables needs to be pushed. We do not # have a flag that says "always NULL" for variables. With efficient NULL # passing however (not at all, TODO), that doesn't matter much. local_variables = statement_sequence.getParentVariableProvider().getLocalVariables() context.pushFrameVariables( tuple( _searchLocalVariableByName(local_variables, variable_name) for variable_name in code_object.getVarNames() ) ) # Now generate the statements code into a local buffer, to we can wrap # the frame stuff around it. local_emit = SourceCodeCollector() _generateStatementSequenceCode( statement_sequence=statement_sequence, emit=local_emit, context=context ) if statement_sequence.mayRaiseException(BaseException): frame_exception_exit = context.getExceptionEscape() else: frame_exception_exit = None if parent_return_exit is not None: frame_return_exit = context.getReturnTarget() else: frame_return_exit = None type_descriptions = context.getFrameVariableTypeDescriptions() if guard_mode == "generator": # TODO: This case should care about "needs_preserve", as for # Python3 it is actually not a stub of empty code. getFrameGuardLightCode( code_identifier=code_identifier, type_descriptions=type_descriptions, codes=local_emit.codes, parent_exception_exit=parent_exception_exit, frame_exception_exit=frame_exception_exit, parent_return_exit=parent_return_exit, frame_return_exit=frame_return_exit, emit=emit, context=context, ) elif guard_mode == "full": getFrameGuardHeavyCode( code_identifier=code_identifier, type_descriptions=type_descriptions, parent_exception_exit=parent_exception_exit, parent_return_exit=parent_return_exit, frame_exception_exit=frame_exception_exit, frame_return_exit=frame_return_exit, codes=local_emit.codes, needs_preserve=needs_preserve, emit=emit, context=context, ) elif guard_mode == "once": getFrameGuardOnceCode( code_identifier=code_identifier, parent_exception_exit=parent_exception_exit, parent_return_exit=parent_return_exit, frame_exception_exit=frame_exception_exit, frame_return_exit=frame_return_exit, codes=local_emit.codes, needs_preserve=needs_preserve, emit=emit, context=context, ) else: assert False, guard_mode context.popFrameVariables() context.popFrameHandle() # For nested frames, make sure to restore set the type description. if context.getFrameHandle() is not None: label = context.allocateLabel("skip_nested_handling") getGotoCode(label, emit) getLabelCode(parent_exception_exit, emit) emit(getFrameVariableTypeDescriptionCode(context)) getGotoCode(real_parent_exception_exit, emit) getLabelCode(label, emit) parent_exception_exit = real_parent_exception_exit context.popCleanupScope() context.setExceptionEscape(parent_exception_exit) if frame_return_exit is not None: context.setReturnTarget(parent_return_exit) def getTypeSizeOf(type_indicator): if type_indicator in ("O", "o", "N", "c"): return "sizeof(void *)" elif type_indicator == "b": return "sizeof(nuitka_bool)" elif type_indicator == "L": return "sizeof(nuitka_ilong)" else: assert False, type_indicator def getFrameAttachLocalsCode(context, frame_identifier): frame_variable_codes = context.getFrameVariableCodeNames() frame_variable_codes = ",\n ".join(frame_variable_codes) if frame_variable_codes: frame_variable_codes = ",\n " + frame_variable_codes return template_frame_attach_locals % { "frame_identifier": frame_identifier, "type_description": context.getFrameTypeDescriptionDeclaration(), "frame_variable_refs": frame_variable_codes, } def getFrameGuardHeavyCode( code_identifier, codes, type_descriptions, needs_preserve, parent_exception_exit, parent_return_exit, frame_exception_exit, frame_return_exit, emit, context, ): # We really need this many parameters here and it gets very # detail rich, pylint: disable=too-many-locals no_exception_exit = context.allocateLabel("frame_no_exception") frame_identifier = context.getFrameHandle() frame_cache_identifier = context.variable_storage.addFrameCacheDeclaration( frame_identifier.code_name ) ( _exception_type, _exception_value, _exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit( template_frame_guard_full_block % { "frame_identifier": frame_identifier, "frame_cache_identifier": frame_cache_identifier, "code_identifier": code_identifier, "locals_size": getFrameLocalsStorageSize(type_descriptions), "codes": indented(codes, 0), "module_identifier": getModuleAccessCode(context), "no_exception_exit": no_exception_exit, "needs_preserve": 1 if needs_preserve else 0, } ) if frame_return_exit is not None: emit( template_frame_guard_full_return_handler % { "frame_identifier": frame_identifier, "return_exit": parent_return_exit, "frame_return_exit": frame_return_exit, "needs_preserve": 1 if needs_preserve else 0, } ) if frame_exception_exit is not None: ( _exception_type, _exception_value, exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit( template_frame_guard_full_exception_handler % { "frame_identifier": frame_identifier, "frame_cache_identifier": frame_cache_identifier, "tb_making": getTracebackMakingIdentifier( context=context, lineno_name=exception_lineno ), "parent_exception_exit": parent_exception_exit, "frame_exception_exit": frame_exception_exit, "attach_locals": getFrameAttachLocalsCode(context, frame_identifier), "needs_preserve": 1 if needs_preserve else 0, "exception_tb": exception_tb, "exception_lineno": exception_lineno, } ) getLabelCode(no_exception_exit, emit) def getFrameGuardOnceCode( code_identifier, codes, parent_exception_exit, parent_return_exit, frame_exception_exit, frame_return_exit, needs_preserve, emit, context, ): # We really need this many parameters here. no_exception_exit = context.allocateLabel("frame_no_exception") # Used for modules only currently, but that ought to change. assert parent_return_exit is None and frame_return_exit is None emit( template_frame_guard_once_block % { "frame_identifier": context.getFrameHandle(), "code_identifier": code_identifier, "codes": indented(codes, 0), "module_identifier": getModuleAccessCode(context), "no_exception_exit": no_exception_exit, "needs_preserve": 1 if needs_preserve else 0, } ) if frame_exception_exit is not None: ( _exception_type, _exception_value, exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() emit( template_frame_guard_once_exception_handler % { "frame_identifier": context.getFrameHandle(), "tb_making": getTracebackMakingIdentifier( context=context, lineno_name=exception_lineno ), "parent_exception_exit": parent_exception_exit, "frame_exception_exit": frame_exception_exit, "needs_preserve": 1 if needs_preserve else 0, "exception_tb": exception_tb, "exception_lineno": exception_lineno, } ) getLabelCode(no_exception_exit, emit) def getFrameGuardLightCode( code_identifier, codes, parent_exception_exit, type_descriptions, parent_return_exit, frame_exception_exit, frame_return_exit, emit, context, ): # We really need this many parameters here and it gets very # detail rich, pylint: disable=too-many-locals ( exception_type, _exception_value, exception_tb, exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() context_identifier = context.getContextObjectName() no_exception_exit = context.allocateLabel("frame_no_exception") frame_identifier = context.getFrameHandle() frame_cache_identifier = context.variable_storage.addFrameCacheDeclaration( frame_identifier.code_name ) emit( template_frame_guard_generator % { "context_identifier": context_identifier, "frame_cache_identifier": frame_cache_identifier, "code_identifier": code_identifier, "locals_size": getFrameLocalsStorageSize(type_descriptions), "codes": indented(codes, 0), "module_identifier": getModuleAccessCode(context), "no_exception_exit": no_exception_exit, } ) if frame_return_exit is not None: emit( template_frame_guard_generator_return_handler % { "context_identifier": context_identifier, "frame_identifier": "%s->m_frame" % context_identifier, "return_exit": parent_return_exit, "frame_return_exit": frame_return_exit, } ) if frame_exception_exit is not None: emit( template_frame_guard_generator_exception_handler % { "context_identifier": context_identifier, "frame_identifier": frame_identifier, "frame_cache_identifier": frame_cache_identifier, "exception_type": exception_type, "exception_tb": exception_tb, "exception_lineno": exception_lineno, "tb_making": getTracebackMakingIdentifier( context=context, lineno_name=exception_lineno ), "attach_locals": indented( getFrameAttachLocalsCode(context, frame_identifier) ), "frame_exception_exit": frame_exception_exit, "parent_exception_exit": parent_exception_exit, } ) getLabelCode(no_exception_exit, emit) def generateFramePreserveExceptionCode(statement, emit, context): if python_version < 0x300: emit("// Preserve existing published exception.") emit( "PRESERVE_FRAME_EXCEPTION(%(frame_identifier)s);" % {"frame_identifier": context.getFrameHandle()} ) else: preserver_id = statement.getPreserverId() assert preserver_id != 0, statement ( exception_preserved_type, exception_preserved_value, exception_preserved_tb, ) = context.addExceptionPreserverVariables(preserver_id) emit( """\ // Preserve existing published exception id %(preserver_id)d. GET_CURRENT_EXCEPTION(&%(exception_preserved_type)s, &%(exception_preserved_value)s, &%(exception_preserved_tb)s); """ % { "exception_preserved_type": exception_preserved_type, "exception_preserved_value": exception_preserved_value, "exception_preserved_tb": exception_preserved_tb, "preserver_id": preserver_id, } ) def generateFrameRestoreExceptionCode(statement, emit, context): if python_version < 0x300: emit( """\ // Restore previous exception. RESTORE_FRAME_EXCEPTION(%(frame_identifier)s);""" % {"frame_identifier": context.getFrameHandle()} ) else: preserver_id = statement.getPreserverId() ( exception_preserved_type, exception_preserved_value, exception_preserved_tb, ) = context.addExceptionPreserverVariables(preserver_id) emit( """\ // Restore previous exception id %(preserver_id)d. SET_CURRENT_EXCEPTION(%(exception_preserved_type)s, %(exception_preserved_value)s, %(exception_preserved_tb)s); """ % { "exception_preserved_type": exception_preserved_type, "exception_preserved_value": exception_preserved_value, "exception_preserved_tb": exception_preserved_tb, "preserver_id": preserver_id, } ) Nuitka-0.6.19.1/nuitka/codegen/FunctionCodes.py0000600000372100037210000006502614166627112026314 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with compiled function objects. """ from nuitka.PythonVersions import python_version from nuitka.Tracing import general from .c_types.CTypePyObjectPtrs import CTypeCellObject, CTypePyObjectPtrPtr from .CodeHelpers import ( decideConversionCheckNeeded, generateExpressionCode, generateStatementSequenceCode, withObjectCodeTemporaryAssignment, ) from .Contexts import PythonFunctionOutlineContext from .Emission import SourceCodeCollector from .ErrorCodes import getErrorExitCode, getMustNotGetHereCode, getReleaseCode from .Indentation import indented from .LabelCodes import getGotoCode, getLabelCode from .LineNumberCodes import emitErrorLineNumberUpdateCode from .ModuleCodes import getModuleAccessCode from .PythonAPICodes import generateCAPIObjectCode, getReferenceExportCode from .templates.CodeTemplatesFunction import ( function_direct_body_template, template_function_body, template_function_direct_declaration, template_function_exception_exit, template_function_make_declaration, template_function_return_exit, template_make_function, template_maker_function_body, ) from .TupleCodes import getTupleCreationCode from .VariableCodes import ( decideLocalVariableCodeType, getLocalVariableDeclaration, ) def getFunctionCreationArgs( defaults_name, kw_defaults_name, annotations_name, closure_variables ): result = [] if defaults_name is not None: result.append("PyObject *defaults") if kw_defaults_name is not None: result.append("PyObject *kw_defaults") if annotations_name is not None: result.append("PyObject *annotations") if closure_variables: result.append("struct Nuitka_CellObject **closure") return result def getFunctionMakerDecl( function_identifier, closure_variables, defaults_name, kw_defaults_name, annotations_name, ): function_creation_args = getFunctionCreationArgs( defaults_name=defaults_name, kw_defaults_name=kw_defaults_name, annotations_name=annotations_name, closure_variables=closure_variables, ) return template_function_make_declaration % { "function_identifier": function_identifier, "function_creation_args": ", ".join(function_creation_args), } def _getFunctionEntryPointIdentifier(function_identifier): return "impl_" + function_identifier def _getFunctionMakerIdentifier(function_identifier): return "MAKE_FUNCTION_" + function_identifier def getFunctionQualnameObj(owner, context): """Get code to pass to function alike object creation for qualname. Qualname for functions existed for Python3, generators only after 3.5 and coroutines and asyncgen for as long as they existed. If identical to the name, we do not pass it as a value, but NULL instead. """ if owner.isExpressionFunctionBody(): min_version = 0x300 else: min_version = 0x350 if python_version < min_version: return "NULL" function_qualname = owner.getFunctionQualname() if function_qualname == owner.getFunctionName(): return "NULL" else: return context.getConstantCode(constant=function_qualname) def getFunctionMakerCode( function_body, function_identifier, closure_variables, defaults_name, kw_defaults_name, annotations_name, function_doc, context, ): # We really need this many parameters here and functions have many details, # that we express as variables, pylint: disable=too-many-locals function_creation_args = getFunctionCreationArgs( defaults_name=defaults_name, kw_defaults_name=kw_defaults_name, annotations_name=annotations_name, closure_variables=closure_variables, ) if function_doc is None: function_doc = "NULL" else: function_doc = context.getConstantCode(constant=function_doc) ( is_constant_returning, constant_return_value, ) = function_body.getConstantReturnValue() if is_constant_returning: function_impl_identifier = "NULL" if constant_return_value is None: # Default value, spare the code for common case. constant_return_code = "" elif constant_return_value is True: constant_return_code = "Nuitka_Function_EnableConstReturnTrue(result);" elif constant_return_value is False: constant_return_code = "Nuitka_Function_EnableConstReturnFalse(result);" else: constant_return_code = ( "Nuitka_Function_EnableConstReturnGeneric(result, %s);" % context.getConstantCode(constant_return_value) ) else: function_impl_identifier = _getFunctionEntryPointIdentifier( function_identifier=function_identifier ) constant_return_code = "" function_maker_identifier = _getFunctionMakerIdentifier( function_identifier=function_identifier ) code_identifier = context.getCodeObjectHandle( code_object=function_body.getCodeObject() ) module_identifier = getModuleAccessCode(context=context) result = template_maker_function_body % { "function_name_obj": context.getConstantCode( constant=function_body.getFunctionName() ), "function_qualname_obj": getFunctionQualnameObj(function_body, context), "function_maker_identifier": function_maker_identifier, "function_impl_identifier": function_impl_identifier, "function_creation_args": ", ".join(function_creation_args), "code_identifier": code_identifier, "function_doc": function_doc, "defaults": "defaults" if defaults_name else "NULL", "kw_defaults": "kw_defaults" if kw_defaults_name else "NULL", "annotations": "annotations" if annotations_name else "NULL", "closure_count": len(closure_variables), "closure_name": "closure" if closure_variables else "NULL", "module_identifier": module_identifier, "constant_return_code": indented(constant_return_code), } # TODO: Make it optional. context.addFunctionCreationInfo(function_impl_identifier) return result def generateFunctionCreationCode(to_name, expression, emit, context): # This is about creating functions, which is detail ridden stuff, # pylint: disable=too-many-locals function_body = expression.subnode_function_ref.getFunctionBody() defaults = expression.subnode_defaults kw_defaults = expression.subnode_kw_defaults annotations = expression.subnode_annotations defaults_first = not expression.kw_defaults_before_defaults assert function_body.needsCreation(), function_body def handleKwDefaults(): if kw_defaults: kw_defaults_name = context.allocateTempName("kw_defaults") assert not kw_defaults.isExpressionConstantDictEmptyRef(), kw_defaults generateExpressionCode( to_name=kw_defaults_name, expression=kw_defaults, emit=emit, context=context, ) else: kw_defaults_name = None return kw_defaults_name def handleDefaults(): if defaults: defaults_name = context.allocateTempName("defaults") getTupleCreationCode( to_name=defaults_name, elements=defaults, emit=emit, context=context ) else: defaults_name = None return defaults_name if defaults_first: defaults_name = handleDefaults() kw_defaults_name = handleKwDefaults() else: kw_defaults_name = handleKwDefaults() defaults_name = handleDefaults() if annotations: annotations_name = context.allocateTempName("annotations") generateExpressionCode( to_name=annotations_name, expression=annotations, emit=emit, context=context ) else: annotations_name = None function_identifier = function_body.getCodeName() # Creation code needs to be done only once. if not context.hasHelperCode(function_identifier): closure_variables = function_body.getClosureVariables() maker_code = getFunctionMakerCode( function_body=function_body, function_identifier=function_identifier, closure_variables=closure_variables, defaults_name=defaults_name, kw_defaults_name=kw_defaults_name, annotations_name=annotations_name, function_doc=function_body.getDoc(), context=context, ) context.addHelperCode(function_identifier, maker_code) function_decl = getFunctionMakerDecl( function_identifier=function_body.getCodeName(), closure_variables=closure_variables, defaults_name=defaults_name, kw_defaults_name=kw_defaults_name, annotations_name=annotations_name, ) context.addDeclaration(function_identifier, function_decl) getFunctionCreationCode( to_name=to_name, function_identifier=function_body.getCodeName(), defaults_name=defaults_name, kw_defaults_name=kw_defaults_name, annotations_name=annotations_name, closure_variables=expression.getClosureVariableVersions(), emit=emit, context=context, ) getReleaseCode(release_name=annotations_name, emit=emit, context=context) def getClosureCopyCode(closure_variables, context): """Get code to copy closure variables storage. This gets used by generator/coroutine/asyncgen with varying "closure_type". """ if closure_variables: closure_name = context.allocateTempName( "closure", "struct Nuitka_CellObject *[%d]" % len(closure_variables) ) else: closure_name = None closure_copy = [] for count, (variable, variable_trace) in enumerate(closure_variables): variable_declaration = getLocalVariableDeclaration( context, variable, variable_trace ) target_cell_code = "%s[%d]" % (closure_name, count) variable_c_type = variable_declaration.getCType() variable_c_type.getCellObjectAssignmentCode( target_cell_code=target_cell_code, variable_code_name=variable_declaration, emit=closure_copy.append, ) return closure_name, closure_copy def getFunctionCreationCode( to_name, function_identifier, defaults_name, kw_defaults_name, annotations_name, closure_variables, emit, context, ): args = [] if defaults_name is not None: getReferenceExportCode(defaults_name, emit, context) args.append(defaults_name) if kw_defaults_name is not None: args.append(kw_defaults_name) if annotations_name is not None: args.append(annotations_name) closure_name, closure_copy = getClosureCopyCode( closure_variables=closure_variables, context=context ) if closure_name: args.append(closure_name) function_maker_identifier = _getFunctionMakerIdentifier( function_identifier=function_identifier ) emit( template_make_function % { "to_name": to_name, "function_maker_identifier": function_maker_identifier, "args": ", ".join(str(arg) for arg in args), "closure_copy": indented(closure_copy, 0, True), } ) if context.needsCleanup(defaults_name): context.removeCleanupTempName(defaults_name) if context.needsCleanup(kw_defaults_name): context.removeCleanupTempName(kw_defaults_name) if context.needsCleanup(annotations_name): context.removeCleanupTempName(annotations_name) # No error checks, this supposedly, cannot fail. context.addCleanupTempName(to_name) def getDirectFunctionCallCode( to_name, function_identifier, arg_names, closure_variables, needs_check, emit, context, ): function_identifier = _getFunctionEntryPointIdentifier( function_identifier=function_identifier ) suffix_args = [] # TODO: Does this still have to be a triple, we are stopping to use # versions later in the game. for closure_variable, variable_trace in closure_variables: variable_declaration = getLocalVariableDeclaration( context=context, variable=closure_variable, variable_trace=variable_trace ) variable_c_type = variable_declaration.getCType() suffix_args.append( variable_c_type.getVariableArgReferencePassingCode(variable_declaration) ) # TODO: We ought to not assume references for direct calls, or make a # profile if an argument needs a reference at all. Most functions don't # bother to release a called argument by "del" or assignment to it. We # could well know that ahead of time. for arg_name in arg_names: if context.needsCleanup(arg_name): context.removeCleanupTempName(arg_name) else: emit("Py_INCREF(%s);" % arg_name) if arg_names: emit( """ { PyObject *dir_call_args[] = {%s}; %s = %s(dir_call_args%s%s); }""" % ( ", ".join(str(arg_name) for arg_name in arg_names), to_name, function_identifier, ", " if suffix_args else "", ", ".join(str(arg) for arg in suffix_args), ) ) else: emit( "%s = %s(NULL%s%s);" % ( to_name, function_identifier, ", " if suffix_args else "", ", ".join(str(arg) for arg in suffix_args), ) ) # Arguments are owned to the called in direct function call. for arg_name in arg_names: if context.needsCleanup(arg_name): context.removeCleanupTempName(arg_name) getErrorExitCode( check_name=to_name, emit=emit, needs_check=needs_check, context=context ) context.addCleanupTempName(to_name) def getFunctionDirectDecl(function_identifier, closure_variables, file_scope, context): parameter_objects_decl = ["PyObject **python_pars"] for closure_variable in closure_variables: variable_declaration = getLocalVariableDeclaration( context=context, variable=closure_variable, variable_trace=None, # TODO: See other uses of None ) variable_c_type = variable_declaration.getCType() parameter_objects_decl.append( variable_c_type.getVariableArgDeclarationCode(variable_declaration) ) result = template_function_direct_declaration % { "file_scope": file_scope, "function_identifier": function_identifier, "direct_call_arg_spec": ", ".join(parameter_objects_decl), } return result def setupFunctionLocalVariables( context, parameters, closure_variables, user_variables, temp_variables ): # Parameter variable initializations if parameters is not None: for count, variable in enumerate(parameters.getAllVariables()): variable_code_name, variable_c_type = decideLocalVariableCodeType( context=context, variable=variable ) variable_declaration = context.variable_storage.addVariableDeclarationTop( variable_c_type.c_type, variable_code_name, variable_c_type.getInitValue("python_pars[%d]" % count), ) context.setVariableType(variable, variable_declaration) # User local variable initializations for variable in user_variables: variable_code_name, variable_c_type = decideLocalVariableCodeType( context=context, variable=variable ) variable_declaration = context.variable_storage.addVariableDeclarationTop( variable_c_type.c_type, variable_code_name, variable_c_type.getInitValue(None), ) context.setVariableType(variable, variable_declaration) for variable in sorted(temp_variables, key=lambda variable: variable.getName()): variable_code_name, variable_c_type = decideLocalVariableCodeType( context=context, variable=variable ) context.variable_storage.addVariableDeclarationTop( variable_c_type.c_type, variable_code_name, variable_c_type.getInitValue(None), ) for closure_variable in closure_variables: variable_code_name, variable_c_type = decideLocalVariableCodeType( context=context, variable=closure_variable ) variable_declaration = context.variable_storage.addVariableDeclarationClosure( variable_c_type.c_type, variable_code_name ) assert variable_c_type in ( CTypeCellObject, CTypePyObjectPtrPtr, ), variable_c_type if not closure_variable.isTempVariable(): context.setVariableType(closure_variable, variable_declaration) def finalizeFunctionLocalVariables(context): function_cleanup = [] # TODO: Many times it will not be necessary to release locals dict, because # they already were, but our tracing doesn't yet allow us to know. for locals_declaration in sorted(context.getLocalsDictNames(), key=str): function_cleanup.append( "Py_XDECREF(%(locals_dict)s);\n" % {"locals_dict": locals_declaration} ) # Automatic variable releases if any. for variable in context.getOwner().getFunctionVariablesWithAutoReleases(): variable_declaration = getLocalVariableDeclaration( context=context, variable=variable, variable_trace=None, # TODO: See other uses of None. ) function_cleanup.append("CHECK_OBJECT(%s);" % variable_declaration) function_cleanup.append("Py_DECREF(%s);" % variable_declaration) return function_cleanup def getFunctionCode( context, function_identifier, parameters, closure_variables, user_variables, temp_variables, function_doc, file_scope, needs_exception_exit, ): try: return _getFunctionCode( context=context, function_identifier=function_identifier, parameters=parameters, closure_variables=closure_variables, user_variables=user_variables, temp_variables=temp_variables, function_doc=function_doc, file_scope=file_scope, needs_exception_exit=needs_exception_exit, ) except Exception: general.warning("Problem creating function code %r." % function_identifier) raise def _getFunctionCode( context, function_identifier, parameters, closure_variables, user_variables, temp_variables, function_doc, file_scope, needs_exception_exit, ): # Functions have many details, that we express as variables, with many # branches to decide, pylint: disable=too-many-locals setupFunctionLocalVariables( context=context, parameters=parameters, closure_variables=closure_variables, user_variables=user_variables, temp_variables=temp_variables, ) function_codes = SourceCodeCollector() generateStatementSequenceCode( statement_sequence=context.getOwner().subnode_body, allow_none=True, emit=function_codes, context=context, ) function_cleanup = finalizeFunctionLocalVariables(context=context) function_locals = context.variable_storage.makeCFunctionLevelDeclarations() function_doc = context.getConstantCode(constant=function_doc) result = "" emit = SourceCodeCollector() getMustNotGetHereCode( reason="Return statement must have exited already.", emit=emit ) function_exit = indented(emit.codes) + "\n\n" del emit if needs_exception_exit: ( exception_type, exception_value, exception_tb, _exception_lineno, ) = context.variable_storage.getExceptionVariableDescriptions() function_exit += template_function_exception_exit % { "function_cleanup": indented(function_cleanup), "exception_type": exception_type, "exception_value": exception_value, "exception_tb": exception_tb, } if context.hasTempName("return_value"): function_exit += template_function_return_exit % { "function_cleanup": indented(function_cleanup) } if context.isForCreatedFunction(): parameter_objects_decl = ["struct Nuitka_FunctionObject const *self"] else: parameter_objects_decl = [] parameter_objects_decl.append("PyObject **python_pars") if context.isForDirectCall(): for closure_variable in closure_variables: variable_declaration = getLocalVariableDeclaration( context=context, variable=closure_variable, variable_trace=None, # TODO: See other uses of None. ) variable_c_type = variable_declaration.getCType() parameter_objects_decl.append( variable_c_type.getVariableArgDeclarationCode(variable_declaration) ) result += function_direct_body_template % { "file_scope": file_scope, "function_identifier": function_identifier, "direct_call_arg_spec": ", ".join(parameter_objects_decl), "function_locals": indented(function_locals), "function_body": indented(function_codes.codes), "function_exit": function_exit, } else: result += template_function_body % { "function_identifier": function_identifier, "parameter_objects_decl": ", ".join(parameter_objects_decl), "function_locals": indented(function_locals), "function_body": indented(function_codes.codes), "function_exit": function_exit, } return result def getExportScopeCode(cross_module): if cross_module: return "NUITKA_CROSS_MODULE" else: return "NUITKA_LOCAL_MODULE" def generateFunctionCallCode(to_name, expression, emit, context): assert expression.subnode_function.isExpressionFunctionCreation() function_body = expression.subnode_function.subnode_function_ref.getFunctionBody() function_identifier = function_body.getCodeName() argument_values = expression.subnode_values arg_names = [] for count, arg_value in enumerate(argument_values, 1): arg_name = context.allocateTempName("dircall_arg%d" % count) generateExpressionCode( to_name=arg_name, expression=arg_value, emit=emit, context=context ) arg_names.append(arg_name) context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) with withObjectCodeTemporaryAssignment( to_name, "call_result", expression, emit, context ) as value_name: getDirectFunctionCallCode( to_name=value_name, function_identifier=function_identifier, arg_names=arg_names, closure_variables=expression.getClosureVariableVersions(), needs_check=expression.subnode_function.subnode_function_ref.getFunctionBody().mayRaiseException( BaseException ), emit=emit, context=context, ) def generateFunctionOutlineCode(to_name, expression, emit, context): assert ( expression.isExpressionOutlineBody() or expression.isExpressionOutlineFunctionBase() ) if expression.isExpressionOutlineFunctionBase(): context = PythonFunctionOutlineContext(parent=context, outline=expression) # Need to set return target, to assign to_name from. return_target = context.allocateLabel("outline_result") old_return_target = context.setReturnTarget(return_target) old_return_release_mode = context.setReturnReleaseMode(False) # TODO: Put the return value name as that to_name.c_type too. if ( expression.isExpressionOutlineFunctionBase() and expression.subnode_body.mayRaiseException(BaseException) ): exception_target = context.allocateLabel("outline_exception") old_exception_target = context.setExceptionEscape(exception_target) else: exception_target = None with withObjectCodeTemporaryAssignment( to_name, "outline_return_value", expression, emit, context ) as return_value_name: old_return_value_name = context.setReturnValueName(return_value_name) generateStatementSequenceCode( statement_sequence=expression.subnode_body, emit=emit, context=context, allow_none=False, ) context.addCleanupTempName(return_value_name) getMustNotGetHereCode( reason="Return statement must have exited already.", emit=emit ) if exception_target is not None: getLabelCode(exception_target, emit) context.setCurrentSourceCodeReference(expression.getSourceReference()) emitErrorLineNumberUpdateCode(emit, context) getGotoCode(old_exception_target, emit) context.setExceptionEscape(old_exception_target) getLabelCode(return_target, emit) # Restore previous "return" handling. context.setReturnTarget(old_return_target) context.setReturnReleaseMode(old_return_release_mode) context.setReturnValueName(old_return_value_name) def generateFunctionErrorStrCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="_PyObject_FunctionStr", arg_desc=(("func_arg", expression.subnode_value),), may_raise=False, conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/CodeHelpers.py0000600000372100037210000004062514166627112025744 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Helpers for code generation. This dispatch building of expressions and statements, as well as providing typical support functions to building parts. """ from contextlib import contextmanager from nuitka import Options from nuitka.nodes.NodeMetaClasses import NuitkaNodeDesignError from nuitka.Options import shallTraceExecution from nuitka.PythonVersions import python_version from nuitka.Tracing import printError from .Emission import withSubCollector from .LabelCodes import getGotoCode, getLabelCode, getStatementTrace from .Reports import onMissingHelper expression_dispatch_dict = {} def addExpressionDispatchDict(dispatch_dict): # We use this to break the cyclic dependency. expression_dispatch_dict.update(dispatch_dict) def generateExpressionCode(to_name, expression, emit, context, allow_none=False): try: _generateExpressionCode( to_name=to_name, expression=expression, emit=emit, context=context, allow_none=allow_none, ) except Exception: printError( "Problem with %r at %s" % ( expression, "" if expression is None else expression.getSourceReference().getAsString(), ) ) raise def _generateExpressionCode(to_name, expression, emit, context, allow_none=False): # This is a dispatching function for every expression. if expression is None and allow_none: return None # Make sure we don't generate code twice for any node, this uncovers bugs # where nodes are shared in the tree, which is not allowed. assert not hasattr(expression, "code_generated"), expression expression.code_generated = True if not expression.isExpression(): printError("No expression %r" % expression) expression.dump() assert False, expression try: code_generator = expression_dispatch_dict[expression.kind] except KeyError: raise NuitkaNodeDesignError( expression.__class__.__name__, "Need to provide code generation as well", expression.kind, ) with context.withCurrentSourceCodeReference(expression.getSourceReference()): code_generator( to_name=to_name, expression=expression, emit=emit, context=context ) def generateExpressionsCode(names, expressions, emit, context): assert len(names) == len(expressions) result = [] for name, expression in zip(names, expressions): if expression is not None: to_name = context.allocateTempName(name) generateExpressionCode( to_name=to_name, expression=expression, emit=emit, context=context ) else: to_name = None result.append(to_name) return result def generateChildExpressionsCode(expression, emit, context): value_names = [] for child_name, child_value in expression.getVisitableNodesNamed(): if type(child_value) is tuple: child_names = [] for child_val in child_value: if child_val.isExpressionKeyValuePair(): child_names.append( tuple( generateChildExpressionsCode( expression=child_val, emit=emit, context=context ) ) ) else: generateExpressionCode( to_name=value_name, expression=child_val, emit=emit, context=context, ) child_names.append(value_name) value_names.append(tuple(child_names)) elif child_value is not None: # Allocate anyway, so names are aligned. value_name = context.allocateTempName(child_name + "_value") generateExpressionCode( to_name=value_name, expression=child_value, emit=emit, context=context ) value_names.append(value_name) else: # Allocate anyway, so names are aligned. context.skipTempName(child_name + "_value") value_names.append(None) return value_names def generateChildExpressionCode(expression, emit, context, child_name=None): assert expression is not None if child_name is None: child_name = expression.getChildName() # Allocate anyway, so names are aligned. value_name = context.allocateTempName( child_name + "_value", ) generateExpressionCode( to_name=value_name, expression=expression, emit=emit, context=context ) return value_name statement_dispatch_dict = {} def setStatementDispatchDict(dispatch_dict): # Using global here, as this is really a singleton, in the form of a module, # and this is to break the cyclic dependency it has, pylint: disable=global-statement # Please call us only once. global statement_dispatch_dict assert not statement_dispatch_dict statement_dispatch_dict = dispatch_dict def generateStatementCode(statement, emit, context): try: statement_dispatch_dict[statement.kind]( statement=statement, emit=emit, context=context ) # Complain if any temporary was not dealt with yet. assert not context.getCleanupTempnames(), context.getCleanupTempnames() except Exception: printError( "Problem with %r at %s" % (statement, statement.getSourceReference().getAsString()) ) raise def _generateStatementSequenceCode(statement_sequence, emit, context): if statement_sequence is None: return for statement in statement_sequence.subnode_statements: if shallTraceExecution(): source_ref = statement.getSourceReference() statement_repr = repr(statement) source_repr = source_ref.getAsString() if python_version >= 0x300: statement_repr = statement_repr.encode("utf8") source_repr = source_repr.encode("utf8") emit(getStatementTrace(source_repr, statement_repr)) # Might contain frame statement sequences as children. if statement.isStatementsFrame(): from .FrameCodes import generateStatementsFrameCode generateStatementsFrameCode( statement_sequence=statement, emit=emit, context=context ) else: with withSubCollector(emit, context) as statement_emit: generateStatementCode( statement=statement, emit=statement_emit, context=context ) def generateStatementSequenceCode(statement_sequence, emit, context, allow_none=False): if allow_none and statement_sequence is None: return None assert statement_sequence.kind == "STATEMENTS_SEQUENCE", statement_sequence _generateStatementSequenceCode( statement_sequence=statement_sequence, emit=emit, context=context ) def decideConversionCheckNeeded(to_name, expression): if to_name.c_type == "nuitka_bool": conversion_check = expression.mayRaiseExceptionBool(BaseException) else: conversion_check = False return conversion_check # TODO: Get rid of the duplication of code with # "withObjectCodeTemporaryAssignment" by setting on one of them. @contextmanager def withObjectCodeTemporaryAssignment2( to_name, value_name, needs_conversion_check, emit, context ): """Converting to the target type, provide temporary object value name only if necessary.""" if to_name.c_type == "PyObject *": value_name = to_name else: value_name = context.allocateTempName(value_name) yield value_name if to_name is not value_name: to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=needs_conversion_check, emit=emit, context=context, ) from .ErrorCodes import getReleaseCode getReleaseCode(value_name, emit, context) @contextmanager def withObjectCodeTemporaryAssignment(to_name, value_name, expression, emit, context): """Converting to the target type, provide temporary object value name only if necessary.""" if to_name.c_type == "PyObject *": value_name = to_name else: value_name = context.allocateTempName(value_name) yield value_name if to_name is not value_name: to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=decideConversionCheckNeeded(to_name, expression), emit=emit, context=context, ) from .ErrorCodes import getReleaseCode getReleaseCode(value_name, emit, context) def assignConstantNoneResult(to_name, emit, context): # TODO: This is also in SetCode, and should be common for statement only # operations that return None in Python, but only in case of non-error to_name.getCType().emitAssignmentCodeFromConstant( to_name=to_name, constant=None, may_escape=False, emit=emit, context=context ) # This assignment will not necessarily use it, and since it is borrowed, # debug mode would otherwise complain. if to_name.c_type == "nuitka_void": to_name.maybe_unused = True class HelperCallHandle(object): def __init__( self, helper_name, target_type, helper_target, left_shape, helper_left, right_shape, helper_right, ): self.helper_name = helper_name self.target_type = target_type self.helper_target = helper_target self.left_shape = left_shape self.helper_left = helper_left self.right_shape = right_shape self.helper_right = helper_right def __str__(self): return self.helper_name def emitHelperCall(self, to_name, arg_names, ref_count, needs_check, emit, context): if ( self.target_type is not None and self.target_type.helper_code != self.helper_target.helper_code ): value_name = context.allocateTempName( to_name.code_name + "_" + self.helper_target.helper_code.lower(), type_name=self.helper_target.c_type, unique=to_name.code_name == "tmp_unused", ) else: value_name = to_name emit( "%s = %s(%s);" % ( value_name, self.helper_name, ", ".join( "%s%s" % ( "&" if count == 0 and "INPLACE" in self.helper_name else "", arg_name, ) for count, arg_name in enumerate(arg_names) ), ) ) # TODO: Move helper calling to something separate. from .ErrorCodes import ( getErrorExitCode, getReleaseCode, getReleaseCodes, ) # TODO: Have a method to indicate these. if value_name.getCType().c_type != "bool": getErrorExitCode( check_name=value_name, release_names=arg_names, needs_check=needs_check, emit=emit, context=context, ) else: getReleaseCodes(arg_names, emit, context) if ref_count: context.addCleanupTempName(value_name) if ( self.target_type is not None and self.target_type.helper_code != self.helper_target.helper_code ): if self.target_type.helper_code in ("NBOOL", "NVOID", "CBOOL"): self.target_type.emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=needs_check, emit=emit, context=context, ) # TODO: Push that release into the emitAssignConversionCode for higher efficiency # in code generation, or else error releases are done as well as later release. if ref_count: getReleaseCode(value_name, emit, context) else: assert False, ( self.target_type.helper_code, self.helper_target.helper_code, ) def pickCodeHelper( prefix, suffix, target_type, left_shape, right_shape, helpers, nonhelpers, source_ref, ): # Lots of details to deal with, # pylint: disable=too-many-locals left_part = left_shape.helper_code right_part = right_shape.helper_code assert left_part != "INVALID", left_shape assert right_part != "INVALID", right_shape if target_type is None: target_part = None else: target_part = target_type.helper_code assert target_part != "INVALID", target_type # Special hack for "NVOID", lets go to "NBOOL more automatically" ideal_helper = "_".join( p for p in (prefix, target_part, left_part, right_part, suffix) if p ) if target_part == "NVOID" and ideal_helper not in helpers: target_part = "NBOOL" ideal_helper = "_".join( p for p in (prefix, target_part, left_part, right_part, suffix) if p ) from .c_types.CTypeNuitkaBools import CTypeNuitkaBoolEnum helper_target = CTypeNuitkaBoolEnum else: helper_target = target_type if ideal_helper in helpers: return HelperCallHandle( helper_name=ideal_helper, target_type=target_type, helper_target=helper_target, left_shape=left_shape, helper_left=left_shape, right_shape=right_shape, helper_right=right_shape, ) if Options.is_report_missing and (not nonhelpers or ideal_helper not in nonhelpers): onMissingHelper(ideal_helper, source_ref) fallback_helper = "%s_%s_%s_%s%s" % (prefix, "OBJECT", "OBJECT", "OBJECT", suffix) fallback_helper = "_".join( p for p in (prefix, "OBJECT" if target_part else "", "OBJECT", "OBJECT", suffix) if p ) from .c_types.CTypePyObjectPtrs import CTypePyObjectPtr return HelperCallHandle( helper_name=fallback_helper, target_type=target_type, helper_target=CTypePyObjectPtr, left_shape=left_shape, helper_left=CTypePyObjectPtr, right_shape=right_shape, helper_right=CTypePyObjectPtr, ) @contextmanager def withCleanupFinally(name, release_name, needs_exception, emit, context): assert not context.needsCleanup(release_name) if needs_exception: exception_target = context.allocateLabel("%s_exception" % name) old_exception_target = context.setExceptionEscape(exception_target) with withSubCollector(emit, context) as guarded_emit: yield guarded_emit assert not context.needsCleanup(release_name) context.addCleanupTempName(release_name) if needs_exception: noexception_exit = context.allocateLabel("%s_noexception" % name) getGotoCode(noexception_exit, emit) context.setExceptionEscape(old_exception_target) emit("// Exception handling pass through code for %s:" % name) getLabelCode(exception_target, emit) from .ErrorCodes import getErrorExitReleaseCode emit(getErrorExitReleaseCode(context)) getGotoCode(old_exception_target, emit) emit("// Finished with no exception for %s:" % name) getLabelCode(noexception_exit, emit) Nuitka-0.6.19.1/nuitka/codegen/OperatorCodes.py0000600000372100037210000000237614166627112026321 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Operator code tables These are mostly used to look up the Python C/API from operations or a wrapper used. """ unary_operator_codes = { "UAdd": ("PyNumber_Positive", 1), "USub": ("PyNumber_Negative", 1), "Invert": ("PyNumber_Invert", 1), "Repr": ("PyObject_Repr", 1), "Not": ("UNARY_NOT", 0), } rich_comparison_codes = { "Lt": "LT", "LtE": "LE", "Eq": "EQ", "NotEq": "NE", "Gt": "GT", "GtE": "GE", } containing_comparison_codes = ("In", "NotIn") Nuitka-0.6.19.1/nuitka/codegen/AttributeCodes.py0000600000372100037210000002323714166627112026470 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Attribute related codes. Attribute lookup, setting. """ from nuitka import Options from .CodeHelpers import ( decideConversionCheckNeeded, generateChildExpressionsCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCode from .PythonAPICodes import generateCAPIObjectCode, generateCAPIObjectCode0 def generateAssignmentAttributeCode(statement, emit, context): lookup_source = statement.subnode_expression attribute_name = statement.getAttributeName() value = statement.subnode_source value_name = context.allocateTempName("assattr_value") generateExpressionCode( to_name=value_name, expression=value, emit=emit, context=context ) target_name = context.allocateTempName("assattr_target") generateExpressionCode( to_name=target_name, expression=lookup_source, emit=emit, context=context ) with context.withCurrentSourceCodeReference( value.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): if attribute_name == "__dict__": getAttributeAssignmentDictSlotCode( target_name=target_name, value_name=value_name, emit=emit, context=context, ) elif attribute_name == "__class__": getAttributeAssignmentClassSlotCode( target_name=target_name, value_name=value_name, emit=emit, context=context, ) else: getAttributeAssignmentCode( target_name=target_name, value_name=value_name, attribute_name=context.getConstantCode(constant=attribute_name), emit=emit, context=context, ) def generateDelAttributeCode(statement, emit, context): target_name = context.allocateTempName("attrdel_target") generateExpressionCode( to_name=target_name, expression=statement.subnode_expression, emit=emit, context=context, ) with context.withCurrentSourceCodeReference( statement.subnode_expression.getSourceReference() if Options.is_fullcompat else statement.getSourceReference() ): getAttributeDelCode( target_name=target_name, attribute_name=context.getConstantCode( constant=statement.getAttributeName() ), emit=emit, context=context, ) def generateAttributeLookupCode(to_name, expression, emit, context): (source_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) attribute_name = expression.getAttributeName() needs_check = expression.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=BaseException, attribute_name=attribute_name ) with withObjectCodeTemporaryAssignment( to_name, "attribute_value", expression, emit, context ) as value_name: if attribute_name == "__dict__": emit("%s = LOOKUP_ATTRIBUTE_DICT_SLOT(%s);" % (value_name, source_name)) elif attribute_name == "__class__": emit("%s = LOOKUP_ATTRIBUTE_CLASS_SLOT(%s);" % (value_name, source_name)) else: emit( "%s = LOOKUP_ATTRIBUTE(%s, %s);" % (value_name, source_name, context.getConstantCode(attribute_name)) ) getErrorExitCode( check_name=value_name, release_name=source_name, needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(value_name) def getAttributeAssignmentCode(target_name, attribute_name, value_name, emit, context): res_name = context.getBoolResName() emit( "%s = SET_ATTRIBUTE(%s, %s, %s);" % (res_name, target_name, attribute_name, value_name) ) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(value_name, target_name, attribute_name), emit=emit, context=context, ) def getAttributeAssignmentDictSlotCode(target_name, value_name, emit, context): """Code for special case target.__dict__ = value""" res_name = context.getBoolResName() emit("%s = SET_ATTRIBUTE_DICT_SLOT(%s, %s);" % (res_name, target_name, value_name)) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(value_name, target_name), emit=emit, context=context, ) def getAttributeAssignmentClassSlotCode(target_name, value_name, emit, context): """Get code for special case target.__class__ = value""" res_name = context.getBoolResName() emit("%s = SET_ATTRIBUTE_CLASS_SLOT(%s, %s);" % (res_name, target_name, value_name)) getErrorExitBoolCode( condition="%s == false" % res_name, release_names=(value_name, target_name), emit=emit, context=context, ) def getAttributeDelCode(target_name, attribute_name, emit, context): res_name = context.getIntResName() emit("%s = PyObject_DelAttr(%s, %s);" % (res_name, target_name, attribute_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(target_name, attribute_name), emit=emit, context=context, ) def generateAttributeLookupSpecialCode(to_name, expression, emit, context): (source_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) attribute_name = expression.getAttributeName() getAttributeLookupSpecialCode( to_name=to_name, source_name=source_name, attr_name=context.getConstantCode(constant=attribute_name), needs_check=expression.subnode_expression.mayRaiseExceptionAttributeLookupSpecial( exception_type=BaseException, attribute_name=attribute_name ), emit=emit, context=context, ) def getAttributeLookupSpecialCode( to_name, source_name, attr_name, needs_check, emit, context ): emit("%s = LOOKUP_SPECIAL(%s, %s);" % (to_name, source_name, attr_name)) getErrorExitCode( check_name=to_name, release_names=(source_name, attr_name), emit=emit, needs_check=needs_check, context=context, ) context.addCleanupTempName(to_name) def generateBuiltinHasattrCode(to_name, expression, emit, context): source_name, attr_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getIntResName() emit("%s = BUILTIN_HASATTR_BOOL(%s, %s);" % (res_name, source_name, attr_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(source_name, attr_name), needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != 0" % res_name, emit=emit ) def generateAttributeCheckCode(to_name, expression, emit, context): (source_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getBoolResName() emit( "%s = HAS_ATTR_BOOL(%s, %s);" % ( res_name, source_name, context.getConstantCode(constant=expression.getAttributeName()), ) ) getReleaseCode(release_name=source_name, emit=emit, context=context) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition=res_name, emit=emit ) def generateBuiltinGetattrCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_GETATTR", arg_desc=( ("getattr_target", expression.subnode_expression), ("getattr_attr", expression.subnode_name), ("getattr_default", expression.subnode_default), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinSetattrCode(to_name, expression, emit, context): generateCAPIObjectCode0( to_name=to_name, capi="BUILTIN_SETATTR", arg_desc=( ("setattr_target", expression.subnode_expression), ("setattr_attr", expression.subnode_attribute), ("setattr_value", expression.subnode_value), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/ImportCodes.py0000600000372100037210000002724114166627112025776 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Import related codes. That is import as expression, and star import. """ from nuitka.nodes.ImportNodes import hard_modules from nuitka.nodes.LocalsScopes import GlobalsDictHandle from nuitka.PythonVersions import python_version from nuitka.utils.Jinja2 import renderTemplateFromString from .CodeHelpers import ( generateChildExpressionsCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCode from .LineNumberCodes import emitLineNumberUpdateCode from .ModuleCodes import getModuleAccessCode def generateBuiltinImportCode(to_name, expression, emit, context): # We know that 5 expressions are created, pylint: disable=W0632 ( module_name, globals_name, locals_name, import_list_name, level_name, ) = generateChildExpressionsCode(expression=expression, emit=emit, context=context) with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: _getBuiltinImportCode( expression=expression, to_name=value_name, module_name=module_name, globals_name=globals_name, locals_name=locals_name, import_list_name=import_list_name, level_name=level_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) # TODO: Maybe use this for other cases too, not just import. def _getCountedArgumentsHelperCallCode( helper_prefix, to_name, args, min_args, needs_check, emit, context ): orig_args = args args = list(args) while args[-1] is None: del args[-1] if None in args: emit( "%s = %s_KW(%s);" % ( to_name, helper_prefix, ", ".join("NULL" if arg is None else str(arg) for arg in orig_args), ) ) else: # Check that no following arguments are not None. assert len(args) >= min_args emit( "%s = %s%d(%s);" % (to_name, helper_prefix, len(args), ", ".join(str(arg) for arg in args)) ) getErrorExitCode( check_name=to_name, release_names=args, needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(to_name) def _getBuiltinImportCode( expression, to_name, module_name, globals_name, locals_name, import_list_name, level_name, needs_check, emit, context, ): emitLineNumberUpdateCode(expression, emit, context) _getCountedArgumentsHelperCallCode( helper_prefix="IMPORT_MODULE", to_name=to_name, args=(module_name, globals_name, locals_name, import_list_name, level_name), min_args=1, needs_check=needs_check, emit=emit, context=context, ) def generateImportModuleFixedCode(to_name, expression, emit, context): module_name = expression.getModuleName() needs_check = expression.mayRaiseException(BaseException) if needs_check: emitLineNumberUpdateCode(expression, emit, context) with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: emit( """%s = IMPORT_MODULE1(%s);""" % (value_name, context.getConstantCode(module_name.asString())) ) getErrorExitCode( check_name=value_name, needs_check=needs_check, emit=emit, context=context ) context.addCleanupTempName(value_name) # IMPORT_MODULE1 doesn't give the child module if one is imported. if "." in module_name: getReleaseCode(value_name, emit, context) emit( """%s = Nuitka_GetModule(%s);""" % (value_name, context.getConstantCode(module_name.asString())) ) getErrorExitCode( check_name=value_name, needs_check=needs_check, emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateImportModuleHardCode(to_name, expression, emit, context): module_name = expression.getModuleName() needs_check = expression.mayRaiseException(BaseException) if needs_check: emitLineNumberUpdateCode(expression, emit, context) with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: emit("""%s = IMPORT_HARD_%s();""" % (value_name, module_name.upper())) getErrorExitCode( check_name=value_name, needs_check=needs_check, emit=emit, context=context ) def generateConstantSysVersionInfoCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: emit("""%s = Nuitka_SysGetObject("%s");""" % (value_name, "version_info")) getErrorExitCode( check_name=value_name, needs_check=False, emit=emit, context=context ) def generateImportModuleNameHardCode(to_name, expression, emit, context): module_name = expression.getModuleName() import_name = expression.getImportName() needs_check = expression.mayRaiseException(BaseException) with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: if module_name == "sys": emit("""%s = Nuitka_SysGetObject("%s");""" % (value_name, import_name)) elif module_name in hard_modules: emitLineNumberUpdateCode(expression, emit, context) # TODO: The import name wouldn't have to be an object really, could do with a # C string only. emit( """\ { PyObject *hard_module = IMPORT_HARD_%(module_name)s(); %(to_name)s = LOOKUP_ATTRIBUTE(hard_module, %(import_name)s); } """ % { "to_name": value_name, "module_name": module_name.upper(), "import_name": context.getConstantCode(import_name), } ) else: assert False, module_name getErrorExitCode( check_name=value_name, needs_check=needs_check, emit=emit, context=context ) def generateImportlibImportCallCode(to_name, expression, emit, context): needs_check = expression.mayRaiseException(BaseException) with withObjectCodeTemporaryAssignment( to_name, "imported_module", expression, emit, context ) as value_name: import_name, package_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) emitLineNumberUpdateCode(expression, emit, context) # TODO: The import name wouldn't have to be an object really, could do with a # C string only. emit( renderTemplateFromString( r""" { PyObject *hard_module = IMPORT_HARD_IMPORTLIB(); PyObject *import_module_func = LOOKUP_ATTRIBUTE(hard_module, {{context.getConstantCode("import_module")}}); {% if package_name == None %} {{to_name}} = CALL_FUNCTION_WITH_SINGLE_ARG(import_module_func, {{import_name}}); {% else %} PyObject *args[2] = { {{import_name}}, {{package_name}} }; {{to_name}} = CALL_FUNCTION_WITH_ARGS2(import_module_func, args); {% endif %} Py_DECREF(import_module_func); } """, context=context, to_name=value_name, import_name=import_name, package_name=package_name, ) ) getErrorExitCode( check_name=value_name, release_names=(import_name, package_name), needs_check=needs_check, emit=emit, context=context, ) def generateImportStarCode(statement, emit, context): module_name = context.allocateTempName("star_imported") generateExpressionCode( to_name=module_name, expression=statement.subnode_module, emit=emit, context=context, ) with context.withCurrentSourceCodeReference(statement.getSourceReference()): res_name = context.getBoolResName() target_scope = statement.getTargetDictScope() if type(target_scope) is GlobalsDictHandle: emit( "%s = IMPORT_MODULE_STAR(%s, true, %s);" % (res_name, getModuleAccessCode(context=context), module_name) ) else: locals_declaration = context.addLocalsDictName(target_scope.getCodeName()) emit( "%(res_name)s = IMPORT_MODULE_STAR(%(locals_dict)s, false, %(module_name)s);" % { "res_name": res_name, "locals_dict": locals_declaration, "module_name": module_name, } ) getErrorExitBoolCode( condition="%s == false" % res_name, release_name=module_name, emit=emit, context=context, ) def generateImportNameCode(to_name, expression, emit, context): from_arg_name = context.allocateTempName("import_name_from") generateExpressionCode( to_name=from_arg_name, expression=expression.subnode_module, emit=emit, context=context, ) with withObjectCodeTemporaryAssignment( to_name, "imported_value", expression, emit, context ) as value_name: if python_version >= 0x350: emit( """\ if (PyModule_Check(%(from_arg_name)s)) { %(to_name)s = IMPORT_NAME_OR_MODULE( %(from_arg_name)s, (PyObject *)moduledict_%(module_identifier)s, %(import_name)s, %(import_level)s ); } else { %(to_name)s = IMPORT_NAME(%(from_arg_name)s, %(import_name)s); } """ % { "to_name": value_name, "from_arg_name": from_arg_name, "import_name": context.getConstantCode( constant=expression.getImportName() ), "import_level": context.getConstantCode( constant=expression.getImportLevel() ), "module_identifier": context.getModuleCodeName(), } ) else: emit( "%s = IMPORT_NAME(%s, %s);" % ( value_name, from_arg_name, context.getConstantCode(constant=expression.getImportName()), ) ) getErrorExitCode( check_name=value_name, release_name=from_arg_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) context.addCleanupTempName(value_name) Nuitka-0.6.19.1/nuitka/codegen/ComparisonCodes.py0000600000372100037210000003227414166627112026640 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Comparison related codes. Rich comparisons, "in", and "not in", also "is", and "is not", and the "isinstance" check as used in conditions, as well as exception matching. """ from nuitka.containers.oset import OrderedSet from nuitka.nodes.shapes.BuiltinTypeShapes import tshape_bool from nuitka.Options import isExperimental from . import OperatorCodes from .CodeHelpers import generateExpressionCode, pickCodeHelper from .ErrorCodes import getErrorExitBoolCode, getReleaseCode, getReleaseCodes specialized_cmp_helpers_set = OrderedSet( ( "RICH_COMPARE_xx_OBJECT_OBJECT_OBJECT", "RICH_COMPARE_xx_CBOOL_OBJECT_OBJECT", "RICH_COMPARE_xx_NBOOL_OBJECT_OBJECT", "RICH_COMPARE_xx_OBJECT_OBJECT_STR", "RICH_COMPARE_xx_CBOOL_OBJECT_STR", "RICH_COMPARE_xx_NBOOL_OBJECT_STR", "RICH_COMPARE_xx_OBJECT_STR_OBJECT", "RICH_COMPARE_xx_CBOOL_STR_OBJECT", "RICH_COMPARE_xx_NBOOL_STR_OBJECT", "RICH_COMPARE_xx_OBJECT_STR_STR", "RICH_COMPARE_xx_CBOOL_STR_STR", "RICH_COMPARE_xx_NBOOL_STR_STR", "RICH_COMPARE_xx_OBJECT_OBJECT_UNICODE", "RICH_COMPARE_xx_CBOOL_OBJECT_UNICODE", "RICH_COMPARE_xx_NBOOL_OBJECT_UNICODE", "RICH_COMPARE_xx_OBJECT_UNICODE_OBJECT", "RICH_COMPARE_xx_CBOOL_UNICODE_OBJECT", "RICH_COMPARE_xx_NBOOL_UNICODE_OBJECT", "RICH_COMPARE_xx_OBJECT_UNICODE_UNICODE", "RICH_COMPARE_xx_CBOOL_UNICODE_UNICODE", "RICH_COMPARE_xx_NBOOL_UNICODE_UNICODE", "RICH_COMPARE_xx_CBOOL_OBJECT_BYTES", "RICH_COMPARE_xx_NBOOL_OBJECT_BYTES", "RICH_COMPARE_xx_OBJECT_BYTES_OBJECT", "RICH_COMPARE_xx_CBOOL_BYTES_OBJECT", "RICH_COMPARE_xx_NBOOL_BYTES_OBJECT", "RICH_COMPARE_xx_OBJECT_BYTES_BYTES", "RICH_COMPARE_xx_CBOOL_BYTES_BYTES", "RICH_COMPARE_xx_NBOOL_BYTES_BYTES", # "RICH_COMPARE_xx_OBJECT_UNICODE", # "RICH_COMPARE_xx_LONG_OBJECT", # "RICH_COMPARE_xx_UNICODE_OBJECT", # "RICH_COMPARE_xx_LONG_LONG", # "RICH_COMPARE_xx_UNICODE_UNICODE", "RICH_COMPARE_xx_OBJECT_INT_INT", "RICH_COMPARE_xx_CBOOL_INT_INT", "RICH_COMPARE_xx_NBOOL_INT_INT", "RICH_COMPARE_xx_OBJECT_OBJECT_INT", "RICH_COMPARE_xx_CBOOL_OBJECT_INT", "RICH_COMPARE_xx_NBOOL_OBJECT_INT", "RICH_COMPARE_xx_OBJECT_INT_OBJECT", "RICH_COMPARE_xx_CBOOL_INT_OBJECT", "RICH_COMPARE_xx_NBOOL_INT_OBJECT", "RICH_COMPARE_xx_OBJECT_LONG_LONG", "RICH_COMPARE_xx_CBOOL_LONG_LONG", "RICH_COMPARE_xx_NBOOL_LONG_LONG", "RICH_COMPARE_xx_OBJECT_OBJECT_LONG", "RICH_COMPARE_xx_CBOOL_OBJECT_LONG", "RICH_COMPARE_xx_NBOOL_OBJECT_LONG", "RICH_COMPARE_xx_OBJECT_LONG_OBJECT", "RICH_COMPARE_xx_CBOOL_LONG_OBJECT", "RICH_COMPARE_xx_NBOOL_LONG_OBJECT", "RICH_COMPARE_xx_OBJECT_FLOAT_FLOAT", "RICH_COMPARE_xx_CBOOL_FLOAT_FLOAT", "RICH_COMPARE_xx_NBOOL_FLOAT_FLOAT", "RICH_COMPARE_xx_OBJECT_OBJECT_FLOAT", "RICH_COMPARE_xx_CBOOL_OBJECT_FLOAT", "RICH_COMPARE_xx_NBOOL_OBJECT_FLOAT", "RICH_COMPARE_xx_OBJECT_FLOAT_OBJECT", "RICH_COMPARE_xx_CBOOL_FLOAT_OBJECT", "RICH_COMPARE_xx_NBOOL_FLOAT_OBJECT", "RICH_COMPARE_xx_OBJECT_TUPLE_TUPLE", "RICH_COMPARE_xx_CBOOL_TUPLE_TUPLE", "RICH_COMPARE_xx_NBOOL_TUPLE_TUPLE", "RICH_COMPARE_xx_OBJECT_OBJECT_TUPLE", "RICH_COMPARE_xx_CBOOL_OBJECT_TUPLE", "RICH_COMPARE_xx_NBOOL_OBJECT_TUPLE", "RICH_COMPARE_xx_OBJECT_TUPLE_OBJECT", "RICH_COMPARE_xx_CBOOL_TUPLE_OBJECT", "RICH_COMPARE_xx_NBOOL_TUPLE_OBJECT", "RICH_COMPARE_xx_OBJECT_LIST_LIST", "RICH_COMPARE_xx_CBOOL_LIST_LIST", "RICH_COMPARE_xx_NBOOL_LIST_LIST", "RICH_COMPARE_xx_OBJECT_OBJECT_LIST", "RICH_COMPARE_xx_CBOOL_OBJECT_LIST", "RICH_COMPARE_xx_NBOOL_OBJECT_LIST", "RICH_COMPARE_xx_OBJECT_LIST_OBJECT", "RICH_COMPARE_xx_CBOOL_LIST_OBJECT", "RICH_COMPARE_xx_NBOOL_LIST_OBJECT", # "RICH_COMPARE_xx_CBOOL_OBJECT_LONG", # "RICH_COMPARE_xx_CBOOL_OBJECT_UNICODE", # "RICH_COMPARE_xx_CBOOL_LONG_OBJECT", # "RICH_COMPARE_xx_CBOOL_UNICODE_OBJECT", # "RICH_COMPARE_xx_CBOOL_LONG_LONG", # "RICH_COMPARE_xx_CBOOL_UNICODE_UNICODE", ) ) def generateComparisonExpressionCode(to_name, expression, emit, context): left = expression.subnode_left right = expression.subnode_right comparator = expression.getComparator() type_name = "PyObject *" if comparator in ("Is", "IsNot"): if left.getTypeShape() is tshape_bool and right.getTypeShape() is tshape_bool: type_name = "nuitka_bool" left_name = context.allocateTempName("compexpr_left", type_name=type_name) right_name = context.allocateTempName("compexpr_right", type_name=type_name) generateExpressionCode( to_name=left_name, expression=left, emit=emit, context=context ) generateExpressionCode( to_name=right_name, expression=right, emit=emit, context=context ) if comparator in OperatorCodes.containing_comparison_codes: needs_check = right.mayRaiseExceptionIn(BaseException, expression.subnode_left) res_name = context.getIntResName() emit( "%s = PySequence_Contains(%s, %s);" % (res_name, right_name, left_name) # sequence goes first in the API. ) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(left_name, right_name), needs_check=needs_check, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s == %d" % (res_name, 1 if comparator == "In" else 0), emit=emit, ) elif comparator == "Is": to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s == %s" % (left_name, right_name), emit=emit ) getReleaseCodes( release_names=(left_name, right_name), emit=emit, context=context ) elif comparator == "IsNot": to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != %s" % (left_name, right_name), emit=emit ) getReleaseCodes( release_names=(left_name, right_name), emit=emit, context=context ) elif comparator in OperatorCodes.rich_comparison_codes: needs_check = expression.mayRaiseExceptionComparison() # TODO: This is probably not really worth it, but we used to do it. # if comparator == "Eq" and not context.mayRecurse(): # suffix = "_NORECURSE" # else: # suffix = "" helper = pickCodeHelper( prefix="RICH_COMPARE_xx", suffix="", target_type=to_name.getCType(), left_shape=left.getTypeShape(), right_shape=expression.subnode_right.getTypeShape(), helpers=specialized_cmp_helpers_set, nonhelpers=(), source_ref=expression.source_ref, ) # Lets patch this up here, instead of having one set per comparison operation. helper.helper_name = helper.helper_name.replace( "xx", OperatorCodes.rich_comparison_codes[comparator] ) helper.emitHelperCall( to_name=to_name, arg_names=(left_name, right_name), ref_count=1, needs_check=needs_check, emit=emit, context=context, ) elif comparator in ("exception_match", "exception_mismatch"): needs_check = expression.mayRaiseExceptionComparison() res_name = context.getIntResName() emit("%s = EXCEPTION_MATCH_BOOL(%s, %s);" % (res_name, left_name, right_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(left_name, right_name), needs_check=needs_check, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s %s 0" % (res_name, "!=" if comparator == "exception_match" else "=="), emit=emit, ) else: assert False, comparator def generateBuiltinIsinstanceCode(to_name, expression, emit, context): inst_name = context.allocateTempName("isinstance_inst") cls_name = context.allocateTempName("isinstance_cls") generateExpressionCode( to_name=inst_name, expression=expression.subnode_instance, emit=emit, context=context, ) generateExpressionCode( to_name=cls_name, expression=expression.subnode_classes, emit=emit, context=context, ) context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) res_name = context.getIntResName() if isExperimental("function-base"): emit("%s = PyObject_IsInstance(%s, %s);" % (res_name, inst_name, cls_name)) else: emit("%s = Nuitka_IsInstance(%s, %s);" % (res_name, inst_name, cls_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(inst_name, cls_name), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != 0" % res_name, emit=emit ) def generateBuiltinIssubclassCode(to_name, expression, emit, context): cls_name = context.allocateTempName("issubclass_cls") classes_name = context.allocateTempName("issubclass_classes") generateExpressionCode( to_name=cls_name, expression=expression.subnode_cls, emit=emit, context=context, ) generateExpressionCode( to_name=classes_name, expression=expression.subnode_classes, emit=emit, context=context, ) context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) res_name = context.getIntResName() emit("%s = PyObject_IsSubclass(%s, %s);" % (res_name, cls_name, classes_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(cls_name, classes_name), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != 0" % res_name, emit=emit ) def generateTypeCheckCode(to_name, expression, emit, context): cls_name = context.allocateTempName("issubclass_cls") generateExpressionCode( to_name=cls_name, expression=expression.subnode_cls, emit=emit, context=context, ) context.setCurrentSourceCodeReference(expression.getCompatibleSourceReference()) res_name = context.getIntResName() emit("%s = PyType_Check(%s);" % (res_name, cls_name)) getReleaseCode( release_name=cls_name, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != 0" % res_name, emit=emit ) def generateMatchTypeCheckMappingCode(to_name, expression, emit, context): cls_name = context.allocateTempName("mapping_check_cls") generateExpressionCode( to_name=cls_name, expression=expression.subnode_value, emit=emit, context=context, ) res_name = context.getIntResName() emit("%s = Py_TYPE(%s)->tp_flags & Py_TPFLAGS_MAPPING;" % (res_name, cls_name)) getReleaseCode( release_name=cls_name, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s" % res_name, emit=emit ) def generateMatchTypeCheckSequenceCode(to_name, expression, emit, context): cls_name = context.allocateTempName("sequence_check_cls") generateExpressionCode( to_name=cls_name, expression=expression.subnode_value, emit=emit, context=context, ) res_name = context.getIntResName() emit("%s = Py_TYPE(%s)->tp_flags & Py_TPFLAGS_SEQUENCE;" % (res_name, cls_name)) getReleaseCode( release_name=cls_name, emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s" % res_name, emit=emit ) Nuitka-0.6.19.1/nuitka/codegen/ConstantCodes.py0000600000372100037210000001341114166627112026307 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Low level constant code generation. This deals with constants, there creation, there access, and some checks about them. Even mutable constants should not change during the course of the program. There are shared constants, which are created for multiple modules to use, you can think of them as globals. And there are module local constants, which are for a single module only. """ import os import sys from nuitka import Options from nuitka.constants.Serialization import ConstantAccessor from nuitka.PythonVersions import python_version from nuitka.Version import getNuitkaVersion from .CodeHelpers import withObjectCodeTemporaryAssignment from .ErrorCodes import getAssertionCode from .GlobalConstants import getConstantDefaultPopulation from .Namify import namifyConstant from .templates.CodeTemplatesConstants import template_constants_reading from .templates.CodeTemplatesModules import template_header_guard def generateConstantReferenceCode(to_name, expression, emit, context): """Assign the constant behind the expression to to_name.""" to_name.getCType().emitAssignmentCodeFromConstant( to_name=to_name, constant=expression.getCompileTimeConstant(), # Derive this from context. may_escape=True, emit=emit, context=context, ) def generateConstantGenericAliasCode(to_name, expression, emit, context): # TODO: Have these as prepared constants as well, if args are not mutable. origin_name = context.allocateTempName("generic_alias_origin") args_name = context.allocateTempName("generic_alias_args") origin_name.getCType().emitAssignmentCodeFromConstant( to_name=origin_name, constant=expression.getCompileTimeConstant().__origin__, may_escape=True, emit=emit, context=context, ) args_name.getCType().emitAssignmentCodeFromConstant( to_name=args_name, constant=expression.getCompileTimeConstant().__args__, may_escape=True, emit=emit, context=context, ) with withObjectCodeTemporaryAssignment( to_name, "builtin_value", expression, emit, context ) as value_name: emit("%s = Py_GenericAlias(%s, %s);" % (value_name, origin_name, args_name)) getAssertionCode(check="%s != NULL" % value_name, emit=emit) context.addCleanupTempName(value_name) def getConstantsDefinitionCode(): """Create the code code "__constants.c" and "__constants.h" files. This needs to create code to make all global constants (used in more than one module) and create them. """ constant_accessor = ConstantAccessor( data_filename="__constants.const", top_level_name="global_constants" ) lines = [] for constant_value in getConstantDefaultPopulation(): identifier = constant_accessor.getConstantCode(constant_value) assert "[" in identifier, (identifier, constant_value) lines.append("// %s" % repr(constant_value)) lines.append( "#define const_%s %s" % (namifyConstant(constant_value), identifier) ) sys_executable = None if not Options.shallMakeModule(): if Options.isStandaloneMode(): # The directory is added back at run time. sys_executable = constant_accessor.getConstantCode( os.path.basename(sys.executable) ) else: sys_executable = constant_accessor.getConstantCode(sys.executable) sys_prefix = None sys_base_prefix = None sys_exec_prefix = None sys_base_exec_prefix = None # TODO: This part is needed for main program only, so do it there? if not Options.shallMakeModule() and not Options.isStandaloneMode(): sys_prefix = constant_accessor.getConstantCode(sys.prefix) sys_exec_prefix = constant_accessor.getConstantCode(sys.exec_prefix) if python_version >= 0x300: sys_base_prefix = constant_accessor.getConstantCode(sys.base_prefix) sys_base_exec_prefix = constant_accessor.getConstantCode( sys.base_exec_prefix ) lines.insert( 0, "extern PyObject *global_constants[%d];" % constant_accessor.getConstantsCount(), ) header = template_header_guard % { "header_guard_name": "__NUITKA_GLOBAL_CONSTANTS_H__", "header_body": "\n".join(lines), } major, minor, micro = getNuitkaVersion().split(".")[:3] if "rc" in micro: micro = micro[: micro.find("rc")] level = "candidate" else: level = "release" body = template_constants_reading % { "global_constants_count": constant_accessor.getConstantsCount(), "sys_executable": sys_executable, "sys_prefix": sys_prefix, "sys_base_prefix": sys_base_prefix, "sys_exec_prefix": sys_exec_prefix, "sys_base_exec_prefix": sys_base_exec_prefix, "nuitka_version_major": major, "nuitka_version_minor": minor, "nuitka_version_micro": micro, "nuitka_version_level": level, } return header, body Nuitka-0.6.19.1/nuitka/codegen/SetCodes.py0000600000372100037210000001456514166627112025264 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code generation for sets. Right now only the creation, and set add code is done here. But more should be added later on. """ from nuitka.PythonVersions import needsSetLiteralReverseInsertion from .CodeHelpers import ( assignConstantNoneResult, decideConversionCheckNeeded, generateChildExpressionsCode, generateExpressionCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import getAssertionCode, getErrorExitBoolCode from .PythonAPICodes import generateCAPIObjectCode def generateSetCreationCode(to_name, expression, emit, context): element_name = context.allocateTempName("set_element") elements = expression.subnode_elements # Supposed to optimize empty set to constant value. assert elements, expression with withObjectCodeTemporaryAssignment( to_name, "set_result", expression, emit, context ) as result_name: for count, element in enumerate(elements): generateExpressionCode( to_name=element_name, expression=element, emit=emit, context=context ) if count == 0: emit("%s = PySet_New(NULL);" % (result_name,)) getAssertionCode(result_name, emit) context.addCleanupTempName(to_name) res_name = context.getIntResName() emit("%s = PySet_Add(%s, %s);" % (res_name, to_name, element_name)) getErrorExitBoolCode( condition="%s != 0" % res_name, needs_check=not element.isKnownToBeHashable(), emit=emit, context=context, ) if context.needsCleanup(element_name): emit("Py_DECREF(%s);" % element_name) context.removeCleanupTempName(element_name) def generateSetLiteralCreationCode(to_name, expression, emit, context): if not needsSetLiteralReverseInsertion(): return generateSetCreationCode(to_name, expression, emit, context) with withObjectCodeTemporaryAssignment( to_name, "set_result", expression, emit, context ) as result_name: emit("%s = PySet_New(NULL);" % (result_name,)) context.addCleanupTempName(result_name) elements = expression.subnode_elements element_names = [] for count, element in enumerate(elements, 1): element_name = context.allocateTempName("set_element_%d" % count) element_names.append(element_name) generateExpressionCode( to_name=element_name, expression=element, emit=emit, context=context ) for count, element in enumerate(elements): element_name = element_names[len(elements) - count - 1] if element.isKnownToBeHashable(): emit("PySet_Add(%s, %s);" % (result_name, element_name)) else: res_name = context.getIntResName() emit("%s = PySet_Add(%s, %s);" % (res_name, result_name, element_name)) getErrorExitBoolCode( condition="%s != 0" % res_name, emit=emit, context=context ) if context.needsCleanup(element_name): emit("Py_DECREF(%s);" % element_name) context.removeCleanupTempName(element_name) def generateSetOperationAddCode(statement, emit, context): set_arg_name = context.allocateTempName("add_set") generateExpressionCode( to_name=set_arg_name, expression=statement.subnode_set_arg, emit=emit, context=context, ) value_arg_name = context.allocateTempName("add_value") generateExpressionCode( to_name=value_arg_name, expression=statement.subnode_value, emit=emit, context=context, ) context.setCurrentSourceCodeReference(statement.getSourceReference()) res_name = context.getIntResName() emit("assert(PySet_Check(%s));" % set_arg_name) emit("%s = PySet_Add(%s, %s);" % (res_name, set_arg_name, value_arg_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(set_arg_name, value_arg_name), emit=emit, context=context, ) def generateSetOperationUpdateCode(to_name, expression, emit, context): res_name = context.getIntResName() set_arg_name, value_arg_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) emit("assert(PySet_Check(%s));" % set_arg_name) emit("%s = _PySet_Update(%s, %s);" % (res_name, set_arg_name, value_arg_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_names=(set_arg_name, value_arg_name), emit=emit, context=context, ) assignConstantNoneResult(to_name, emit, context) def generateBuiltinSetCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PySet_New", arg_desc=(("set_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinFrozensetCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="PyFrozenSet_New", arg_desc=(("frozenset_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/__init__.py0000600000372100037210000000150114166627112025274 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/codegen/LabelCodes.py0000600000372100037210000000374614166627112025547 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ C labels, small helpers. Much things are handled with "goto" statements in the generated code, error exits, finally blocks, etc. this provides just the means to emit a label or the goto statement itself. """ from nuitka.utils.CStrings import encodePythonStringToC def getGotoCode(label, emit): assert label is not None emit("goto %s;" % label) def getLabelCode(label, emit): assert label is not None emit("%s:;" % label) def getBranchingCode(condition, emit, context): true_target = context.getTrueBranchTarget() false_target = context.getFalseBranchTarget() if true_target is not None and false_target is None: emit("if (%s) goto %s;" % (condition, true_target)) elif true_target is None and false_target is not None: emit("if (!(%s)) goto %s;" % (condition, false_target)) else: assert true_target is not None and false_target is not None emit( """\ if (%s) { goto %s; } else { goto %s; }""" % (condition, true_target, false_target) ) def getStatementTrace(source_desc, statement_repr): return 'NUITKA_PRINT_TRACE("Execute: " %s);' % ( encodePythonStringToC(source_desc + b" " + statement_repr), ) Nuitka-0.6.19.1/nuitka/codegen/BuiltinCodes.py0000600000372100037210000003463714166627112026141 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in codes This is code generation for built-in references, and some built-ins like range, bin, etc. """ from nuitka import Builtins from nuitka.PythonVersions import python_version from .CodeHelpers import ( decideConversionCheckNeeded, generateChildExpressionsCode, withObjectCodeTemporaryAssignment, ) from .ErrorCodes import ( getAssertionCode, getErrorExitBoolCode, getErrorExitCode, ) from .PythonAPICodes import generateCAPIObjectCode def generateBuiltinAbsCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_ABS", arg_desc=(("abs_arg", expression.subnode_operand),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinRefCode(to_name, expression, emit, context): builtin_name = expression.getBuiltinName() with withObjectCodeTemporaryAssignment( to_name, "builtin_value", expression, emit, context ) as value_name: emit( "%s = LOOKUP_BUILTIN(%s);" % (value_name, context.getConstantCode(constant=builtin_name)) ) getAssertionCode(check="%s != NULL" % value_name, emit=emit) # Gives no reference def generateBuiltinAnonymousRefCode(to_name, expression, emit, context): builtin_name = expression.getBuiltinName() with withObjectCodeTemporaryAssignment( to_name, "builtin_value", expression, emit, context ) as value_name: emit( "%s = (PyObject *)%s;" % (value_name, Builtins.builtin_anon_codes[builtin_name]) ) def generateBuiltinType1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_TYPE1", arg_desc=(("type_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinType3Code(to_name, expression, emit, context): type_name, bases_name, dict_name = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) with withObjectCodeTemporaryAssignment( to_name, "type3_result", expression, emit, context ) as value_name: emit( "%s = BUILTIN_TYPE3(%s, %s, %s, %s);" % ( value_name, context.getConstantCode(constant=context.getModuleName().asString()), type_name, bases_name, dict_name, ) ) getErrorExitCode( check_name=value_name, release_names=(type_name, bases_name, dict_name), emit=emit, context=context, ) context.addCleanupTempName(value_name) def generateBuiltinOpenCode(to_name, expression, emit, context): arg_desc = ( ("open_filename", expression.subnode_filename), ("open_mode", expression.subnode_mode), ("open_buffering", expression.subnode_buffering), ) if python_version >= 0x300: arg_desc += ( ("open_encoding", expression.subnode_encoding), ("open_errors", expression.subnode_errors), ("open_newline", expression.subnode_newline), ("open_closefd", expression.subnode_closefd), ("open_opener", expression.subnode_opener), ) generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_OPEN", arg_desc=arg_desc, may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), none_null=True, source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinSum1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_SUM1", arg_desc=(("sum_sequence", expression.subnode_sequence),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinSum2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_SUM2", arg_desc=( ("sum_sequence", expression.subnode_sequence), ("sum_start", expression.subnode_start), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinRange1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_RANGE", arg_desc=(("range_arg", expression.subnode_low),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinRange2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_RANGE2", arg_desc=( ("range2_low", expression.subnode_low), ("range2_high", expression.subnode_high), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinRange3Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_RANGE3", arg_desc=( ("range3_low", expression.subnode_low), ("range3_high", expression.subnode_high), ("range3_step", expression.subnode_step), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinXrange1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_XRANGE1", arg_desc=(("xrange_low", expression.subnode_low),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, none_null=True, ) def generateBuiltinXrange2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_XRANGE2", arg_desc=( ("xrange_low", expression.subnode_low), ("xrange_high", expression.subnode_high), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, none_null=True, ) def generateBuiltinXrange3Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_XRANGE3", arg_desc=( ("xrange_low", expression.subnode_low), ("xrange_high", expression.subnode_high), ("xrange_step", expression.subnode_step), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, none_null=True, ) def generateBuiltinFloatCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="TO_FLOAT", arg_desc=(("float_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinComplex1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_COMPLEX1", arg_desc=(("real_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinComplex2Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_COMPLEX2", arg_desc=( ("real_arg", expression.subnode_real), ("imag_arg", expression.subnode_imag), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinBoolCode(to_name, expression, emit, context): (arg_name,) = generateChildExpressionsCode( expression=expression, emit=emit, context=context ) res_name = context.getIntResName() emit("%s = CHECK_IF_TRUE(%s);" % (res_name, arg_name)) getErrorExitBoolCode( condition="%s == -1" % res_name, release_name=arg_name, needs_check=expression.mayRaiseException(BaseException), emit=emit, context=context, ) to_name.getCType().emitAssignmentCodeFromBoolCondition( to_name=to_name, condition="%s != 0" % res_name, emit=emit ) def generateBuiltinBinCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_BIN", arg_desc=(("bin_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinOctCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_OCT", arg_desc=(("oct_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinHexCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_HEX", arg_desc=(("hex_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinBytearray1Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_BYTEARRAY1", arg_desc=(("bytearray_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinBytearray3Code(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_BYTEARRAY3", arg_desc=( ("bytearray_string", expression.subnode_string), ("bytearray_encoding", expression.subnode_encoding), ("bytearray_errors", expression.subnode_errors), ), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), none_null=True, emit=emit, context=context, ) def generateBuiltinStaticmethodCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_STATICMETHOD", arg_desc=(("staticmethod_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) def generateBuiltinClassmethodCode(to_name, expression, emit, context): generateCAPIObjectCode( to_name=to_name, capi="BUILTIN_CLASSMETHOD", arg_desc=(("classmethod_arg", expression.subnode_value),), may_raise=expression.mayRaiseException(BaseException), conversion_check=decideConversionCheckNeeded(to_name, expression), source_ref=expression.getCompatibleSourceReference(), emit=emit, context=context, ) Nuitka-0.6.19.1/nuitka/codegen/LoopCodes.py0000600000372100037210000000607714166627112025441 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Loop codes. Code generation for loops, breaking them, or continuing them. In Nuitka, there are no for-loops or while-loops at this point. They have been re-formulated in a simpler loop without a condition, and statements there-in that break under certain conditions. See Developer Manual for how the CPython loops are mapped to these nodes. """ from .CodeHelpers import generateStatementSequenceCode from .ErrorCodes import getErrorExitBoolCode from .ExceptionCodes import getExceptionUnpublishedReleaseCode from .LabelCodes import getGotoCode, getLabelCode def generateLoopBreakCode(statement, emit, context): # Functions used for generation all accept statement, but this one does # not use it. pylint: disable=unused-argument getExceptionUnpublishedReleaseCode(emit, context) break_target = context.getLoopBreakTarget() getGotoCode(break_target, emit) def generateLoopContinueCode(statement, emit, context): # Functions used for generation all accept statement, but this one does # not use it. pylint: disable=unused-argument getExceptionUnpublishedReleaseCode(emit, context) continue_target = context.getLoopContinueTarget() getGotoCode(continue_target, emit) def generateLoopCode(statement, emit, context): loop_start_label = context.allocateLabel("loop_start") if not statement.isStatementAborting(): loop_end_label = context.allocateLabel("loop_end") else: loop_end_label = None getLabelCode(loop_start_label, emit) old_loop_break = context.setLoopBreakTarget(loop_end_label) old_loop_continue = context.setLoopContinueTarget(loop_start_label) generateStatementSequenceCode( statement_sequence=statement.subnode_loop_body, allow_none=True, emit=emit, context=context, ) context.setLoopBreakTarget(old_loop_break) context.setLoopContinueTarget(old_loop_continue) # Note: We are using the wrong line here, but it's an exception, it's unclear what line it would be anyway. with context.withCurrentSourceCodeReference(statement.getSourceReference()): getErrorExitBoolCode( condition="CONSIDER_THREADING() == false", emit=emit, context=context ) getGotoCode(loop_start_label, emit) if loop_end_label is not None: getLabelCode(loop_end_label, emit) Nuitka-0.6.19.1/nuitka/codegen/ModuleCodes.py0000600000372100037210000001421114166627112025742 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code to generate and interact with compiled module objects. """ from nuitka import Options from nuitka.__past__ import iterItems from nuitka.codegen import Emission from nuitka.Version import getNuitkaVersion, getNuitkaVersionYear from .CodeHelpers import ( decideConversionCheckNeeded, generateStatementSequenceCode, withObjectCodeTemporaryAssignment, ) from .CodeObjectCodes import getCodeObjectsDeclCode, getCodeObjectsInitCode from .Indentation import indented from .templates.CodeTemplatesModules import ( template_global_copyright, template_module_body_template, template_module_exception_exit, template_module_external_entry_point, template_module_noexception_exit, ) from .VariableCodes import getVariableReferenceCode def getModuleAccessCode(context): return "module_%s" % context.getModuleCodeName() def getModuleCode( module, function_decl_codes, function_body_codes, module_const_blob_name, context ): # For the module code, lots of arguments and attributes come together. # pylint: disable=too-many-locals # Temporary variable initializations # TODO: Move that to a place outside of functions. from .FunctionCodes import ( finalizeFunctionLocalVariables, setupFunctionLocalVariables, ) setupFunctionLocalVariables( context=context, parameters=None, closure_variables=(), user_variables=module.getOutlineLocalVariables(), temp_variables=module.getTempVariables(), ) module_codes = Emission.SourceCodeCollector() module = context.getOwner() module_body = module.subnode_body generateStatementSequenceCode( statement_sequence=module_body, emit=module_codes, allow_none=True, context=context, ) for _identifier, code in sorted(iterItems(context.getHelperCodes())): function_body_codes.append(code) for _identifier, code in sorted(iterItems(context.getDeclarations())): function_decl_codes.append(code) function_body_codes = "\n\n".join(function_body_codes) function_decl_codes = "\n\n".join(function_decl_codes) _cleanup = finalizeFunctionLocalVariables(context) # TODO: Seems like a bug, classes could produce those. # assert not _cleanup, _cleanup module_identifier = module.getCodeName() if module_body is not None and module_body.mayRaiseException(BaseException): module_exit = template_module_exception_exit % { "module_identifier": module_identifier, "is_top": 1 if module.isTopModule() else 0, } else: module_exit = template_module_noexception_exit local_var_inits = context.variable_storage.makeCFunctionLevelDeclarations() function_table_entries_decl = [] for func_impl_identifier in context.getFunctionCreationInfos(): function_table_entries_decl.append("%s," % func_impl_identifier) module_name = module.getFullName() is_package = module.isCompiledPythonPackage() is_top = module.isTopModule() module_identifier = module.getCodeName() template = template_global_copyright + template_module_body_template if is_top == 1 and Options.shallMakeModule(): template += template_module_external_entry_point module_code_objects_decl = getCodeObjectsDeclCode(context) module_code_objects_init = getCodeObjectsInitCode(context) is_dunder_main = module.isMainModule() dunder_main_package = context.getConstantCode( module.getRuntimePackageValue() if is_dunder_main else "" ) return template % { "module_name": module_name, "version": getNuitkaVersion(), "year": getNuitkaVersionYear(), "is_top": 1 if module.isTopModule() else 0, "is_dunder_main": 1 if is_dunder_main else 0, "dunder_main_package": dunder_main_package, "is_package": 1 if is_package else 0, "module_identifier": module_identifier, "module_functions_decl": function_decl_codes, "module_functions_code": function_body_codes, "module_function_table_entries": indented(function_table_entries_decl), "temps_decl": indented(local_var_inits), "module_code": indented(module_codes.codes), "module_exit": module_exit, "module_code_objects_decl": indented(module_code_objects_decl, 0), "module_code_objects_init": indented(module_code_objects_init, 1), "constants_count": context.getConstantsCount(), "module_const_blob_name": module_const_blob_name, } def generateModuleAttributeFileCode(to_name, expression, emit, context): # TODO: Special treatment justified? with withObjectCodeTemporaryAssignment( to_name, "module_fileattr_value", expression, emit, context ) as result_name: emit("%s = module_filename_obj;" % result_name) def generateModuleAttributeCode(to_name, expression, emit, context): getVariableReferenceCode( to_name=to_name, variable=expression.getVariable(), variable_trace=None, needs_check=False, conversion_check=decideConversionCheckNeeded(to_name, expression), emit=emit, context=context, ) def generateNuitkaLoaderCreationCode(to_name, expression, emit, context): with withObjectCodeTemporaryAssignment( to_name, "nuitka_loader_value", expression, emit, context ) as result_name: emit("%s = Nuitka_Loader_New(loader_entry);" % result_name) Nuitka-0.6.19.1/nuitka/codegen/VariableCodes.py0000600000372100037210000003463014166627112026251 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Low level variable code generation. """ from nuitka.nodes.shapes.BuiltinTypeShapes import ( tshape_bool, tshape_int_or_long, ) from nuitka.PythonVersions import python_version from .c_types.CTypeNuitkaBools import CTypeNuitkaBoolEnum from .c_types.CTypePyObjectPtrs import ( CTypeCellObject, CTypePyObjectPtr, CTypePyObjectPtrPtr, ) from .CodeHelpers import ( decideConversionCheckNeeded, generateExpressionCode, withObjectCodeTemporaryAssignment2, ) from .ErrorCodes import ( getAssertionCode, getErrorExitCode, getLocalVariableReferenceErrorCode, getNameReferenceErrorCode, ) from .VariableDeclarations import VariableDeclaration def generateAssignmentVariableCode(statement, emit, context): assign_source = statement.subnode_source variable = statement.getVariable() variable_trace = statement.getVariableTrace() if variable.isModuleVariable(): # Use "object" for module variables. tmp_name = context.allocateTempName("assign_source") else: source_shape = assign_source.getTypeShape() variable_declaration = getLocalVariableDeclaration( context, variable, variable_trace ) if source_shape is tshape_bool and variable_declaration.c_type == "nuitka_bool": tmp_name = context.allocateTempName("assign_source", "nuitka_bool") elif ( source_shape is tshape_int_or_long and variable_declaration.c_type == "nuitka_ilong" ): tmp_name = context.allocateTempName("assign_source", "nuitka_ilong") else: tmp_name = context.allocateTempName("assign_source") generateExpressionCode( expression=assign_source, to_name=tmp_name, emit=emit, context=context ) getVariableAssignmentCode( tmp_name=tmp_name, variable=variable, variable_trace=variable_trace, needs_release=statement.needsReleasePreviousValue(), in_place=statement.isInplaceSuspect(), emit=emit, context=context, ) # Ownership of that reference must have been transferred. assert not context.needsCleanup(tmp_name) def generateDelVariableCode(statement, emit, context): with context.withCurrentSourceCodeReference(statement.getSourceReference()): _getVariableDelCode( variable=statement.getVariable(), variable_trace=statement.variable_trace, previous_trace=statement.previous_trace, tolerant=statement.isTolerant(), needs_check=statement.isTolerant() or statement.mayRaiseException(BaseException), emit=emit, context=context, ) def getVariableReferenceCode( to_name, variable, variable_trace, needs_check, conversion_check, emit, context ): if variable.isModuleVariable(): owner = context.getOwner() with withObjectCodeTemporaryAssignment2( to_name, "mvar_value", conversion_check, emit, context ) as value_name: # TODO: Rather have this passed from a distinct node type, so inlining # doesn't change things. emit( """\ %(value_name)s = GET_STRING_DICT_VALUE(moduledict_%(module_identifier)s, (Nuitka_StringObject *)%(var_name)s); if (unlikely(%(value_name)s == NULL)) { %(value_name)s = %(helper_code)s(%(var_name)s); } """ % { "helper_code": "GET_MODULE_VARIABLE_VALUE_FALLBACK_IN_FUNCTION" if python_version < 0x340 and not owner.isCompiledPythonModule() and not owner.isExpressionClassBody() else "GET_MODULE_VARIABLE_VALUE_FALLBACK", "module_identifier": context.getModuleCodeName(), "value_name": value_name, "var_name": context.getConstantCode(constant=variable.getName()), } ) getErrorExitCode( check_name=value_name, emit=emit, context=context, needs_check=needs_check, ) else: variable_declaration = getLocalVariableDeclaration( context, variable, variable_trace ) value_name = variable_declaration.getCType().emitValueAccessCode( value_name=variable_declaration, emit=emit, context=context ) if needs_check: condition = value_name.getCType().getInitTestConditionCode( value_name, inverted=True ) getLocalVariableReferenceErrorCode( variable=variable, condition=condition, emit=emit, context=context ) else: value_name.getCType().emitValueAssertionCode( value_name=value_name, emit=emit ) to_name.getCType().emitAssignConversionCode( to_name=to_name, value_name=value_name, needs_check=conversion_check, emit=emit, context=context, ) def generateVariableReferenceCode(to_name, expression, emit, context): variable = expression.getVariable() variable_trace = expression.getVariableTrace() needs_check = expression.mayRaiseException(BaseException) getVariableReferenceCode( to_name=to_name, variable=variable, variable_trace=variable_trace, needs_check=needs_check, conversion_check=decideConversionCheckNeeded(to_name, expression), emit=emit, context=context, ) def _getVariableCodeName(in_context, variable): if in_context: # Closure case: return "closure_" + variable.getCodeName() elif variable.isParameterVariable(): return "par_" + variable.getCodeName() elif variable.isTempVariable(): return "tmp_" + variable.getCodeName() else: return "var_" + variable.getCodeName() def getPickedCType(variable, context): """Return type to use for specific context.""" user = context.getEntryPoint() owner = variable.getEntryPoint() if owner is user: if variable.isSharedTechnically(): # TODO: That need not really be an impedient, we could share pointers to # everything. result = CTypeCellObject else: shapes = variable.getTypeShapes() if len(shapes) > 1: # Avoiding this for now, but we will have to use our enum # based code variants, either generated or hard coded in # the future. if len(shapes) > 1: return CTypePyObjectPtr r = shapes.pop().getCType() return r elif context.isForDirectCall(): if variable.isSharedTechnically(): result = CTypeCellObject else: result = CTypePyObjectPtrPtr else: result = CTypeCellObject return result def decideLocalVariableCodeType(context, variable): # Now must be local or temporary variable. # Complexity should be moved out of here, pylint: disable=too-many-branches user = context.getOwner() owner = variable.getOwner() user = user.getEntryPoint() prefix = "" if owner.isExpressionOutlineFunctionBase(): entry_point = owner.getEntryPoint() prefix = ( "outline_%d_" % entry_point.getTraceCollection().getOutlineFunctions().index(owner) ) owner = entry_point if variable.isTempVariableBool(): c_type = CTypeNuitkaBoolEnum else: c_type = getPickedCType(variable, context) if owner is user: result = _getVariableCodeName(in_context=False, variable=variable) result = prefix + result elif context.isForDirectCall(): if user.isExpressionGeneratorObjectBody(): closure_index = user.getClosureVariableIndex(variable) result = "generator->m_closure[%d]" % closure_index elif user.isExpressionCoroutineObjectBody(): closure_index = user.getClosureVariableIndex(variable) result = "coroutine->m_closure[%d]" % closure_index elif user.isExpressionAsyncgenObjectBody(): closure_index = user.getClosureVariableIndex(variable) result = "asyncgen->m_closure[%d]" % closure_index else: result = _getVariableCodeName(in_context=True, variable=variable) result = prefix + result else: closure_index = user.getClosureVariableIndex(variable) if user.isExpressionGeneratorObjectBody(): result = "generator->m_closure[%d]" % closure_index elif user.isExpressionCoroutineObjectBody(): result = "coroutine->m_closure[%d]" % closure_index elif user.isExpressionAsyncgenObjectBody(): result = "asyncgen->m_closure[%d]" % closure_index else: # TODO: If this were context.getContextObjectName() this would be # a one liner. result = "self->m_closure[%d]" % closure_index return result, c_type def getLocalVariableDeclaration(context, variable, variable_trace): # TODO: Decide if we will use variable trace, pylint: disable=unused-argument # Now must be local or temporary variable. user = context.getOwner() owner = variable.getOwner() user = user.getEntryPoint() prefix = "" if owner.isExpressionOutlineFunctionBase(): entry_point = owner.getEntryPoint() prefix = ( "outline_%d_" % entry_point.getTraceCollection().getOutlineFunctions().index(owner) ) owner = entry_point if owner is user: result = _getVariableCodeName(in_context=False, variable=variable) result = prefix + result result = context.variable_storage.getVariableDeclarationTop(result) assert result is not None, variable return result else: closure_index = user.getClosureVariableIndex(variable) return context.variable_storage.getVariableDeclarationClosure(closure_index) def getVariableAssignmentCode( context, emit, variable, variable_trace, tmp_name, needs_release, in_place ): # For transfer of ownership. if context.needsCleanup(tmp_name): ref_count = 1 else: ref_count = 0 if variable.isModuleVariable(): variable_declaration = VariableDeclaration( "module_var", variable.getName(), None, None ) else: variable_declaration = getLocalVariableDeclaration( context, variable, variable_trace ) assert variable_declaration, (variable, context) if variable.isLocalVariable(): context.setVariableType(variable, variable_declaration) variable_declaration.getCType().emitVariableAssignCode( value_name=variable_declaration, needs_release=needs_release, tmp_name=tmp_name, ref_count=ref_count, in_place=in_place, emit=emit, context=context, ) if ref_count: context.removeCleanupTempName(tmp_name) def _getVariableDelCode( variable, variable_trace, previous_trace, tolerant, needs_check, emit, context ): if variable.isModuleVariable(): variable_declaration_old = VariableDeclaration( "module_var", variable.getName(), None, None ) variable_declaration_new = variable_declaration_old else: variable_declaration_old = getLocalVariableDeclaration( context, variable, previous_trace ) variable_declaration_new = getLocalVariableDeclaration( context, variable, variable_trace ) # TODO: We need to split this operation in two parts. Release and init # are not one thing, until then require this. assert variable_declaration_old == variable_declaration_new if variable.isLocalVariable(): context.setVariableType(variable, variable_declaration_new) if needs_check and not tolerant: to_name = context.getBoolResName() else: to_name = None variable_declaration_old.getCType().getDeleteObjectCode( to_name=to_name, value_name=variable_declaration_old, tolerant=tolerant, needs_check=needs_check, emit=emit, context=context, ) if needs_check and not tolerant: if variable.isModuleVariable(): getNameReferenceErrorCode( variable_name=variable.getName(), condition="%s == false" % to_name, emit=emit, context=context, ) elif variable.isLocalVariable(): getLocalVariableReferenceErrorCode( variable=variable, condition="%s == false" % to_name, emit=emit, context=context, ) else: getAssertionCode(check="%s != false" % to_name, emit=emit) def generateVariableReleaseCode(statement, emit, context): variable = statement.getVariable() # Only for normal variables we do this. assert not variable.isModuleVariable() variable_trace = statement.getVariableTrace() if variable.isSharedTechnically(): # TODO: We might start to not allocate the cell object, then a check # would be due. But currently we always allocate it. needs_check = False else: needs_check = not variable_trace.mustHaveValue() value_name = getLocalVariableDeclaration(context, variable, variable_trace) c_type = value_name.getCType() if not needs_check: c_type.emitReleaseAssertionCode(value_name=value_name, emit=emit) c_type.getReleaseCode(value_name=value_name, needs_check=needs_check, emit=emit) c_type.emitReinitCode(value_name=value_name, emit=emit) Nuitka-0.6.19.1/nuitka/ModuleRegistry.py0000600000372100037210000001455614166627112025125 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This to keep track of used modules. There is a set of root modules, which are user specified, and must be processed. As they go, they add more modules to active modules list and move done modules out of it. That process can be restarted and modules will be fetched back from the existing set of modules. """ import collections import os from nuitka.containers.oset import OrderedSet from nuitka.PythonVersions import python_version from nuitka.utils.FileOperations import areSamePaths # One or more root modules, i.e. entry points that must be there. root_modules = OrderedSet() # To be traversed modules active_modules = OrderedSet() # Information about why a module became active. active_modules_info = {} ActiveModuleInfo = collections.namedtuple( "ActiveModuleInfo", ("using_module", "usage_tag", "reason", "source_ref") ) # Already traversed modules done_modules = set() # Uncompiled modules uncompiled_modules = set() def addRootModule(module): root_modules.add(module) def getRootModules(): return root_modules def getRootTopModule(): top_module = next(iter(root_modules)) assert top_module.isTopModule(), top_module return top_module def hasRootModule(module_name): for module in root_modules: if module.getFullName() == module_name: return True return False def replaceRootModule(old, new): # Using global here, as this is really a singleton, in the form of a module, # pylint: disable=global-statement global root_modules new_root_modules = OrderedSet() for module in root_modules: new_root_modules.add(module if module is not old else new) root_modules = new_root_modules def addUncompiledModule(module): uncompiled_modules.add(module) def getUncompiledModules(): return sorted(uncompiled_modules, key=lambda module: module.getFullName()) def getUncompiledTechnicalModules(): result = [module for module in uncompiled_modules if module.isTechnical()] return sorted(result, key=lambda module: module.getFullName()) def getUncompiledNonTechnicalModules(): result = [module for module in uncompiled_modules if not module.isTechnical()] return sorted(result, key=lambda module: module.getFullName()) def _normalizeModuleFilename(filename): if python_version >= 0x300: filename = filename.replace("__pycache__", "") suffix = ".cpython-%d.pyc" % (python_version // 10) if filename.endswith(suffix): filename = filename[: -len(suffix)] + ".py" else: if filename.endswith(".pyc"): filename = filename[:-3] + ".py" if os.path.basename(filename) == "__init__.py": filename = os.path.dirname(filename) return filename def getUncompiledModule(module_name, module_filename): for uncompiled_module in uncompiled_modules: if module_name == uncompiled_module.getFullName(): if areSamePaths( _normalizeModuleFilename(module_filename), _normalizeModuleFilename(uncompiled_module.filename), ): return uncompiled_module return None def removeUncompiledModule(module): uncompiled_modules.remove(module) def startTraversal(): # Using global here, as this is really a singleton, in the form of a module, # pylint: disable=global-statement global active_modules, done_modules, active_modules_info active_modules = OrderedSet(root_modules) active_modules_info = {} for root_module in root_modules: active_modules_info[root_module] = ActiveModuleInfo( using_module=None, usage_tag="root_module", reason="Root module", source_ref=None, ) done_modules = set() for active_module in active_modules: active_module.startTraversal() def addUsedModule(module, using_module, usage_tag, reason, source_ref): if module not in done_modules and module not in active_modules: active_modules.add(module) active_modules_info[module] = ActiveModuleInfo( using_module=using_module, usage_tag=usage_tag, reason=reason, source_ref=source_ref, ) module.startTraversal() def nextModule(): if active_modules: result = active_modules.pop() done_modules.add(result) return result else: return None def getRemainingModulesCount(): return len(active_modules) def getDoneModulesCount(): return len(done_modules) def getDoneModules(): return sorted(done_modules, key=lambda module: (module.getFullName(), module.kind)) def getModuleInclusionInfos(): return active_modules_info def removeDoneModule(module): done_modules.remove(module) def getModuleFromCodeName(code_name): # TODO: We need something to just load modules. for module in root_modules: if module.getCodeName() == code_name: return module assert False, code_name def getOwnerFromCodeName(code_name): if "$$$" in code_name: module_code_name, _function_code_name = code_name.split("$$$", 1) module = getModuleFromCodeName(module_code_name) return module.getFunctionFromCodeName(code_name) else: return getModuleFromCodeName(code_name) def getModuleByName(module_name): for module in active_modules: if module.getFullName() == module_name: return module for module in done_modules: if module.getFullName() == module_name: return module for module in uncompiled_modules: if module.getFullName() == module_name: return module return None Nuitka-0.6.19.1/nuitka/PostProcessing.py0000600000372100037210000003331214166627112025120 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Postprocessing tasks for create binaries or modules. """ import ctypes import os import sys from nuitka import Options, OutputDirectories from nuitka.build.DataComposerInterface import getConstantBlobFilename from nuitka.finalizations.FinalizeMarkups import getImportedNames from nuitka.PythonVersions import ( getPythonABI, getTargetPythonDLLPath, python_version, python_version_str, ) from nuitka.Tracing import postprocessing_logger from nuitka.utils.FileOperations import ( getExternalUsePath, getFileContents, makePath, putTextFileContents, removeFileExecutablePermission, ) from nuitka.utils.Images import convertImageToIconFormat from nuitka.utils.MacOSApp import createPlistInfoFile from nuitka.utils.SharedLibraries import callInstallNameTool from nuitka.utils.Utils import isMacOS, isWin32Windows from nuitka.utils.WindowsResources import ( RT_GROUP_ICON, RT_ICON, RT_RCDATA, addResourceToFile, addVersionInfoResource, convertStructureToBytes, copyResourcesFromFileToFile, getDefaultWindowsExecutableManifest, getWindowsExecutableManifest, ) class IconDirectoryHeader(ctypes.Structure): _fields_ = [ ("reserved", ctypes.c_short), ("type", ctypes.c_short), ("count", ctypes.c_short), ] class IconDirectoryEntry(ctypes.Structure): _fields_ = [ ("width", ctypes.c_char), ("height", ctypes.c_char), ("colors", ctypes.c_char), ("reserved", ctypes.c_char), ("planes", ctypes.c_short), ("bit_count", ctypes.c_short), ("image_size", ctypes.c_int), ("image_offset", ctypes.c_int), ] class IconGroupDirectoryEntry(ctypes.Structure): # Make sure the don't have padding issues. _pack_ = 2 _fields_ = ( ("width", ctypes.c_char), ("height", ctypes.c_char), ("colors", ctypes.c_char), ("reserved", ctypes.c_char), ("planes", ctypes.c_short), ("bit_count", ctypes.c_short), ("image_size", ctypes.c_int), ("id", ctypes.c_short), ) def readFromFile(readable, c_struct): """Read ctypes structures from input.""" result = c_struct() chunk = readable.read(ctypes.sizeof(result)) ctypes.memmove(ctypes.byref(result), chunk, ctypes.sizeof(result)) return result def _addWindowsIconFromIcons(onefile): # Relatively detailed handling, pylint: disable=too-many-locals icon_group = 1 image_id = 1 images = [] result_filename = OutputDirectories.getResultFullpath(onefile=onefile) for icon_spec in Options.getIconPaths(): if "#" in icon_spec: icon_path, icon_index = icon_spec.rsplit("#", 1) icon_index = int(icon_index) else: icon_path = icon_spec icon_index = None icon_path = os.path.normcase(icon_path) if not icon_path.endswith(".ico"): postprocessing_logger.info( "File '%s' is not in Windows icon format, converting to it." % icon_path ) if icon_index is not None: postprocessing_logger.sysexit( "Cannot specify indexes with non-ico format files in '%s'." % icon_spec ) icon_build_path = os.path.join( OutputDirectories.getSourceDirectoryPath(onefile=onefile), "icons", ) makePath(icon_build_path) converted_icon_path = os.path.join( icon_build_path, "icon-%d.ico" % image_id, ) convertImageToIconFormat( logger=postprocessing_logger, image_filename=icon_spec, icon_filename=converted_icon_path, ) icon_path = converted_icon_path with open(icon_path, "rb") as icon_file: # Read header and icon entries. header = readFromFile(icon_file, IconDirectoryHeader) icons = [ readFromFile(icon_file, IconDirectoryEntry) for _i in range(header.count) ] if icon_index is not None: if icon_index > len(icons): postprocessing_logger.sysexit( "Error, referenced icon index %d in file '%s' with only %d icons." % (icon_index, icon_path, len(icons)) ) icons[:] = icons[icon_index : icon_index + 1] postprocessing_logger.info( "Adding %d icon(s) from icon file '%s'." % (len(icons), icon_spec) ) # Image data are to be scanned from places specified icon entries for icon in icons: icon_file.seek(icon.image_offset, 0) images.append(icon_file.read(icon.image_size)) parts = [convertStructureToBytes(header)] for icon in icons: parts.append( convertStructureToBytes( IconGroupDirectoryEntry( width=icon.width, height=icon.height, colors=icon.colors, reserved=icon.reserved, planes=icon.planes, bit_count=icon.bit_count, image_size=icon.image_size, id=image_id, ) ) ) image_id += 1 addResourceToFile( target_filename=result_filename, data=b"".join(parts), resource_kind=RT_GROUP_ICON, lang_id=0, res_name=icon_group, logger=postprocessing_logger, ) for count, image in enumerate(images, 1): addResourceToFile( target_filename=result_filename, data=image, resource_kind=RT_ICON, lang_id=0, res_name=count, logger=postprocessing_logger, ) version_resources = {} def executePostProcessingResources(manifest, onefile): """Adding Windows resources to the binary. Used for both onefile and not onefile binary, potentially two times. """ result_filename = OutputDirectories.getResultFullpath(onefile=onefile) if manifest is None: manifest = getDefaultWindowsExecutableManifest() if Options.shallAskForWindowsAdminRights(): manifest.addUacAdmin() if Options.shallAskForWindowsUIAccessRights(): manifest.addUacUiAccess() manifest.addResourceToFile(result_filename, logger=postprocessing_logger) if ( Options.getWindowsVersionInfoStrings() or Options.getWindowsProductVersion() or Options.getWindowsFileVersion() ): version_resources.update( addVersionInfoResource( string_values=Options.getWindowsVersionInfoStrings(), product_version=Options.getWindowsProductVersion(), file_version=Options.getWindowsFileVersion(), file_date=(0, 0), is_exe=not Options.shallMakeModule(), result_filename=result_filename, logger=postprocessing_logger, ) ) # Attach icons from template file if given. template_exe = Options.getWindowsIconExecutablePath() if template_exe is not None: res_copied = copyResourcesFromFileToFile( template_exe, target_filename=result_filename, resource_kinds=(RT_ICON, RT_GROUP_ICON), ) if res_copied == 0: postprocessing_logger.warning( "The specified icon template executable %r didn't contain anything to copy." % template_exe ) else: postprocessing_logger.warning( "Copied %d icon resources from %r." % (res_copied, template_exe) ) else: _addWindowsIconFromIcons(onefile=onefile) splash_screen_filename = Options.getWindowsSplashScreen() if splash_screen_filename is not None: splash_data = getFileContents(splash_screen_filename, mode="rb") addResourceToFile( target_filename=result_filename, data=splash_data, resource_kind=RT_RCDATA, lang_id=0, res_name=27, logger=postprocessing_logger, ) def executePostProcessing(): """Postprocessing of the resulting binary. These are in part required steps, not usable after failure. """ result_filename = OutputDirectories.getResultFullpath(onefile=False) if not os.path.exists(result_filename): postprocessing_logger.sysexit( "Error, scons failed to create the expected file %r. " % result_filename ) if isWin32Windows(): if not Options.shallMakeModule(): if python_version < 0x300: # Copy the Windows manifest from the CPython binary to the created # executable, so it finds "MSCRT.DLL". This is needed for Python2 # only, for Python3 newer MSVC doesn't hide the C runtime. manifest = getWindowsExecutableManifest(sys.executable) else: manifest = None executePostProcessingResources(manifest=manifest, onefile=False) source_dir = OutputDirectories.getSourceDirectoryPath() # Attach the binary blob as a Windows resource. addResourceToFile( target_filename=result_filename, data=getFileContents(getConstantBlobFilename(source_dir), "rb"), resource_kind=RT_RCDATA, res_name=3, lang_id=0, logger=postprocessing_logger, ) # On macOS, we update the executable path for searching the "libpython" # library. if ( isMacOS() and not Options.shallMakeModule() and not Options.shallUseStaticLibPython() ): python_abi_version = python_version_str + getPythonABI() python_dll_filename = "libpython" + python_abi_version + ".dylib" python_lib_path = os.path.join(sys.prefix, "lib") # Note: For CPython and potentially others, the rpath for the Python # library needs to be set. callInstallNameTool( filename=result_filename, mapping=( ( python_dll_filename, os.path.join(python_lib_path, python_dll_filename), ), ( "@rpath/Python3.framework/Versions/%s/Python3" % python_version_str, os.path.join(python_lib_path, python_dll_filename), ), ), rpath=python_lib_path, ) if isMacOS() and Options.shallCreateAppBundle(): createPlistInfoFile(logger=postprocessing_logger, onefile=False) # Modules should not be executable, but Scons creates them like it, fix # it up here. if not isWin32Windows() and Options.shallMakeModule(): removeFileExecutablePermission(result_filename) if isWin32Windows() and Options.shallMakeModule(): candidate = os.path.join( os.path.dirname(result_filename), "lib" + os.path.basename(result_filename)[:-4] + ".a", ) if os.path.exists(candidate): os.unlink(candidate) if isWin32Windows() and Options.shallTreatUninstalledPython(): dll_directory = getExternalUsePath(os.path.dirname(getTargetPythonDLLPath())) cmd_filename = OutputDirectories.getResultRunFilename(onefile=False) cmd_contents = """ @echo off rem This script was created by Nuitka to execute '%(exe_filename)s' with Python DLL being found. set PATH=%(dll_directory)s;%%PATH%% set PYTHONHOME=%(dll_directory)s "%%~dp0.\\%(exe_filename)s" %%* """ % { "dll_directory": dll_directory, "exe_filename": os.path.basename(result_filename), } putTextFileContents(cmd_filename, cmd_contents) # Create a ".pyi" file for created modules if Options.shallMakeModule() and Options.shallCreatePyiFile(): pyi_filename = OutputDirectories.getResultBasepath() + ".pyi" putTextFileContents( filename=pyi_filename, contents="""\ # This file was generated by Nuitka and describes the types of the # created shared library. # At this time it lists only the imports made and can be used by the # tools that bundle libraries, including Nuitka itself. For instance # standalone mode usage of the created library will need it. # In the future, this will also contain type information for values # in the module, so IDEs will use this. Therefore please include it # when you make software releases of the extension module that it # describes. %(imports)s # This is not Python source even if it looks so. Make it clear for # now. This was decided by PEP 484 designers. __name__ = ... """ % { "imports": "\n".join( "import %s" % module_name for module_name in getImportedNames() ) }, ) Nuitka-0.6.19.1/nuitka/Errors.py0000600000372100037210000000436014166627112023413 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ For enhanced bug reporting, these exceptions should be used. They ideally should point out what it ought to take for reproducing the issue when output. """ class NuitkaErrorBase(Exception): pass class NuitkaNodeError(NuitkaErrorBase): # Try to output more information about nodes passed. def __str__(self): try: from nuitka.codegen.Indentation import indented parts = [""] for arg in self.args: # false alarm, pylint: disable=I0021,not-an-iterable if hasattr(arg, "asXmlText"): parts.append(indented("\n%s\n" % arg.asXmlText())) else: parts.append(str(arg)) parts.append("") parts.append("The above information should be included in a bug report.") return "\n".join(parts) except Exception as e: # Catch all the things, pylint: disable=broad-except return "" % e class NuitkaOptimizationError(NuitkaNodeError): pass class NuitkaAssumptionError(AssertionError): pass class NuitkaCodeDeficit(NuitkaErrorBase): pass class NuitkaNodeDesignError(Exception): pass class NuitkaForbiddenImportEncounter(Exception): pass class CodeTooComplexCode(Exception): """The code of the module is too complex. It cannot be compiled, with recursive code, and therefore the bytecode should be used instead. Example of this is "idnadata". """ Nuitka-0.6.19.1/nuitka/nodes/0000700000372100037210000000000014167275622022676 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/nodes/YieldNodes.py0000600000372100037210000001023014166627112025277 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Yield node. The yield node returns to the caller of the generator and therefore may execute absolutely arbitrary code, from the point of view of this code. It then returns something, which may often be 'None', but doesn't have to be. TODO: Often it will be used as a statement, which may also be reflected in a dedicated node to save a bit of memory. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildHavingBase class ExpressionYieldBase(ExpressionChildHavingBase): if python_version >= 0x300: __slots__ = ("exception_preserving",) else: __slots__ = () def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) if python_version >= 0x300: self.exception_preserving = False if python_version >= 0x300: def markAsExceptionPreserving(self): self.exception_preserving = True def isExceptionPreserving(self): return self.exception_preserving else: @staticmethod def isExceptionPreserving(): return False def computeExpression(self, trace_collection): # TODO: That's actually only needed if the value is mutable. trace_collection.removeKnowledge(self.subnode_expression) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) # Nothing possible really here. return self, None, None class ExpressionYield(ExpressionYieldBase): """Yielding an expression. Typical code: yield expression Can only happen in a generator. Kind of explicitly suspends and resumes the execution. The user may inject any kind of exception or give any return value. The value of "None" is the most common though, esp. if it's not used. """ kind = "EXPRESSION_YIELD" named_child = "expression" def __init__(self, expression, source_ref): ExpressionYieldBase.__init__(self, value=expression, source_ref=source_ref) class ExpressionYieldFrom(ExpressionYieldBase): """Yielding from an expression. Typical code: yield from expression (Python3) Can only happen in a generator and only in Python3. Similar to yield, but implies a loop and exception propagation to the yield from generator if such. Kind of explicitly suspends and resumes the execution. The user may inject any kind of exception or give any return value. Having a return value is what makes Python3 generators special, and with yield from, that value is the expression result. """ kind = "EXPRESSION_YIELD_FROM" named_child = "expression" def __init__(self, expression, source_ref): ExpressionYieldBase.__init__(self, value=expression, source_ref=source_ref) class ExpressionYieldFromWaitable(ExpressionYieldBase): """Yielding from an expression. Typical code: await x, async for ..., async with (Python3.5) Can only happen in a coroutine or asyncgen and only in Python3.5 or higher. Similar to yield from. The actual lookups of awaitable go through slots and have dedicated nodes. """ kind = "EXPRESSION_YIELD_FROM_WAITABLE" named_child = "expression" def __init__(self, expression, source_ref): ExpressionYieldBase.__init__(self, value=expression, source_ref=source_ref) Nuitka-0.6.19.1/nuitka/nodes/BuiltinComplexNodes.py0000600000372100037210000000441014166627112027172 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'complex' built-in. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionSpecBasedComputationMixin, ) from .ExpressionShapeMixins import ExpressionComplexShapeExactMixin class ExpressionBuiltinComplex1( ExpressionComplexShapeExactMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_BUILTIN_COMPLEX1" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) def computeExpression(self, trace_collection): value = self.subnode_value return value.computeExpressionComplex( complex_node=self, trace_collection=trace_collection ) class ExpressionBuiltinComplex2( ExpressionSpecBasedComputationMixin, ExpressionComplexShapeExactMixin, ExpressionChildrenHavingBase, ): kind = "EXPRESSION_BUILTIN_COMPLEX2" named_children = ("real", "imag") builtin_spec = BuiltinParameterSpecs.builtin_complex_spec def __init__(self, real, imag, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"real": real, "imag": imag}, source_ref=source_ref ) def computeExpression(self, trace_collection): given_values = self.subnode_real, self.subnode_imag return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=given_values ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinFormatNodes.py0000600000372100037210000001173414166627112027022 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Format related nodes format/bin/oct/hex/ascii. These will most often be used for outputs, and the hope is, the type prediction or the result prediction will help to be smarter, but generally these should not be that much about performance critical. """ from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ( ExpressionBuiltinSingleArgBase, ExpressionChildrenHavingBase, ) from .ExpressionShapeMixins import ( ExpressionIntOrLongExactMixin, ExpressionStrOrUnicodeExactMixin, ExpressionStrShapeExactMixin, ) from .NodeMakingHelpers import makeStatementExpressionOnlyReplacementNode class ExpressionBuiltinFormat( ExpressionStrOrUnicodeExactMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_FORMAT" named_children = ("value", "format_spec") # Using slots, they don't need that # pylint: disable=access-member-before-definition,attribute-defined-outside-init def __init__(self, value, format_spec, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"value": value, "format_spec": format_spec}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Can use the format built-in on compile time constants at least. value = self.subnode_value format_spec = self.subnode_format_spec # Go to default way if possible. if format_spec is not None and format_spec.isExpressionConstantStrEmptyRef(): self.subnode_format_spec = None format_spec = None # Strings format themselves as what they are. if format_spec is None: if value.hasShapeStrOrUnicodeExact(): return ( value, "new_expression", """\ Removed useless 'format' on '%s' value.""" % value.getTypeShape().getTypeName(), ) # TODO: Provide "__format__" slot based handling. # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionBuiltinAscii( ExpressionStrShapeExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_ASCII" if python_version >= 0x300: builtin_spec = BuiltinParameterSpecs.builtin_ascii_spec class ExpressionBuiltinBin( ExpressionStrShapeExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_BIN" builtin_spec = BuiltinParameterSpecs.builtin_bin_spec class ExpressionBuiltinOct( ExpressionStrShapeExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_OCT" builtin_spec = BuiltinParameterSpecs.builtin_oct_spec class ExpressionBuiltinHex( ExpressionStrShapeExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_HEX" builtin_spec = BuiltinParameterSpecs.builtin_hex_spec class ExpressionBuiltinId( ExpressionIntOrLongExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_ID" builtin_spec = BuiltinParameterSpecs.builtin_id_spec def computeExpression(self, trace_collection): # Note: Quite impossible to predict the pointer value or anything, but # we know the result will be a long. return self, None, None def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseException(exception_type) def getIntValue(self): return self # TODO: Make use SideEffectsFromChildrenMixin in form of a SideEffectsFromChildMixin def computeExpressionDrop(self, statement, trace_collection): result = makeStatementExpressionOnlyReplacementNode( expression=self.subnode_value, node=self ) del self.parent return ( result, "new_statements", """\ Removed id taking for unused result.""", ) def mayHaveSideEffects(self): return self.subnode_value.mayHaveSideEffects() def extractSideEffects(self): return self.subnode_value.extractSideEffects() Nuitka-0.6.19.1/nuitka/nodes/AsyncgenNodes.py0000600000372100037210000000675014166627112026014 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for async generator objects and their creations. Async generator are turned into normal functions that create generator objects, whose implementation lives here. The creation itself also lives here. """ from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionNoSideEffectsMixin, ) from .FunctionNodes import ExpressionFunctionEntryPointBase class ExpressionMakeAsyncgenObject( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_MAKE_ASYNCGEN_OBJECT" named_child = "asyncgen_ref" __slots__ = ("variable_closure_traces",) def __init__(self, asyncgen_ref, source_ref): assert asyncgen_ref.getFunctionBody().isExpressionAsyncgenObjectBody() ExpressionChildHavingBase.__init__( self, value=asyncgen_ref, source_ref=source_ref ) self.variable_closure_traces = [] def getDetailsForDisplay(self): return {"asyncgen": self.subnode_asyncgen_ref.getFunctionBody().getCodeName()} def computeExpression(self, trace_collection): self.variable_closure_traces = [] for ( closure_variable ) in self.subnode_asyncgen_ref.getFunctionBody().getClosureVariables(): trace = trace_collection.getVariableCurrentTrace(closure_variable) trace.addNameUsage() self.variable_closure_traces.append((closure_variable, trace)) # TODO: Asyncgen body may know something too. return self, None, None def getClosureVariableVersions(self): return self.variable_closure_traces class ExpressionAsyncgenObjectBody(ExpressionFunctionEntryPointBase): kind = "EXPRESSION_ASYNCGEN_OBJECT_BODY" __slots__ = ("qualname_setup", "needs_generator_return_exit") def __init__(self, provider, name, code_object, flags, auto_release, source_ref): ExpressionFunctionEntryPointBase.__init__( self, provider=provider, name=name, code_object=code_object, code_prefix="asyncgen", flags=flags, auto_release=auto_release, source_ref=source_ref, ) self.needs_generator_return_exit = False self.qualname_setup = None def getFunctionName(self): return self.name def markAsNeedsGeneratorReturnHandling(self, value): self.needs_generator_return_exit = max(self.needs_generator_return_exit, value) def needsGeneratorReturnHandling(self): return self.needs_generator_return_exit == 2 def needsGeneratorReturnExit(self): return bool(self.needs_generator_return_exit) @staticmethod def needsCreation(): return False @staticmethod def isUnoptimized(): return False Nuitka-0.6.19.1/nuitka/nodes/BuiltinHashNodes.py0000600000372100037210000000400714166627112026450 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node the calls to the 'hash' built-in. This is a specific thing, which must be calculated at run time, but we can predict things about its type, and the fact that it won't raise an exception for some types, so it is still useful. Also calls to it can be accelerated slightly. """ from .ExpressionBases import ExpressionChildHavingBase class ExpressionBuiltinHash(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_HASH" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) def computeExpression(self, trace_collection): value = self.subnode_value # TODO: Have a computation slot for hashing and specialize for known cases. if not value.isKnownToBeHashable(): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Static raise if it's known not to be hashable. return self, None, None def mayRaiseException(self, exception_type): return ( self.subnode_value.mayRaiseException(exception_type) or not self.subnode_value.isKnownToBeHashable() ) def mayRaiseExceptionOperation(self): return not self.subnode_value.isKnownToBeHashable() Nuitka-0.6.19.1/nuitka/nodes/ModuleNodes.py0000600000372100037210000010206614166627112025467 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module/Package nodes The top of the tree. Packages are also modules. Modules are what hold a program together and cross-module optimizations are the most difficult to tackle. """ import os from nuitka import Options, Variables from nuitka.containers.oset import OrderedSet from nuitka.importing.Importing import ( getModuleNameAndKindFromFilename, locateModule, ) from nuitka.importing.Recursion import decideRecursion, recurseTo from nuitka.ModuleRegistry import getModuleByName, getOwnerFromCodeName from nuitka.optimizations.TraceCollections import TraceCollectionModule from nuitka.PythonVersions import python_version from nuitka.SourceCodeReferences import fromFilename from nuitka.tree.Operations import DetectUsedModules, visitTree from nuitka.tree.SourceReading import readSourceCodeFromFilename from nuitka.utils.CStrings import encodePythonIdentifierToC from nuitka.utils.FileOperations import getFileContentByLine from nuitka.utils.ModuleNames import ModuleName from .Checkers import checkStatementsSequenceOrNone from .FutureSpecs import fromFlags from .IndicatorMixins import EntryPointMixin, MarkNeedsAnnotationsMixin from .LocalsScopes import getLocalsDictHandle from .NodeBases import ( ChildrenHavingMixin, ClosureGiverNodeMixin, NodeBase, extractKindAndArgsFromXML, fromXML, ) class PythonModuleBase(NodeBase): # Base classes can be abstract, pylint: disable=abstract-method __slots__ = ("module_name",) def __init__(self, module_name, source_ref): assert type(module_name) is ModuleName, module_name NodeBase.__init__(self, source_ref=source_ref) self.module_name = module_name def getDetails(self): return {"module_name": self.module_name} def getFullName(self): return self.module_name @staticmethod def isMainModule(): return False @staticmethod def isTopModule(): return False def attemptRecursion(self): # Make sure the package is recursed to if any package_name = self.module_name.getPackageName() if package_name is None: return () # Return the list of newly added modules. package = getModuleByName(package_name) if package_name is not None and package is None: _package_name, package_filename, finding = locateModule( module_name=package_name, parent_package=None, level=1, ) # If we can't find the package for Python3.3 that is semi-OK, it might be in a # namespace package, these have no init code. if python_version >= 0x300 and not package_filename: return () if package_name == "uniconvertor.app.modules": return () assert package_filename is not None, (package_name, finding) _package_name, package_kind = getModuleNameAndKindFromFilename( package_filename ) # assert _package_name == self.package_name, (package_filename, _package_name, self.package_name) decision, _reason = decideRecursion( module_filename=package_filename, module_name=package_name, module_kind=package_kind, ) if decision is not None: package = recurseTo( signal_change=self.trace_collection.signalChange if hasattr(self, "trace_collection") else None, module_name=package_name, module_filename=package_filename, module_kind="py", reason="Containing package of '%s'." % self.getFullName(), ) if package: from nuitka.ModuleRegistry import addUsedModule addUsedModule( package, using_module=self, usage_tag="package", reason="Containing package", source_ref=self.source_ref, ) def getCodeName(self): # Abstract method, pylint: disable=no-self-use return None def getCompileTimeFilename(self): """The compile time filename for the module. Returns: Full path to module file at compile time. Notes: We are getting the absolute path here, since we do not want to have to deal with resolving paths at all. """ return os.path.abspath(self.source_ref.getFilename()) def getCompileTimeDirectory(self): """The compile time directory for the module. Returns: Full path to module directory at compile time. Notes: For packages, we let the package directory be the result, otherwise the containing directory is the result. Notes: Use this to find files nearby a module, mainly in plugin code. """ result = self.getCompileTimeFilename() if not os.path.isdir(result): result = os.path.dirname(result) return result def getRunTimeFilename(self): reference_mode = Options.getFileReferenceMode() if reference_mode == "original": return self.getCompileTimeFilename() elif reference_mode == "frozen": return "" % self.getFullName() else: filename = self.getCompileTimeFilename() full_name = self.getFullName() result = os.path.basename(filename) current = filename levels = full_name.count(".") if self.isCompiledPythonPackage(): levels += 1 for _i in range(levels): current = os.path.dirname(current) result = os.path.join(os.path.basename(current), result) return result class CompiledPythonModule( ChildrenHavingMixin, ClosureGiverNodeMixin, MarkNeedsAnnotationsMixin, EntryPointMixin, PythonModuleBase, ): """Compiled Python Module""" # This one has a few indicators, pylint: disable=too-many-instance-attributes kind = "COMPILED_PYTHON_MODULE" __slots__ = ( "is_top", "name", "code_prefix", "code_name", "uids", "temp_variables", "temp_scopes", "preserver_id", "needs_annotations_dict", "trace_collection", "mode", "variables", "active_functions", "visited_functions", "cross_used_functions", "used_modules", "future_spec", "source_code", "module_dict_name", "locals_scope", ) named_children = ("body", "functions") checkers = {"body": checkStatementsSequenceOrNone} def __init__(self, module_name, is_top, mode, future_spec, source_ref): PythonModuleBase.__init__(self, module_name=module_name, source_ref=source_ref) ClosureGiverNodeMixin.__init__( self, name=module_name.getBasename(), code_prefix="module" ) ChildrenHavingMixin.__init__( self, values={"body": None, "functions": ()} # delayed ) MarkNeedsAnnotationsMixin.__init__(self) EntryPointMixin.__init__(self) self.is_top = is_top self.mode = mode self.variables = {} # Functions that have been used. self.active_functions = OrderedSet() # Functions that should be visited again. self.visited_functions = set() self.cross_used_functions = OrderedSet() self.used_modules = OrderedSet() # Often "None" until tree building finishes its part. self.future_spec = future_spec # The source code of the module if changed or not from disk. self.source_code = None self.module_dict_name = "globals_%s" % (self.getCodeName(),) self.locals_scope = getLocalsDictHandle( self.module_dict_name, "module_dict", self ) self.used_modules = OrderedSet() @staticmethod def isCompiledPythonModule(): return True def getDetails(self): return { "filename": self.source_ref.getFilename(), "module_name": self.module_name, } def getDetailsForDisplay(self): result = self.getDetails() if self.future_spec is not None: result["code_flags"] = ",".join(self.future_spec.asFlags()) return result def getCompilationMode(self): return self.mode @classmethod def fromXML(cls, provider, source_ref, **args): # Modules are not having any provider, must not be used, assert False def getFutureSpec(self): return self.future_spec def setFutureSpec(self, future_spec): self.future_spec = future_spec def isTopModule(self): return self.is_top def asGraph(self, graph, desc): graph = graph.add_subgraph( name="cluster_%s" % desc, comment="Graph for %s" % self.getName() ) # graph.body.append("style=filled") # graph.body.append("color=lightgrey") # graph.body.append("label=Iteration_%d" % desc) def makeTraceNodeName(variable, version, variable_trace): return "%s/ %s %s %s" % ( desc, variable.getName(), version, variable_trace.__class__.__name__, ) for function_body in self.active_functions: trace_collection = function_body.trace_collection node_names = {} for ( (variable, version), variable_trace, ) in trace_collection.getVariableTracesAll().items(): node_name = makeTraceNodeName(variable, version, variable_trace) node_names[variable_trace] = node_name for ( (variable, version), variable_trace, ) in trace_collection.getVariableTracesAll().items(): node_name = node_names[variable_trace] previous = variable_trace.getPrevious() attrs = {"style": "filled"} if variable_trace.getUsageCount(): attrs["color"] = "blue" else: attrs["color"] = "red" graph.add_node(node_name, **attrs) if type(previous) is tuple: for prev_trace in previous: graph.add_edge(node_names[prev_trace], node_name) assert prev_trace is not variable_trace elif previous is not None: assert previous is not variable_trace graph.add_edge(node_names[previous], node_name) return graph def getSourceCode(self): if self.source_code is not None: return self.source_code else: return readSourceCodeFromFilename( module_name=self.getFullName(), source_filename=self.getCompileTimeFilename(), ) def setSourceCode(self, code): self.source_code = code def getParent(self): # We have never have a parent return None def getParentVariableProvider(self): # We have never have a provider return None def hasVariableName(self, variable_name): return variable_name in self.variables or variable_name in self.temp_variables def getProvidedVariables(self): return self.variables.values() def getFilename(self): return self.source_ref.getFilename() def getVariableForAssignment(self, variable_name): return self.getProvidedVariable(variable_name) def getVariableForReference(self, variable_name): return self.getProvidedVariable(variable_name) def getVariableForClosure(self, variable_name): return self.getProvidedVariable(variable_name=variable_name) def createProvidedVariable(self, variable_name): assert variable_name not in self.variables result = Variables.ModuleVariable(module=self, variable_name=variable_name) self.variables[variable_name] = result return result @staticmethod def getContainingClassDictCreation(): return None @staticmethod def isEarlyClosure(): # Modules should immediately closure variables on use. return True def getEntryPoint(self): return self def getCodeName(self): # For code name of modules, we need to translate to C identifiers, # removing characters illegal for that. return encodePythonIdentifierToC(self.getFullName()) def addFunction(self, function_body): functions = self.subnode_functions assert function_body not in functions functions += (function_body,) self.setChild("functions", functions) def startTraversal(self): self.used_modules = None self.active_functions = OrderedSet() def restartTraversal(self): self.visited_functions = set() def getUsedModules(self): if self.used_modules is None: visitor = DetectUsedModules() visitTree(tree=self, visitor=visitor) self.used_modules = visitor.getUsedModules() return self.used_modules def addUsedFunction(self, function_body): assert function_body in self.subnode_functions, function_body assert ( function_body.isExpressionFunctionBody() or function_body.isExpressionClassBody() or function_body.isExpressionGeneratorObjectBody() or function_body.isExpressionCoroutineObjectBody() or function_body.isExpressionAsyncgenObjectBody() ) self.active_functions.add(function_body) result = function_body not in self.visited_functions self.visited_functions.add(function_body) return result def getUsedFunctions(self): return self.active_functions def getUnusedFunctions(self): for function in self.subnode_functions: if function not in self.active_functions: yield function def addCrossUsedFunction(self, function_body): if function_body not in self.cross_used_functions: self.cross_used_functions.add(function_body) def getCrossUsedFunctions(self): return self.cross_used_functions def getFunctionFromCodeName(self, code_name): for function in self.subnode_functions: if function.getCodeName() == code_name: return function def getOutputFilename(self): main_filename = self.getFilename() if main_filename.endswith(".py"): result = main_filename[:-3] elif main_filename.endswith(".pyw"): result = main_filename[:-4] else: result = main_filename # There are some characters that somehow are passed to shell, by # Scons or unknown, so lets avoid them for now. return result.replace(")", "").replace("(", "") def computeModule(self): self.restartTraversal() old_collection = self.trace_collection self.trace_collection = TraceCollectionModule( self, old_collection.getVeryTrustedModuleVariables() if old_collection is not None else {}, ) module_body = self.subnode_body if module_body is not None: result = module_body.computeStatementsSequence( trace_collection=self.trace_collection ) if result is not module_body: self.setChild("body", result) self.attemptRecursion() # We determine the trusted module variable for use on next turnaround to provide functions with traces for them. very_trusted_module_variables = {} for module_variable in self.locals_scope.getLocalsRelevantVariables(): very_trusted_node = self.trace_collection.getVariableCurrentTrace( module_variable ).getAttributeNodeVeryTrusted() if very_trusted_node is not None: very_trusted_module_variables[module_variable] = very_trusted_node if self.trace_collection.updateVeryTrustedModuleVariables( very_trusted_module_variables ): self.trace_collection.signalChange( tags="trusted_module_variables", message="Trusting module variable(s) '%s'" % ",".join( variable.getName() for variable in self.trace_collection.getVeryTrustedModuleVariables() ), source_ref=self.source_ref, ) # Finalize locals scopes previously determined for removal in last pass. self.trace_collection.updateVariablesFromCollection( old_collection=old_collection, source_ref=self.source_ref ) # Indicate if this is pass 1 for the module as return value. was_complete = not self.locals_scope.complete def markAsComplete(body, trace_collection): if ( body.locals_scope is not None and body.locals_scope.isMarkedForPropagation() ): body.locals_scope = None if body.locals_scope is not None: body.locals_scope.markAsComplete(trace_collection) def markEntryPointAsComplete(body): markAsComplete(body, body.trace_collection) outline_bodies = body.trace_collection.getOutlineFunctions() if outline_bodies is not None: for outline_body in outline_bodies: markAsComplete(outline_body, body.trace_collection) body.optimizeUnusedTempVariables() markEntryPointAsComplete(self) for function_body in self.getUsedFunctions(): markEntryPointAsComplete(function_body) function_body.optimizeUnusedClosureVariables() function_body.optimizeVariableReleases() return was_complete def getTraceCollections(self): yield self.trace_collection for function in self.getUsedFunctions(): yield function.trace_collection def isUnoptimized(self): # Modules don't do this, pylint: disable=no-self-use return False def getLocalVariables(self): # Modules don't do this, pylint: disable=no-self-use return () def getUserLocalVariables(self): # Modules don't do this, pylint: disable=no-self-use return () @staticmethod def getFunctionVariablesWithAutoReleases(): """Return the list of function variables that should be released at exit.""" return () def getOutlineLocalVariables(self): outlines = self.getTraceCollection().getOutlineFunctions() if outlines is None: return () result = [] for outline in outlines: result.extend(outline.getUserLocalVariables()) return result def hasClosureVariable(self, variable): # Modules don't do this, pylint: disable=no-self-use,unused-argument return False def removeUserVariable(self, variable): outlines = self.getTraceCollection().getOutlineFunctions() for outline in outlines: user_locals = outline.getUserLocalVariables() if variable in user_locals: outline.removeUserVariable(variable) break def getLocalsScope(self): return self.locals_scope def getRuntimePackageValue(self): # Do not want to get asked for now. assert not Options.shallMakeModule() if self.isCompiledPythonPackage(): return self.getFullName().asString() value = self.getFullName().getPackageName() if value is not None: return value.asString() if self.isMainModule(): if self.main_added: return "" else: return None else: return None def getRuntimeNameValue(self): # Do not want to get asked for now. assert not Options.shallMakeModule() if self.isMainModule() and Options.hasPythonFlagPackageMode(): return "__main__" else: return self.getFullName().asString() class CompiledPythonPackage(CompiledPythonModule): kind = "COMPILED_PYTHON_PACKAGE" def __init__(self, module_name, is_top, mode, future_spec, source_ref): CompiledPythonModule.__init__( self, module_name=module_name, is_top=is_top, mode=mode, future_spec=future_spec, source_ref=source_ref, ) def getOutputFilename(self): result = self.getFilename() if os.path.isdir(result): return result else: return os.path.dirname(result) @staticmethod def canHaveExternalImports(): return True def makeUncompiledPythonModule( module_name, filename, bytecode, is_package, user_provided, technical ): source_ref = fromFilename(filename) if is_package: return UncompiledPythonPackage( module_name=module_name, bytecode=bytecode, filename=filename, user_provided=user_provided, technical=technical, source_ref=source_ref, ) else: return UncompiledPythonModule( module_name=module_name, bytecode=bytecode, filename=filename, user_provided=user_provided, technical=technical, source_ref=source_ref, ) class UncompiledPythonModule(PythonModuleBase): """Compiled Python Module""" kind = "UNCOMPILED_PYTHON_MODULE" __slots__ = "bytecode", "filename", "user_provided", "technical", "used_modules" def __init__( self, module_name, bytecode, filename, user_provided, technical, source_ref ): PythonModuleBase.__init__(self, module_name=module_name, source_ref=source_ref) self.bytecode = bytecode self.filename = filename self.user_provided = user_provided self.technical = technical self.used_modules = () def finalize(self): del self.used_modules del self.bytecode @staticmethod def isUncompiledPythonModule(): return True def isUserProvided(self): return self.user_provided def isTechnical(self): """Must be bytecode as it's used in CPython library initialization.""" return self.technical def getByteCode(self): return self.bytecode def getFilename(self): return self.filename def getUsedModules(self): return self.used_modules def setUsedModules(self, used_modules): self.used_modules = used_modules def startTraversal(self): pass class UncompiledPythonPackage(UncompiledPythonModule): kind = "UNCOMPILED_PYTHON_PACKAGE" class PythonMainModule(CompiledPythonModule): """Main module of a program, typically "__main__" but can be inside a package too.""" kind = "PYTHON_MAIN_MODULE" __slots__ = ("main_added", "early_modules") def __init__(self, module_name, main_added, mode, future_spec, source_ref): assert not Options.shallMakeModule() # Is this one from a "__main__.py" file self.main_added = main_added CompiledPythonModule.__init__( self, module_name=module_name, is_top=True, mode=mode, future_spec=future_spec, source_ref=source_ref, ) self.early_modules = () def getDetails(self): return { "filename": self.source_ref.getFilename(), "module_name": self.module_name, "main_added": self.main_added, "mode": self.mode, } @classmethod def fromXML(cls, provider, source_ref, **args): if "code_flags" in args: future_spec = fromFlags(args["code_flags"]) result = cls( main_added=args["main_added"] == "True", mode=args["mode"], module_name=ModuleName(args["module_name"]), future_spec=future_spec, source_ref=source_ref, ) from nuitka.ModuleRegistry import addRootModule addRootModule(result) function_work = [] for xml in args["functions"]: _kind, node_class, func_args, source_ref = extractKindAndArgsFromXML( xml, source_ref ) if "provider" in func_args: func_args["provider"] = getOwnerFromCodeName(func_args["provider"]) else: func_args["provider"] = result if "flags" in args: func_args["flags"] = set(func_args["flags"].split(",")) if "doc" not in args: func_args["doc"] = None function = node_class.fromXML(source_ref=source_ref, **func_args) # Could do more checks for look up of body here, but so what... function_work.append((function, iter(iter(xml).next()).next())) for function, xml in function_work: function.setChild( "body", fromXML( provider=function, xml=xml, source_ref=function.getSourceReference() ), ) result.setChild( "body", fromXML(provider=result, xml=args["body"][0], source_ref=source_ref) ) return result @staticmethod def isMainModule(): return True def getOutputFilename(self): if self.main_added: return os.path.dirname(self.getFilename()) else: return CompiledPythonModule.getOutputFilename(self) def setEarlyModules(self, early_modules): self.early_modules = early_modules def getEarlyModules(self): return self.early_modules def computeModule(self): CompiledPythonModule.computeModule(self) from nuitka.ModuleRegistry import addUsedModule for early_module in self.early_modules: if early_module.isTechnical(): usage_tag = "technical" reason = "Module needed for initializing Python" else: usage_tag = "stdlib" reason = "Part of standard library" addUsedModule( module=early_module, using_module=self, usage_tag=usage_tag, reason=reason, source_ref=self.source_ref, ) class PythonShlibModule(PythonModuleBase): kind = "PYTHON_SHLIB_MODULE" __slots__ = ("used_modules",) avoid_duplicates = set() def __init__(self, module_name, source_ref): PythonModuleBase.__init__(self, module_name=module_name, source_ref=source_ref) # That would be a mistake we just made. assert os.path.basename(source_ref.getFilename()) != "" # That is too likely a bug. assert module_name != "__main__" # Duplicates should be avoided by us caching elsewhere before creating # the object. assert self.getFullName() not in self.avoid_duplicates, self.getFullName() self.avoid_duplicates.add(self.getFullName()) self.used_modules = None def finalize(self): del self.used_modules def getFilename(self): return self.source_ref.getFilename() def startTraversal(self): pass def getPyIFilename(self): """Get Python type description filename.""" path = self.getFilename() filename = os.path.basename(path) dirname = os.path.dirname(path) return os.path.join(dirname, filename.split(".")[0]) + ".pyi" def _readPyPIFile(self): """Read the .pyi file if present and scan for dependencies.""" # Complex stuff, pylint: disable=too-many-branches,too-many-statements if self.used_modules is None: pyi_filename = self.getPyIFilename() if os.path.exists(pyi_filename): pyi_deps = OrderedSet() # Flag signalling multiline import handling in_import = False in_import_part = "" for line in getFileContentByLine(pyi_filename): line = line.strip() if not in_import: if line.startswith("import "): imported = line[7:] pyi_deps.add(imported) elif line.startswith("from "): parts = line.split(None, 3) assert parts[0] == "from" assert parts[2] == "import" origin_name = parts[1] if origin_name == "typing": continue if origin_name == ".": origin_name = self.getFullName() else: dot_count = 0 while origin_name.startswith("."): origin_name = origin_name[1:] dot_count += 1 if dot_count > 0: if origin_name: origin_name = ( self.getFullName() .getRelativePackageName(level=dot_count + 1) .getChildNamed(origin_name) ) else: origin_name = ( self.getFullName().getRelativePackageName( level=dot_count + 1 ) ) if origin_name != self.getFullName(): pyi_deps.add(origin_name) imported = parts[3] if imported.startswith("("): # Handle multiline imports if not imported.endswith(")"): in_import = True imported = imported[1:] in_import_part = origin_name assert in_import_part, ( "Multiline part in file %s cannot be empty" % pyi_filename ) else: in_import = False imported = imported[1:-1] assert imported if imported == "*": continue for name in imported.split(","): if name: name = name.strip() pyi_deps.add(origin_name + "." + name) else: # In import imported = line if imported.endswith(")"): imported = imported[0:-1] in_import = False for name in imported.split(","): name = name.strip() if name: pyi_deps.add(in_import_part + "." + name) if "typing" in pyi_deps: pyi_deps.discard("typing") if "__future__" in pyi_deps: pyi_deps.discard("__future__") if self.getFullName() in pyi_deps: pyi_deps.discard(self.getFullName()) if self.getFullName().getPackageName() in pyi_deps: pyi_deps.discard(self.getFullName().getPackageName()) self.used_modules = tuple((pyi_dep, None) for pyi_dep in pyi_deps) else: self.used_modules = () def getUsedModules(self): self._readPyPIFile() assert "." not in self.used_modules, self return self.used_modules def getParentModule(self): return self Nuitka-0.6.19.1/nuitka/nodes/SubscriptNodes.py0000600000372100037210000001345714166627112026225 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Subscript node. Subscripts are important when working with lists and dictionaries. Tracking them can allow to achieve more compact code, or predict results at compile time. There is be a method "computeExpressionSubscript" to aid predicting them in the other nodes. """ from .ExpressionBases import ExpressionChildrenHavingBase from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeBases import ( SideEffectsFromChildrenMixin, StatementChildrenHavingBase, ) from .NodeMakingHelpers import wrapExpressionWithNodeSideEffects class StatementAssignmentSubscript(StatementChildrenHavingBase): kind = "STATEMENT_ASSIGNMENT_SUBSCRIPT" named_children = ("source", "subscribed", "subscript") def __init__(self, subscribed, subscript, source, source_ref): StatementChildrenHavingBase.__init__( self, values={"source": source, "subscribed": subscribed, "subscript": subscript}, source_ref=source_ref, ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.subnode_subscribed.computeExpressionSetSubscript( set_node=self, subscript=self.subnode_subscript, value_node=self.subnode_source, trace_collection=trace_collection, ) @staticmethod def getStatementNiceName(): return "subscript assignment statement" class StatementDelSubscript(StatementChildrenHavingBase): kind = "STATEMENT_DEL_SUBSCRIPT" named_children = ("subscribed", "subscript") def __init__(self, subscribed, subscript, source_ref): StatementChildrenHavingBase.__init__( self, values={"subscribed": subscribed, "subscript": subscript}, source_ref=source_ref, ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.subnode_subscribed.computeExpressionDelSubscript( del_node=self, subscript=self.subnode_subscript, trace_collection=trace_collection, ) @staticmethod def getStatementNiceName(): return "subscript del statement" class ExpressionSubscriptLookup(ExpressionChildrenHavingBase): kind = "EXPRESSION_SUBSCRIPT_LOOKUP" named_children = ("expression", "subscript") def __init__(self, expression, subscript, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "subscript": subscript}, source_ref=source_ref, ) def computeExpression(self, trace_collection): return self.subnode_expression.computeExpressionSubscript( lookup_node=self, subscript=self.subnode_subscript, trace_collection=trace_collection, ) @staticmethod def isKnownToBeIterable(count): return None def hasSubscript(value, subscript): """Check if a value has a subscript.""" try: value[subscript] except Exception: # Catch all the things, pylint: disable=broad-except return False else: return True class ExpressionSubscriptCheck( ExpressionBoolShapeExactMixin, SideEffectsFromChildrenMixin, ExpressionChildrenHavingBase, ): kind = "EXPRESSION_SUBSCRIPT_CHECK" named_children = ("expression", "subscript") def __init__(self, expression, subscript, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "subscript": subscript}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # We do at least for compile time constants optimization here, but more # could be done, were we to consider shapes. source = self.subnode_expression subscript = self.subnode_subscript if source.isCompileTimeConstant() and subscript.isCompileTimeConstant(): ( result, tags, change_desc, ) = trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: hasSubscript( source.getCompileTimeConstant(), subscript.getCompileTimeConstant() ), description="Subscript check has been pre-computed.", ) # If source has side effects, they must be evaluated. result = wrapExpressionWithNodeSideEffects(new_node=result, old_node=source) return result, tags, change_desc trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def mayRaiseException(exception_type): return False Nuitka-0.6.19.1/nuitka/nodes/ExecEvalNodes.py0000600000372100037210000002373514166627112025743 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes concern with exec and eval builtins. These are the dynamic codes, and as such rather difficult. We would like to eliminate or limit their impact as much as possible, but it's difficult to do. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildrenHavingBase from .NodeBases import StatementChildHavingBase, StatementChildrenHavingBase from .NodeMakingHelpers import ( convertNoneConstantToNone, makeStatementOnlyNodesFromExpressions, ) class ExpressionBuiltinEval(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_EVAL" named_children = ("source", "globals_arg", "locals_arg") def __init__(self, source_code, globals_arg, locals_arg, source_ref): ExpressionChildrenHavingBase.__init__( self, values={ "source": source_code, "globals_arg": globals_arg, "locals_arg": locals_arg, }, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Attempt for constant values to do it. return self, None, None # Note: Python3 only so far. if python_version >= 0x300: class ExpressionBuiltinExec(ExpressionBuiltinEval): kind = "EXPRESSION_BUILTIN_EXEC" def __init__(self, source_code, globals_arg, locals_arg, source_ref): ExpressionBuiltinEval.__init__( self, source_code=source_code, globals_arg=globals_arg, locals_arg=locals_arg, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Attempt for constant values to do it. return self, None, None def computeExpressionDrop(self, statement, trace_collection): if self.getParentVariableProvider().isEarlyClosure(): result = StatementExec( source_code=self.subnode_source, globals_arg=self.subnode_globals_arg, locals_arg=self.subnode_locals_arg, source_ref=self.source_ref, ) del self.parent return ( result, "new_statements", """\ Replaced built-in exec call to exec statement in early closure context.""", ) else: return statement, None, None # Note: Python2 only if python_version < 0x300: class ExpressionBuiltinExecfile(ExpressionBuiltinEval): kind = "EXPRESSION_BUILTIN_EXECFILE" named_children = ("source", "globals_arg", "locals_arg") def __init__(self, source_code, globals_arg, locals_arg, source_ref): ExpressionBuiltinEval.__init__( self, source_code=source_code, globals_arg=globals_arg, locals_arg=locals_arg, source_ref=source_ref, ) def computeExpressionDrop(self, statement, trace_collection): # In this case, the copy-back must be done and will only be done # correctly by the code for exec statements. provider = self.getParentVariableProvider() if provider.isExpressionClassBody(): result = StatementExec( source_code=self.subnode_source, globals_arg=self.subnode_globals_arg, locals_arg=self.subnode_locals_arg, source_ref=self.source_ref, ) del self.parent return ( result, "new_statements", """\ Changed 'execfile' with unused result to 'exec' on class level.""", ) else: return statement, None, None class StatementExec(StatementChildrenHavingBase): kind = "STATEMENT_EXEC" named_children = ("source", "globals_arg", "locals_arg") def __init__(self, source_code, globals_arg, locals_arg, source_ref): StatementChildrenHavingBase.__init__( self, values={ "globals_arg": globals_arg, "locals_arg": locals_arg, "source": source_code, }, source_ref=source_ref, ) def setChild(self, name, value): if name in ("globals_arg", "locals_arg"): value = convertNoneConstantToNone(value) return StatementChildrenHavingBase.setChild(self, name, value) def computeStatement(self, trace_collection): source_code = trace_collection.onExpression(expression=self.subnode_source) if source_code.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if source_code.willRaiseException(BaseException): result = source_code return ( result, "new_raise", """\ Exec statement raises implicitly when determining source code argument.""", ) globals_arg = trace_collection.onExpression( expression=self.subnode_globals_arg, allow_none=True ) if globals_arg is not None and globals_arg.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if globals_arg is not None and globals_arg.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(source_code, globals_arg) ) return ( result, "new_raise", """\ Exec statement raises implicitly when determining globals argument.""", ) locals_arg = trace_collection.onExpression( expression=self.subnode_locals_arg, allow_none=True ) if locals_arg is not None and locals_arg.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if locals_arg is not None and locals_arg.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(source_code, globals_arg, locals_arg) ) return ( result, "new_raise", """\ Exec statement raises implicitly when determining locals argument.""", ) trace_collection.onExceptionRaiseExit(BaseException) str_value = self.subnode_source.getStrValue() if str_value is not None: # TODO: This needs to be re-done. # TODO: Don't forget to consider side effects of source code, # locals_arg, and globals_arg. return self, None, None # exec_body = ... # return (exec_body, "new_statements", "In-lined constant exec statement.") return self, None, None class StatementLocalsDictSync(StatementChildHavingBase): kind = "STATEMENT_LOCALS_DICT_SYNC" named_child = "locals_arg" __slots__ = ("locals_scope", "previous_traces", "variable_traces") def __init__(self, locals_scope, locals_arg, source_ref): StatementChildHavingBase.__init__(self, value=locals_arg, source_ref=source_ref) self.previous_traces = None self.variable_traces = None self.locals_scope = locals_scope def getDetails(self): return {"locals_scope": self.locals_scope} def getPreviousVariablesTraces(self): return self.previous_traces def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc provider = self.getParentVariableProvider() if provider.isCompiledPythonModule(): return None, "new_statements", "Removed sync back to locals without locals." self.previous_traces = trace_collection.onLocalsUsage(self.locals_scope) if not self.previous_traces: return None, "new_statements", "Removed sync back to locals without locals." trace_collection.removeAllKnowledge() self.variable_traces = trace_collection.onLocalsUsage(self.locals_scope) return self, None, None @staticmethod def mayRaiseException(exception_type): return False class ExpressionBuiltinCompile(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_COMPILE" named_children = ("source", "filename", "mode", "flags", "dont_inherit", "optimize") def __init__( self, source_code, filename, mode, flags, dont_inherit, optimize, source_ref ): ExpressionChildrenHavingBase.__init__( self, values={ "source": source_code, "filename": filename, "mode": mode, "flags": flags, "dont_inherit": dont_inherit, "optimize": optimize, }, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Attempt for constant values to do it. return self, None, None Nuitka-0.6.19.1/nuitka/nodes/FutureSpecs.py0000600000372100037210000001240014166627112025511 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Specification record for future flags. A source reference also implies a specific set of future flags in use by the parser at that location. Can be different inside a module due to e.g. the in-lining of "exec" statements with their own future imports, or in-lining of code from other modules. """ from nuitka.PythonVersions import python_version from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) # These defaults have changed with Python versions. _future_division_default = python_version >= 0x300 _future_absolute_import_default = python_version >= 0x300 _future_generator_stop_default = python_version >= 0x370 _future_annotations_default = python_version >= 0x400 class FutureSpec(object): __slots__ = ( "future_division", "unicode_literals", "absolute_import", "future_print", "barry_bdfl", "generator_stop", "future_annotations", ) @counted_init def __init__(self): self.future_division = _future_division_default self.unicode_literals = False self.absolute_import = _future_absolute_import_default self.future_print = False self.barry_bdfl = False self.generator_stop = _future_generator_stop_default self.future_annotations = _future_annotations_default if isCountingInstances(): __del__ = counted_del() def __repr__(self): return "" % ",".join(self.asFlags()) def clone(self): result = FutureSpec() result.future_division = self.future_division result.unicode_literals = self.unicode_literals result.absolute_import = self.absolute_import result.future_print = self.future_print result.barry_bdfl = self.barry_bdfl result.generator_stop = self.generator_stop result.future_annotations = result.future_annotations return result def isFutureDivision(self): return self.future_division def enableFutureDivision(self): self.future_division = True def isFuturePrint(self): return self.future_print def enableFuturePrint(self): self.future_print = True def enableUnicodeLiterals(self): self.unicode_literals = True def enableAbsoluteImport(self): self.absolute_import = True def enableBarry(self): self.barry_bdfl = True def enableGeneratorStop(self): self.generator_stop = True def isAbsoluteImport(self): return self.absolute_import def isGeneratorStop(self): return self.generator_stop def enableFutureAnnotations(self): self.future_annotations = True def isFutureAnnotations(self): return self.future_annotations def asFlags(self): """Create a list of C identifiers to represent the flag values. This is for use in code generation and to restore from saved modules. """ result = [] if python_version < 0x300 and self.future_division: result.append("CO_FUTURE_DIVISION") if self.unicode_literals: result.append("CO_FUTURE_UNICODE_LITERALS") if python_version < 0x300 and self.absolute_import: result.append("CO_FUTURE_ABSOLUTE_IMPORT") if python_version < 0x300 and self.future_print: result.append("CO_FUTURE_PRINT_FUNCTION") if python_version >= 0x300 and self.barry_bdfl: result.append("CO_FUTURE_BARRY_AS_BDFL") if 0x350 <= python_version < 0x370 and self.generator_stop: result.append("CO_FUTURE_GENERATOR_STOP") if python_version >= 0x370 and self.future_annotations: result.append("CO_FUTURE_ANNOTATIONS") return tuple(result) def fromFlags(flags): flags = flags.split(",") if "" in flags: flags.remove("") result = FutureSpec() if "CO_FUTURE_DIVISION" in flags: result.enableFutureDivision() if "CO_FUTURE_UNICODE_LITERALS" in flags: result.enableUnicodeLiterals() if "CO_FUTURE_ABSOLUTE_IMPORT" in flags: result.enableAbsoluteImport() if "CO_FUTURE_PRINT_FUNCTION" in flags: result.enableFuturePrint() if "CO_FUTURE_BARRY_AS_BDFL" in flags: result.enableBarry() if "CO_FUTURE_GENERATOR_STOP" in flags: result.enableGeneratorStop() # Check if we are going to give similar results than what we got. assert tuple(result.asFlags()) == tuple(flags), (result, result.asFlags(), flags) return result Nuitka-0.6.19.1/nuitka/nodes/LocalsScopes.py0000600000372100037210000003257114166627112025646 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module maintains the locals dict handles. """ from nuitka import Variables from nuitka.containers.odict import OrderedDict from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) from .shapes.BuiltinTypeShapes import tshape_dict from .shapes.StandardShapes import tshape_unknown locals_dict_handles = {} def getLocalsDictType(kind): if kind == "python2_function_exec": locals_scope = LocalsDictExecHandle elif kind == "python_function": locals_scope = LocalsDictFunctionHandle elif kind == "python3_class": locals_scope = LocalsMappingHandle elif kind == "python2_class": locals_scope = LocalsDictHandle elif kind == "module_dict": locals_scope = GlobalsDictHandle else: assert False, kind return locals_scope def getLocalsDictHandle(locals_name, kind, owner): assert locals_name not in locals_dict_handles, locals_name locals_dict_handles[locals_name] = getLocalsDictType(kind)( locals_name=locals_name, owner=owner ) return locals_dict_handles[locals_name] class LocalsDictHandleBase(object): # TODO: Might remove some of these later, pylint: disable=too-many-instance-attributes __slots__ = ( "locals_name", # TODO: Specialize what the kinds really use. "variables", "local_variables", "providing", "mark_for_propagation", "propagation", "owner", "complete", ) @counted_init def __init__(self, locals_name, owner): self.locals_name = locals_name self.owner = owner # For locals dict variables in this scope. self.variables = {} # For local variables in this scope. self.local_variables = {} self.providing = OrderedDict() # Can this be eliminated through replacement of temporary variables self.mark_for_propagation = False self.propagation = None self.complete = False if isCountingInstances(): __del__ = counted_del() def __repr__(self): return "<%s of %s>" % (self.__class__.__name__, self.locals_name) def getName(self): return self.locals_name def makeClone(self, new_owner): count = 1 # Make it unique. while 1: locals_name = self.locals_name + "_inline_%d" % count if locals_name not in locals_dict_handles: break count += 1 result = self.__class__(locals_name=locals_name, owner=new_owner) variable_translation = {} # Clone variables as well. for variable_name, variable in self.variables.items(): new_variable = variable.makeClone(new_owner=new_owner) variable_translation[variable] = new_variable result.variables[variable_name] = new_variable for variable_name, variable in self.local_variables.items(): new_variable = variable.makeClone(new_owner=new_owner) variable_translation[variable] = new_variable result.local_variables[variable_name] = new_variable result.providing = OrderedDict() for variable_name, variable in self.providing.items(): if variable in variable_translation: new_variable = variable_translation[variable] else: new_variable = variable.makeClone(new_owner=new_owner) variable_translation[variable] = new_variable result.providing[variable_name] = new_variable return result, variable_translation @staticmethod def getTypeShape(): return tshape_dict @staticmethod def hasShapeDictionaryExact(): return True def getCodeName(self): return self.locals_name @staticmethod def isModuleScope(): return False @staticmethod def isClassScope(): return False @staticmethod def isFunctionScope(): return False @staticmethod def isUnoptimizedFunctionScope(): return False def getProvidedVariables(self): return self.providing.values() def registerProvidedVariable(self, variable): variable_name = variable.getName() self.providing[variable_name] = variable def unregisterProvidedVariable(self, variable): """Remove provided variable, e.g. because it became unused.""" variable_name = variable.getName() if variable_name in self.providing: del self.providing[variable_name] registerClosureVariable = registerProvidedVariable unregisterClosureVariable = unregisterProvidedVariable def hasProvidedVariable(self, variable_name): """Test if a variable is provided.""" return variable_name in self.providing def getProvidedVariable(self, variable_name): """Test if a variable is provided.""" return self.providing[variable_name] def getLocalsRelevantVariables(self): """The variables relevant to locals.""" return self.providing.values() def getLocalsDictVariable(self, variable_name): if variable_name not in self.variables: result = Variables.LocalsDictVariable( owner=self, variable_name=variable_name ) self.variables[variable_name] = result return self.variables[variable_name] # TODO: Have variable ownership moved to the locals scope, so owner becomes not needed here. def getLocalVariable(self, owner, variable_name): if variable_name not in self.local_variables: result = Variables.LocalVariable(owner=owner, variable_name=variable_name) self.local_variables[variable_name] = result return self.local_variables[variable_name] def markForLocalsDictPropagation(self): self.mark_for_propagation = True def isMarkedForPropagation(self): return self.mark_for_propagation def allocateTempReplacementVariable(self, trace_collection, variable_name): if self.propagation is None: self.propagation = OrderedDict() if variable_name not in self.propagation: provider = trace_collection.getOwner() self.propagation[variable_name] = provider.allocateTempVariable( temp_scope=None, name=self.getCodeName() + "_key_" + variable_name ) return self.propagation[variable_name] def getPropagationVariables(self): if self.propagation is None: return () return self.propagation def finalize(self): # Make it unusable when it's become empty, not used. self.owner.locals_scope = None del self.owner del self.propagation del self.mark_for_propagation for variable in self.variables.values(): variable.finalize() for variable in self.local_variables.values(): variable.finalize() del self.variables del self.providing def markAsComplete(self, trace_collection): self.complete = True self._considerUnusedUserLocalVariables(trace_collection) self._considerPropagation(trace_collection) # TODO: Limited to Python2 classes for now, more overloads need to be added, this # ought to be abstract and have variants with TODOs for each of them. @staticmethod def _considerPropagation(trace_collection): """For overload by scope type. Check if this can be replaced.""" def _considerUnusedUserLocalVariables(self, trace_collection): """Check scope for unused variables.""" provided = self.getProvidedVariables() removals = [] for variable in provided: if ( variable.isLocalVariable() and not variable.isParameterVariable() and variable.getOwner() is self.owner ): empty = trace_collection.hasEmptyTraces(variable) if empty: removals.append(variable) for variable in removals: self.unregisterProvidedVariable(variable) trace_collection.signalChange( "var_usage", self.owner.getSourceReference(), message="Remove unused local variable '%s'." % variable.getName(), ) class LocalsDictHandle(LocalsDictHandleBase): """Locals dict for a Python class with mere dict.""" __slots__ = () @staticmethod def isClassScope(): return True @staticmethod def getMappingValueShape(variable): # We don't yet track dictionaries, let alone mapping values. # pylint: disable=unused-argument return tshape_unknown def _considerPropagation(self, trace_collection): self.complete = True propagate = True for variable in self.variables.values(): for variable_trace in variable.traces: if variable_trace.isAssignTrace(): # For assign traces we want the value to not have a side effect, # then we can push it down the line. TODO: Once temporary # variables and dictionary building allows for unset values # remove this if ( variable_trace.getAssignNode().subnode_source.mayHaveSideEffects() ): propagate = False break elif variable_trace.isDeletedTrace(): propagate = False break elif variable_trace.isMergeTrace(): propagate = False break elif variable_trace.isUninitTrace(): pass elif variable_trace.isUnknownTrace(): propagate = False break elif variable_trace.isEscapeTrace(): propagate = False break else: assert False, (variable, variable_trace) if propagate: trace_collection.signalChange( "var_usage", self.owner.getSourceReference(), message="Forward propagage locals dictionary.", ) self.markForLocalsDictPropagation() return propagate class LocalsMappingHandle(LocalsDictHandle): """Locals dict of a Python3 class with a mapping.""" __slots__ = () @staticmethod def getTypeShape(): # TODO: Make mapping available for this. return tshape_unknown @staticmethod def hasShapeDictionaryExact(): # TODO: Keep in sync with getTypeShape being calculated eventually. return False @staticmethod def isClassScope(): return True class LocalsDictExecHandle(LocalsDictHandleBase): """Locals dict of a Python2 function with an exec.""" __slots__ = ("closure_variables",) def __init__(self, locals_name, owner): LocalsDictHandleBase.__init__(self, locals_name=locals_name, owner=owner) self.closure_variables = None @staticmethod def isFunctionScope(): return True @staticmethod def isUnoptimizedFunctionScope(): return True def getLocalsRelevantVariables(self): if self.closure_variables is None: return self.providing.values() else: return [ variable for variable in self.providing.values() if variable not in self.closure_variables ] # TODO: What about the ".0" variety, we used to exclude it. def registerClosureVariable(self, variable): self.registerProvidedVariable(variable) if self.closure_variables is None: self.closure_variables = set() self.closure_variables.add(variable) def unregisterClosureVariable(self, variable): self.unregisterProvidedVariable(variable) variable_name = variable.getName() if variable_name in self.providing: del self.providing[variable_name] class LocalsDictFunctionHandle(LocalsDictHandleBase): """Locals dict of a Python3 function or Python2 function without an exec.""" __slots__ = () @staticmethod def isFunctionScope(): return True class GlobalsDictHandle(LocalsDictHandleBase): __slots__ = ("escaped",) def __init__(self, locals_name, owner): LocalsDictHandleBase.__init__(self, locals_name=locals_name, owner=owner) self.escaped = False @staticmethod def isModuleScope(): return True def markAsEscaped(self): self.escaped = True def isEscaped(self): return self.escaped Nuitka-0.6.19.1/nuitka/nodes/TypeMatchNodes.py0000600000372100037210000000447114166627112026141 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Dedicated nodes used for the 3.10 matching Not usable with older Python as it depends on type flags not present. """ from .ExpressionBases import ExpressionChildHavingBase from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeBases import SideEffectsFromChildrenMixin class ExpressionMatchTypeCheckBase( ExpressionBoolShapeExactMixin, SideEffectsFromChildrenMixin, ExpressionChildHavingBase, ): named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__( self, value=value, source_ref=source_ref, ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseException(exception_type) class ExpressionMatchTypeCheckSequence(ExpressionMatchTypeCheckBase): kind = "EXPRESSION_MATCH_TYPE_CHECK_SEQUENCE" def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict, based on argument # shape, this could evaluate to statically True/False and then will allow # optimization into match branches. return self, None, None class ExpressionMatchTypeCheckMapping(ExpressionMatchTypeCheckBase): kind = "EXPRESSION_MATCH_TYPE_CHECK_MAPPING" def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict, based on argument # shape, this could evaluate to statically True/False and then will allow # optimization into match branches. return self, None, None Nuitka-0.6.19.1/nuitka/nodes/ClassNodes.py0000600000372100037210000001511714166627112025307 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for classes and their creations. The classes are are at the core of the language and have their complexities. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildrenHavingBase from .IndicatorMixins import MarkNeedsAnnotationsMixin from .LocalsScopes import getLocalsDictHandle from .OutlineNodes import ExpressionOutlineFunctionBase class ExpressionClassBody(MarkNeedsAnnotationsMixin, ExpressionOutlineFunctionBase): kind = "EXPRESSION_CLASS_BODY" __slots__ = ("needs_annotations_dict", "doc") if python_version >= 0x340: __slots__ += ("qualname_setup",) def __init__(self, provider, name, doc, source_ref): ExpressionOutlineFunctionBase.__init__( self, provider=provider, name=name, body=None, code_prefix="class", source_ref=source_ref, ) MarkNeedsAnnotationsMixin.__init__(self) self.doc = doc # Force creation with proper type. if python_version >= 0x300: locals_kind = "python3_class" else: locals_kind = "python2_class" self.locals_scope = getLocalsDictHandle( "locals_%s_%d" % (self.getCodeName(), source_ref.getLineNumber()), locals_kind, self, ) if python_version >= 0x340: self.qualname_setup = None def getDetails(self): return { "name": self.getFunctionName(), "provider": self.provider.getCodeName(), "doc": self.doc, "flags": self.flags, } def getDetailsForDisplay(self): result = { "name": self.getFunctionName(), "provider": self.provider.getCodeName(), "flags": "" if self.flags is None else ",".join(sorted(self.flags)), } if self.doc is not None: result["doc"] = self.doc return result @classmethod def fromXML(cls, provider, source_ref, **args): return cls(provider=provider, source_ref=source_ref, **args) def getDoc(self): return self.doc @staticmethod def isEarlyClosure(): return True def getVariableForClosure(self, variable_name): # print( "getVariableForClosure", self, variable_name ) # The class bodies provide no closure, except under CPython3.x, there # they provide "__class__" but nothing else. if variable_name == "__class__": if python_version < 0x300: return self.provider.getVariableForClosure("__class__") else: return ExpressionOutlineFunctionBase.getVariableForClosure( self, variable_name="__class__" ) else: result = self.provider.getVariableForClosure(variable_name) self.taken.add(result) return result def markAsDirectlyCalled(self): pass @staticmethod def mayHaveSideEffects(): # The function definition has no side effects, calculating the defaults # would be, but that is done outside of this. return False def mayRaiseException(self, exception_type): return self.subnode_body.mayRaiseException(exception_type) def isUnoptimized(self): # Classes all are that. return True class ExpressionSelectMetaclass(ExpressionChildrenHavingBase): kind = "EXPRESSION_SELECT_METACLASS" named_children = ("metaclass", "bases") def __init__(self, metaclass, bases, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"metaclass": metaclass, "bases": bases}, source_ref=source_ref ) def computeExpression(self, trace_collection): # TODO: Meta class selection is very computable, and should be done. return self, None, None class ExpressionBuiltinType3(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_TYPE3" named_children = ("type_name", "bases", "dict") def __init__(self, type_name, bases, type_dict, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"type_name": type_name, "bases": bases, "dict": type_dict}, source_ref=source_ref, ) def _calculateMetaClass(self): # TODO: Share code with ExpressionSelectMetaclass if not self.subnode_bases.isCompileTimeConstant(): return None # TODO: Want to cache this result probably for speed reasons and it may also # contain allocations for dataclasses, generics, etc. # Need to use private CPython API unless we want to re-implement it, pylint: disable=protected-access import ctypes ctypes.pythonapi._PyType_CalculateMetaclass.argtypes = [ ctypes.py_object, ctypes.py_object, ] ctypes.pythonapi._PyType_CalculateMetaclass.restype = ctypes.py_object bases = self.subnode_bases.getCompileTimeConstant() return ctypes.pythonapi._PyType_CalculateMetaclass(type, bases) def mayRaiseException(self, exception_type): # TODO: In many cases, this will not raise for compile time knowable # case classes. We might ask the bases for the metaclass selected by # compile time inspection. return True def computeExpression(self, trace_collection): # TODO: Can use this to specialize to the correct metaclass at compile # time. # metacls = self._calculateMetaClass() # TODO: Should be compile time computable if bases and dict are # allowing that to happen into a dedicated class creation node, # with known metaclass selection. # Any exception may be raised. if self.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/AttributeNodes.py0000600000372100037210000003014714166627112026205 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Attribute nodes Knowing attributes of an object is very important, esp. when it comes to 'self' and objects and classes. There will be a methods "computeExpression*Attribute" to aid predicting them, with many variants for setting, deleting, and accessing. Also there is some complication in the form of special lookups, that won't go through the normal path, but just check slots. Due to ``getattr`` and ``setattr`` built-ins, there is also a different in the computations for objects and for compile time known strings. This reflects what CPython also does with "tp_getattr" and "tp_getattro". These nodes are therefore mostly delegating the work to expressions they work on, and let them decide and do the heavy lifting of optimization and annotation is happening in the nodes that implement these compute slots. """ from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .NodeBases import StatementChildHavingBase, StatementChildrenHavingBase from .NodeMakingHelpers import ( makeCompileTimeConstantReplacementNode, wrapExpressionWithNodeSideEffects, ) class StatementAssignmentAttribute(StatementChildrenHavingBase): """Assignment to an attribute. Typically from code like: source.attribute_name = expression Both source and expression may be complex expressions, the source is evaluated first. Assigning to an attribute has its on slot on the source, which gets to decide if it knows it will work or not, and what value it will be. """ __slots__ = ("attribute_name",) kind = "STATEMENT_ASSIGNMENT_ATTRIBUTE" named_children = ("source", "expression") def __init__(self, expression, attribute_name, source, source_ref): StatementChildrenHavingBase.__init__( self, values={"expression": expression, "source": source}, source_ref=source_ref, ) self.attribute_name = attribute_name def getDetails(self): return {"attribute_name": self.attribute_name} def getAttributeName(self): return self.attribute_name def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.subnode_expression.computeExpressionSetAttribute( set_node=self, attribute_name=self.attribute_name, value_node=self.subnode_source, trace_collection=trace_collection, ) @staticmethod def getStatementNiceName(): return "attribute assignment statement" class StatementDelAttribute(StatementChildHavingBase): """Deletion of an attribute. Typically from code like: del source.attribute_name The source may be complex expression. Deleting an attribute has its on slot on the source, which gets to decide if it knows it will work or not, and what value it will be. """ kind = "STATEMENT_DEL_ATTRIBUTE" named_child = "expression" __slots__ = ("attribute_name",) def __init__(self, expression, attribute_name, source_ref): StatementChildHavingBase.__init__(self, value=expression, source_ref=source_ref) self.attribute_name = attribute_name def getDetails(self): return {"attribute_name": self.attribute_name} def getAttributeName(self): return self.attribute_name def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.subnode_expression.computeExpressionDelAttribute( set_node=self, attribute_name=self.attribute_name, trace_collection=trace_collection, ) @staticmethod def getStatementNiceName(): return "attribute del statement" from .AttributeLookupNodes import ExpressionAttributeLookup from .AttributeNodesGenerated import attribute_classes def makeExpressionAttributeLookup(expression, attribute_name, source_ref): attribute_class = attribute_classes.get(attribute_name) if attribute_class is not None: assert attribute_class.attribute_name == attribute_name return attribute_class(expression=expression, source_ref=source_ref) else: return ExpressionAttributeLookup( expression=expression, attribute_name=attribute_name, source_ref=source_ref ) class ExpressionAttributeLookupSpecial(ExpressionAttributeLookup): """Special lookup up an attribute of an object. Typically from code like this: with source: pass These directly go to slots, and are performed for with statements of Python2.7 or higher. """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_SPECIAL" def computeExpression(self, trace_collection): return self.subnode_expression.computeExpressionAttributeSpecial( lookup_node=self, attribute_name=self.attribute_name, trace_collection=trace_collection, ) class ExpressionBuiltinGetattr(ExpressionChildrenHavingBase): """Built-in "getattr". Typical code like this: getattr(object_arg, name, default) The default is optional, but computed before the lookup is done. """ kind = "EXPRESSION_BUILTIN_GETATTR" named_children = ("expression", "name", "default") def __init__(self, expression, name, default, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "name": name, "default": default}, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) default = self.subnode_default if default is None or not default.mayHaveSideEffects(): attribute = self.subnode_name attribute_name = attribute.getStringValue() if attribute_name is not None: source = self.subnode_expression if source.isKnownToHaveAttribute(attribute_name): # If source has side effects, they must be evaluated, before # the lookup, meaning, a temporary variable should be assigned. # For now, we give up in this case. side_effects = source.extractSideEffects() if not side_effects: result = makeExpressionAttributeLookup( expression=source, attribute_name=attribute_name, source_ref=self.source_ref, ) result = wrapExpressionWithNodeSideEffects( new_node=result, old_node=attribute ) return ( result, "new_expression", """Replaced call to built-in 'getattr' with constant \ attribute '%s' to mere attribute lookup""" % attribute_name, ) return self, None, None class ExpressionBuiltinSetattr(ExpressionChildrenHavingBase): """Built-in "setattr". Typical code like this: setattr(source, attribute, value) """ kind = "EXPRESSION_BUILTIN_SETATTR" named_children = ("expression", "attribute", "value") def __init__(self, expression, name, value, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "attribute": name, "value": value}, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # Note: Might be possible to predict or downgrade to mere attribute set. return self, None, None class ExpressionBuiltinHasattr(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_HASATTR" named_children = ("expression", "attribute") def __init__(self, expression, name, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "attribute": name}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # We do at least for compile time constants optimization here, but more # could be done, were we to know shapes. source = self.subnode_expression if source.isCompileTimeConstant(): attribute = self.subnode_attribute attribute_name = attribute.getStringValue() # TODO: Something needs to be done if it has no string value. if attribute_name is not None: # If source or attribute have side effects, they must be # evaluated, before the lookup. ( result, tags, change_desc, ) = trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: hasattr( source.getCompileTimeConstant(), attribute_name ), description="Call to 'hasattr' pre-computed.", ) result = wrapExpressionWithNodeSideEffects( new_node=result, old_node=attribute ) result = wrapExpressionWithNodeSideEffects( new_node=result, old_node=source ) return result, tags, change_desc trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionAttributeCheck(ExpressionChildHavingBase): kind = "EXPRESSION_ATTRIBUTE_CHECK" named_child = "expression" __slots__ = ("attribute_name",) def __init__(self, expression, attribute_name, source_ref): ExpressionChildHavingBase.__init__( self, value=expression, source_ref=source_ref ) self.attribute_name = attribute_name def getDetails(self): return {"attribute_name": self.attribute_name} def computeExpression(self, trace_collection): source = self.subnode_expression # For things that know their attributes, we can statically optimize this # into true or false, preserving side effects of course. has_attribute = source.isKnownToHaveAttribute(self.attribute_name) if has_attribute is not None: result = makeCompileTimeConstantReplacementNode( value=has_attribute, node=self, user_provided=False ) # If source has side effects, they must be evaluated. result = wrapExpressionWithNodeSideEffects(new_node=result, old_node=source) return result, "new_constant", "Attribute check has been pre-computed." # Attribute check is implemented by getting an attribute. if source.mayRaiseExceptionAttributeLookup(BaseException, self.attribute_name): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def mayRaiseException(exception_type): return False def getAttributeName(self): return self.attribute_name Nuitka-0.6.19.1/nuitka/nodes/CodeObjectSpecs.py0000600000372100037210000001444414166627112026252 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Code object specifications. For code objects that will be attached to module, function, and generator objects, as well as tracebacks. They might be shared. """ from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) class CodeObjectSpec(object): # One attribute for each code object aspect, and even flags, # pylint: disable=too-many-arguments,too-many-instance-attributes __slots__ = ( "co_name", "co_kind", "co_varnames", "co_argcount", "co_freevars", "co_posonlyargcount", "co_kwonlyargcount", "co_has_starlist", "co_has_stardict", "filename", "line_number", "future_spec", "new_locals", "is_optimized", ) @counted_init def __init__( self, co_name, co_kind, co_varnames, co_freevars, co_argcount, co_posonlyargcount, co_kwonlyargcount, co_has_starlist, co_has_stardict, co_filename, co_lineno, future_spec, co_new_locals=None, co_is_optimized=None, ): # pylint: disable=I0021,too-many-locals self.co_name = co_name self.co_kind = co_kind self.future_spec = future_spec assert future_spec # Strings happens from XML parsing, make sure to convert them. if type(co_varnames) is str: if co_varnames == "": co_varnames = () else: co_varnames = co_varnames.split(",") if type(co_freevars) is str: if co_freevars == "": co_freevars = () else: co_freevars = co_freevars.split(",") if type(co_has_starlist) is not bool: co_has_starlist = co_has_starlist != "False" if type(co_has_stardict) is not bool: co_has_stardict = co_has_stardict != "False" self.co_varnames = tuple(co_varnames) self.co_freevars = tuple(co_freevars) self.co_argcount = int(co_argcount) self.co_posonlyargcount = int(co_posonlyargcount) self.co_kwonlyargcount = int(co_kwonlyargcount) self.co_has_starlist = co_has_starlist self.co_has_stardict = co_has_stardict self.filename = co_filename self.line_number = int(co_lineno) if type(co_has_starlist) is not bool: co_new_locals = co_new_locals != "False" if type(co_has_starlist) is not bool: co_is_optimized = co_is_optimized != "False" self.new_locals = co_new_locals self.is_optimized = co_is_optimized if isCountingInstances(): __del__ = counted_del() def __repr__(self): return ( """\ """ % self.getDetails() ) def getDetails(self): return { "co_name": self.co_name, "co_kind": self.co_kind, "co_varnames": ",".join(self.co_varnames), "co_freevars": ",".join(self.co_freevars), "co_argcount": self.co_argcount, "co_posonlyargcount": self.co_posonlyargcount, "co_kwonlyargcount": self.co_kwonlyargcount, "co_has_starlist": self.co_has_starlist, "co_has_stardict": self.co_has_stardict, "co_filename": self.filename, "co_lineno": self.line_number, "co_new_locals": self.new_locals, "co_is_optimized": self.is_optimized, "code_flags": ",".join(self.future_spec.asFlags()), } def getCodeObjectKind(self): return self.co_kind def updateLocalNames(self, local_names, freevar_names): """Move detected local variables after closure has been decided.""" self.co_varnames += tuple( local_name for local_name in local_names if local_name not in self.co_varnames # TODO: This is actually a bug, but we have a hard time without it to know # frame locals easily. We use this in compiled function run time, that all # variables, including closure variables are found there. This would have to # be cleaned up, for potentially little gain. # if local_name not in freevar_names ) self.co_freevars = tuple(freevar_names) def removeFreeVarname(self, freevar_name): self.co_freevars = tuple( var_name for var_name in self.co_freevars if var_name != freevar_name ) def setFlagIsOptimizedValue(self, value): self.is_optimized = value def getFlagIsOptimizedValue(self): return self.is_optimized def setFlagNewLocalsValue(self, value): self.new_locals = value def getFlagNewLocalsValue(self): return self.new_locals def getFutureSpec(self): return self.future_spec def getVarNames(self): return self.co_varnames def getFreeVarNames(self): return self.co_freevars def getArgumentCount(self): return self.co_argcount def getPosOnlyParameterCount(self): return self.co_posonlyargcount def getKwOnlyParameterCount(self): return self.co_kwonlyargcount def getCodeObjectName(self): return self.co_name def hasStarListArg(self): return self.co_has_starlist def hasStarDictArg(self): return self.co_has_stardict def getFilename(self): return self.filename def getLineNumber(self): return self.line_number Nuitka-0.6.19.1/nuitka/nodes/VariableRefNodes.py0000600000372100037210000006440414166627112026427 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for variable references. These represent all variable references in the node tree. Can be in assignments and its expressions, changing the meaning of course dramatically. """ from nuitka import Builtins, Variables from nuitka.ModuleRegistry import getOwnerFromCodeName from nuitka.PythonVersions import python_version from .DictionaryNodes import ( ExpressionDictOperationIn, ExpressionDictOperationItem, ExpressionDictOperationNotIn, StatementDictOperationRemove, StatementDictOperationSet, ) from .ExpressionBases import ExpressionBase, ExpressionNoSideEffectsMixin from .ModuleAttributeNodes import ( ExpressionModuleAttributeLoaderRef, ExpressionModuleAttributeNameRef, ExpressionModuleAttributePackageRef, ExpressionModuleAttributeSpecRef, ) from .NodeMakingHelpers import ( makeRaiseExceptionReplacementExpression, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, ) from .shapes.StandardShapes import tshape_unknown class ExpressionVariableNameRef(ExpressionBase): """These are used before the actual variable object is known from VariableClosure.""" kind = "EXPRESSION_VARIABLE_NAME_REF" __slots__ = "variable_name", "provider" def __init__(self, provider, variable_name, source_ref): assert not provider.isExpressionOutlineBody(), source_ref ExpressionBase.__init__(self, source_ref=source_ref) self.variable_name = variable_name self.provider = provider def finalize(self): del self.parent del self.provider @staticmethod def isExpressionVariableNameRef(): return True def getDetails(self): return {"variable_name": self.variable_name, "provider": self.provider} def getVariableName(self): return self.variable_name def computeExpressionRaw(self, trace_collection): return self, None, None @staticmethod def needsFallback(): return True class ExpressionVariableLocalNameRef(ExpressionVariableNameRef): """These are used before the actual variable object is known from VariableClosure. The special thing about this as opposed to ExpressionVariableNameRef is that these must remain local names and cannot fallback to outside scopes. This is used for "__annotations__". """ kind = "EXPRESSION_VARIABLE_LOCAL_NAME_REF" @staticmethod def needsFallback(): return False class ExpressionVariableRefBase(ExpressionBase): # Base classes can be abstract, pylint: disable=abstract-method __slots__ = "variable", "variable_trace" def __init__(self, variable, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.variable = variable self.variable_trace = None def finalize(self): del self.parent del self.variable del self.variable_trace def getVariableName(self): return self.variable.getName() def getVariable(self): return self.variable def getVariableTrace(self): return self.variable_trace def getTypeShape(self): if self.variable_trace is None: return tshape_unknown else: return self.variable_trace.getTypeShape() def onContentEscapes(self, trace_collection): trace_collection.onVariableContentEscapes(self.variable) def computeExpressionLen(self, len_node, trace_collection): if self.variable_trace is not None and self.variable_trace.isAssignTrace(): value = self.variable_trace.getAssignNode().subnode_source shape = value.getValueShape() has_len = shape.hasShapeSlotLen() if has_len is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="object of type '%s' has no len()", operation="len", original_node=len_node, value_node=self, ) elif has_len is True: iter_length = value.getIterationLength() if iter_length is not None: from .ConstantRefNodes import makeConstantRefNode result = makeConstantRefNode( constant=int(iter_length), # make sure to downcast long source_ref=len_node.getSourceReference(), ) return ( result, "new_constant", "Predicted 'len' result of variable.", ) # The variable itself is to be considered escaped. trace_collection.markActiveVariableAsEscaped(self.variable) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return len_node, None, None def computeExpressionAttribute(self, lookup_node, attribute_name, trace_collection): if self.variable_trace is not None: attribute_node = self.variable_trace.getAttributeNode() if attribute_node is not None: # The variable itself is to be considered escaped no matter what, since # we don't know exactly what the attribute is used for later on. We would # have to attach the variable to the result created here in such a way, # that e.g. calling it will make it escaped only. trace_collection.markActiveVariableAsEscaped(self.variable) return attribute_node.computeExpressionAttribute( lookup_node=lookup_node, attribute_name=attribute_name, trace_collection=trace_collection, ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # The variable itself is to be considered escaped. trace_collection.markActiveVariableAsEscaped(self.variable) if not self.isKnownToHaveAttribute(attribute_name): trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def mayRaiseExceptionAttributeLookup(self, exception_type, attribute_name): return not self.isKnownToHaveAttribute(attribute_name) def isKnownToHaveAttribute(self, attribute_name): if self.variable_trace is not None: attribute_node = self.variable_trace.getAttributeNode() if attribute_node is not None: return attribute_node.isKnownToHaveAttribute(attribute_name) return None def computeExpressionImportName(self, import_node, import_name, trace_collection): # TODO: For include modules, something might be possible here. return self.computeExpressionAttribute( lookup_node=import_node, attribute_name=import_name, trace_collection=trace_collection, ) def computeExpressionComparisonIn(self, in_node, value_node, trace_collection): tags = None message = None # Any code could be run, note that. trace_collection.onControlFlowEscape(in_node) if self.variable_trace.hasShapeDictionaryExact(): tags = "new_expression" message = """\ Check '%s' on dictionary lowered to dictionary '%s'.""" % ( in_node.comparator, in_node.comparator, ) if in_node.comparator == "In": in_node = ExpressionDictOperationIn( key=value_node, dict_arg=self, source_ref=in_node.getSourceReference(), ) else: in_node = ExpressionDictOperationNotIn( key=value_node, dict_arg=self, source_ref=in_node.getSourceReference(), ) # Any exception may be raised. if in_node.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return in_node, tags, message def computeExpressionSetSubscript( self, set_node, subscript, value_node, trace_collection ): tags = None message = None # By default, an subscript may change everything about the lookup # source. if self.variable_trace.hasShapeDictionaryExact(): result = StatementDictOperationSet( dict_arg=self, key=subscript, value=value_node, source_ref=set_node.getSourceReference(), ) change_tags = "new_statements" change_desc = """\ Subscript assignment to dictionary lowered to dictionary assignment.""" trace_collection.removeKnowledge(self) result2, change_tags2, change_desc2 = result.computeStatementOperation( trace_collection ) if result2 is not result: trace_collection.signalChange( tags=change_tags, source_ref=self.source_ref, message=change_desc, ) return result2, change_tags2, change_desc2 else: return result, change_tags, change_desc trace_collection.removeKnowledge(self) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception might be raised. if set_node.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return set_node, tags, message def computeExpressionDelSubscript(self, del_node, subscript, trace_collection): tags = None message = None if self.variable_trace.hasShapeDictionaryExact(): result = StatementDictOperationRemove( dict_arg=self, key=subscript, source_ref=del_node.getSourceReference(), ) change_tags = "new_statements" change_desc = """\ Subscript del to dictionary lowered to dictionary del.""" trace_collection.removeKnowledge(self) result2, change_tags2, change_desc2 = result.computeStatementOperation( trace_collection ) if result2 is not result: trace_collection.signalChange( tags=change_tags, source_ref=self.source_ref, message=change_desc, ) return result2, change_tags2, change_desc2 else: return result, change_tags, change_desc # By default, an subscript may change everything about the lookup # source. # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception might be raised. if del_node.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return del_node, tags, message def computeExpressionSubscript(self, lookup_node, subscript, trace_collection): tags = None message = None if self.variable_trace.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionDictOperationItem( dict_arg=self, key=subscript, source_ref=lookup_node.getSourceReference(), ), change_tags="new_expression", change_desc="""\ Subscript look-up to dictionary lowered to dictionary look-up.""", ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception might be raised. if lookup_node.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, tags, message def _applyReplacement(self, trace_collection, replacement): trace_collection.signalChange( "new_expression", self.source_ref, "Value propagated for '%s' from '%s'." % (self.variable.getName(), replacement.getSourceReference().getAsString()), ) # Special case for in-place assignments. if self.parent.isExpressionOperationInplace(): statement = self.parent.parent if statement.isStatementAssignmentVariable(): statement.unmarkAsInplaceSuspect() # Need to compute the replacement still. return replacement.computeExpressionRaw(trace_collection) _hard_names = ("dir", "eval", "exec", "execfile", "locals", "vars", "super") class ExpressionVariableRef(ExpressionVariableRefBase): kind = "EXPRESSION_VARIABLE_REF" __slots__ = () def __init__(self, variable, source_ref): assert variable is not None ExpressionVariableRefBase.__init__( self, variable=variable, source_ref=source_ref ) @staticmethod def isExpressionVariableRef(): return True def getDetails(self): return {"variable": self.variable} def getDetailsForDisplay(self): return { "variable_name": self.variable.getName(), "owner": self.variable.getOwner().getCodeName(), } @classmethod def fromXML(cls, provider, source_ref, **args): assert cls is ExpressionVariableRef, cls owner = getOwnerFromCodeName(args["owner"]) variable = owner.getProvidedVariable(args["variable_name"]) return cls(variable=variable, source_ref=source_ref) @staticmethod def isTargetVariableRef(): return False def getVariable(self): return self.variable def setVariable(self, variable): assert isinstance(variable, Variables.Variable), repr(variable) self.variable = variable def computeExpressionRaw(self, trace_collection): # Terribly detailed, pylint: disable=too-many-branches,too-many-statements variable = self.variable assert variable is not None self.variable_trace = trace_collection.getVariableCurrentTrace( variable=variable ) replacement = self.variable_trace.getReplacementNode(self) if replacement is not None: return self._applyReplacement(trace_collection, replacement) if not self.variable_trace.mustHaveValue(): # TODO: This could be way more specific surely, either NameError or UnboundLocalError # could be decided from context. trace_collection.onExceptionRaiseExit(BaseException) if variable.isModuleVariable() and variable.hasDefiniteWrites() is False: variable_name = self.variable.getName() if variable_name in Builtins.builtin_exception_names: if not self.variable.getOwner().getLocalsScope().isEscaped(): from .BuiltinRefNodes import ExpressionBuiltinExceptionRef new_node = ExpressionBuiltinExceptionRef( exception_name=self.variable.getName(), source_ref=self.source_ref, ) change_tags = "new_builtin_ref" change_desc = """\ Module variable '%s' found to be built-in exception reference.""" % ( variable_name ) else: self.variable_trace.addUsage() new_node = self change_tags = None change_desc = None elif variable_name in Builtins.builtin_names: if ( variable_name in _hard_names or not self.variable.getOwner().getLocalsScope().isEscaped() ): from .BuiltinRefNodes import makeExpressionBuiltinRef new_node = makeExpressionBuiltinRef( builtin_name=variable_name, locals_scope=self.getFunctionsLocalsScope(), source_ref=self.source_ref, ) change_tags = "new_builtin_ref" change_desc = """\ Module variable '%s' found to be built-in reference.""" % ( variable_name ) else: self.variable_trace.addUsage() new_node = self change_tags = None change_desc = None elif variable_name == "__name__": new_node = ExpressionModuleAttributeNameRef( variable=variable, source_ref=self.source_ref ) change_tags = "new_expression" change_desc = """\ Replaced read-only module attribute '__name__' with module attribute reference.""" elif variable_name == "__package__": new_node = ExpressionModuleAttributePackageRef( variable=variable, source_ref=self.source_ref ) change_tags = "new_expression" change_desc = """\ Replaced read-only module attribute '__package__' with module attribute reference.""" elif variable_name == "__loader__" and python_version >= 0x300: new_node = ExpressionModuleAttributeLoaderRef( variable=variable, source_ref=self.source_ref ) change_tags = "new_expression" change_desc = """\ Replaced read-only module attribute '__loader__' with module attribute reference.""" elif variable_name == "__spec__" and python_version >= 0x340: new_node = ExpressionModuleAttributeSpecRef( variable=variable, source_ref=self.source_ref ) change_tags = "new_expression" change_desc = """\ Replaced read-only module attribute '__spec__' with module attribute reference.""" else: self.variable_trace.addUsage() # Probably should give a warning once about it. new_node = self change_tags = None change_desc = None return new_node, change_tags, change_desc self.variable_trace.addUsage() if self.variable_trace.mustNotHaveValue(): assert self.variable.isLocalVariable(), self.variable variable_name = self.variable.getName() result = makeRaiseExceptionReplacementExpression( expression=self, exception_type="UnboundLocalError", exception_value="""local variable '%s' referenced before assignment""" % variable_name, ) return ( result, "new_raise", "Variable access of not initialized variable '%s'" % variable_name, ) return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): # The called and the arguments escape for good. self.onContentEscapes(trace_collection) if call_args is not None: call_args.onContentEscapes(trace_collection) if call_kw is not None: call_kw.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) if ( self.variable.getName() in _hard_names and self.variable.isIncompleteModuleVariable() ): # Just inform the collection that all escaped. trace_collection.onLocalsUsage(locals_scope=self.getFunctionsLocalsScope()) return call_node, None, None def hasShapeDictionaryExact(self): return ( self.variable_trace is not None and self.variable_trace.hasShapeDictionaryExact() ) def hasShapeStrExact(self): return ( self.variable_trace is not None and self.variable_trace.hasShapeStrExact() ) def hasShapeUnicodeExact(self): return ( self.variable_trace is not None and self.variable_trace.hasShapeUnicodeExact() ) def getTruthValue(self): return self.variable_trace.getTruthValue() def getComparisonValue(self): return self.variable_trace.getComparisonValue() @staticmethod def isKnownToBeIterable(count): return None def mayHaveSideEffects(self): return not self.variable_trace.mustHaveValue() def mayRaiseException(self, exception_type): return self.variable_trace is None or not self.variable_trace.mustHaveValue() def mayRaiseExceptionBool(self, exception_type): return ( self.variable_trace is None or not self.variable_trace.mustHaveValue() or not self.variable_trace.getTypeShape().hasShapeSlotBool() ) def getFunctionsLocalsScope(self): return self.getParentVariableProvider().getLocalsScope() class ExpressionVariableOrBuiltinRef(ExpressionVariableRef): kind = "EXPRESSION_VARIABLE_OR_BUILTIN_REF" __slots__ = ("locals_scope",) def __init__(self, variable, locals_scope, source_ref): ExpressionVariableRef.__init__(self, variable=variable, source_ref=source_ref) self.locals_scope = locals_scope def getDetails(self): return {"variable": self.variable, "locals_scope": self.locals_scope} def getFunctionsLocalsScope(self): return self.locals_scope def makeExpressionVariableRef(variable, locals_scope, source_ref): if variable.getName() in _hard_names: return ExpressionVariableOrBuiltinRef( variable=variable, locals_scope=locals_scope, source_ref=source_ref ) else: return ExpressionVariableRef(variable=variable, source_ref=source_ref) # Note: Temporary variable references are to be guarantueed to not raise # therefore no side effects. class ExpressionTempVariableRef( ExpressionNoSideEffectsMixin, ExpressionVariableRefBase ): kind = "EXPRESSION_TEMP_VARIABLE_REF" def __init__(self, variable, source_ref): assert variable.isTempVariable() ExpressionVariableRefBase.__init__( self, variable=variable, source_ref=source_ref ) def getDetailsForDisplay(self): return { "temp_name": self.variable.getName(), "owner": self.variable.getOwner().getCodeName(), } def getDetails(self): return {"variable": self.variable} @classmethod def fromXML(cls, provider, source_ref, **args): assert cls is ExpressionTempVariableRef, cls owner = getOwnerFromCodeName(args["owner"]) variable = owner.getTempVariable(None, args["temp_name"]) return cls(variable=variable, source_ref=source_ref) @staticmethod def isTargetVariableRef(): return False def computeExpressionRaw(self, trace_collection): self.variable_trace = trace_collection.getVariableCurrentTrace( variable=self.variable ) replacement = self.variable_trace.getReplacementNode(self) if replacement is not None: return self._applyReplacement(trace_collection, replacement) self.variable_trace.addUsage() # Nothing to do here. return self, None, None def computeExpressionNext1(self, next_node, trace_collection): may_not_raise = False if self.variable_trace.isAssignTrace(): value = self.variable_trace.getAssignNode().subnode_source # TODO: Add iteration handles to trace collections instead. current_index = trace_collection.getIteratorNextCount(value) trace_collection.onIteratorNext(value) if value.hasShapeSlotNext(): if ( current_index is not None # TODO: Change to iteration handles. and value.isKnownToBeIterableAtMin(current_index + 1) ): may_not_raise = True # TODO: Make use of this # candidate = value.getIterationValue(current_index) # if False: # and value.canPredictIterationValues() # return ( # candidate, # "new_expression", # "Predicted 'next' value from iteration.", # ) else: # TODO: Could ask it about exception predictability for that case # or warn about it at least. pass # assert False, value self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return may_not_raise, (next_node, None, None) def mayRaiseExceptionImportName(self, exception_type, import_name): if self.variable_trace is not None and self.variable_trace.isAssignTrace(): return self.variable_trace.getAssignNode().subnode_source.mayRaiseExceptionImportName( exception_type, import_name ) else: return True @staticmethod def isKnownToBeIterableAtMin(count): # TODO: See through the variable current trace. return None Nuitka-0.6.19.1/nuitka/nodes/NodeMetaClasses.py0000600000372100037210000001157014166627112026262 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node meta classes. This provides meta classes for nodes, currently only one. These do all kinds of checks, and add methods automatically. """ from abc import ABCMeta from nuitka.__past__ import intern from nuitka.Errors import NuitkaNodeDesignError def _checkBases(name, bases): # Avoid duplicate base classes. assert len(bases) == len(set(bases)), (name, bases) # Insist on mixins being in proper place for inheritance. last_mixin = None for base in bases: base_name = base.__name__ is_mixin = base_name.endswith("Mixin") if is_mixin and last_mixin is False: raise NuitkaNodeDesignError( name, "Mixins must come first in base classes.", bases ) last_mixin = is_mixin if base is not object and "__slots__" not in base.__dict__: raise NuitkaNodeDesignError(name, "All bases must have __slots__.", base) class NodeCheckMetaClass(ABCMeta): kinds = {} # This is in conflict with Pylint 1.9.2 used for Python2, it # should be "mcls" for one and "cls" for the other. # pylint: disable=I0021,bad-mcs-classmethod-argument def __new__(cls, name, bases, dictionary): # pylint: disable=I0021,arguments-differ _checkBases(name, bases) if "__slots__" not in dictionary: dictionary["__slots__"] = () if "named_child" in dictionary: named_child = dictionary["named_child"] if type(named_child) is not str: raise NuitkaNodeDesignError( name, "Class named_child attribute must be string not", type(named_child), ) dictionary["__slots__"] += (intern("subnode_" + dictionary["named_child"]),) if "named_children" in dictionary: if len(dictionary["named_children"]) <= 1: raise NuitkaNodeDesignError( name, "Use ExpressionChildHaving for one child node classes" ) assert type(dictionary["named_children"]) is tuple dictionary["__slots__"] += tuple( intern("subnode_" + named_child) for named_child in dictionary["named_children"] ) # Not a method: if "checker" in dictionary: dictionary["checker"] = staticmethod(dictionary["checker"]) # false alarm, pylint: disable=I0021,too-many-function-args return ABCMeta.__new__(cls, name, bases, dictionary) def __init__(cls, name, bases, dictionary): # @NoSelf if not name.endswith("Base"): if "kind" not in dictionary: raise NuitkaNodeDesignError(name, "Must provide class variable 'kind'") kind = dictionary["kind"] assert type(kind) is str, name assert kind not in NodeCheckMetaClass.kinds, (name, kind) NodeCheckMetaClass.kinds[kind] = cls NodeCheckMetaClass.kinds[name] = cls kind_to_name_part = "".join([x.capitalize() for x in kind.split("_")]) assert name.endswith(kind_to_name_part), (name, kind_to_name_part) # Automatically add checker methods for everything to the common # base class checker_method = "is" + kind_to_name_part # TODO: How about making these two functions, one to statically # return True and False, and put one in the base class, and one # in the new class, would be slightly faster. def checkKind(self): return self.kind == kind # Add automatic checker methods to the node base class. from .NodeBases import NodeBase if not hasattr(NodeBase, checker_method): setattr(NodeBase, checker_method, checkKind) ABCMeta.__init__(cls, name, bases, dictionary) # For every node type, there is a test, and then some more members, # For Python2/3 compatible source, we create a base class that has the metaclass # used and doesn't require making a syntax choice. NodeMetaClassBase = NodeCheckMetaClass( "NodeMetaClassBase", (object,), {"__slots__": ()} ) Nuitka-0.6.19.1/nuitka/nodes/ContainerMakingNodes.py0000600000372100037210000003045214167275603027317 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes that build containers. """ import functools from abc import abstractmethod from nuitka.PythonVersions import needsSetLiteralReverseInsertion from .ConstantRefNodes import ( ExpressionConstantListEmptyRef, ExpressionConstantSetEmptyRef, ExpressionConstantTupleEmptyRef, makeConstantRefNode, ) from .ExpressionBases import ExpressionChildTupleHavingBase from .ExpressionShapeMixins import ( ExpressionListShapeExactMixin, ExpressionSetShapeExactMixin, ExpressionTupleShapeExactMixin, ) from .IterationHandles import ListAndTupleContainerMakingIterationHandle from .NodeBases import SideEffectsFromChildrenMixin from .NodeMakingHelpers import ( makeStatementOnlyNodesFromExpressions, wrapExpressionWithSideEffects, ) class ExpressionMakeSequenceBase( SideEffectsFromChildrenMixin, ExpressionChildTupleHavingBase ): __slots__ = ("sequence_kind",) named_child = "elements" def __init__(self, sequence_kind, elements, source_ref): assert elements for element in elements: assert element.isExpression(), element self.sequence_kind = sequence_kind.lower() ExpressionChildTupleHavingBase.__init__( self, value=tuple(elements), source_ref=source_ref ) @staticmethod def isExpressionMakeSequence(): return True @abstractmethod def getSimulator(self): """The simulator for the container making, for overload.""" def computeExpression(self, trace_collection): elements = self.subnode_elements are_constants = True for count, element in enumerate(elements): if element.willRaiseException(BaseException): result = wrapExpressionWithSideEffects( side_effects=elements[:count], new_node=element, old_node=self ) return result, "new_raise", "Sequence creation raises exception" if are_constants and not element.isCompileTimeConstant(): are_constants = False if are_constants is False: return self, None, None simulator = self.getSimulator() assert simulator is not None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( element.getCompileTimeConstant() for element in elements ), description="%s with constant arguments." % simulator.__name__.capitalize(), user_provided=True, ) def isKnownToBeIterable(self, count): return count is None or count == len(self.subnode_elements) def isKnownToBeIterableAtMin(self, count): return count <= len(self.subnode_elements) def getIterationValue(self, count): return self.subnode_elements[count] def getIterationValueRange(self, start, stop): return self.subnode_elements[start:stop] @staticmethod def canPredictIterationValues(): return True def getIterationValues(self): return self.subnode_elements def getIterationHandle(self): return ListAndTupleContainerMakingIterationHandle(self.subnode_elements) @staticmethod def getTruthValue(): return True def mayRaiseException(self, exception_type): for element in self.subnode_elements: if element.mayRaiseException(exception_type): return True return False def computeExpressionDrop(self, statement, trace_collection): result = makeStatementOnlyNodesFromExpressions( expressions=self.subnode_elements ) del self.parent return ( result, "new_statements", """\ Removed sequence creation for unused sequence.""", ) def onContentEscapes(self, trace_collection): for element in self.subnode_elements: element.onContentEscapes(trace_collection) def makeExpressionMakeTuple(elements, source_ref): if elements: return ExpressionMakeTuple(elements, source_ref) else: # TODO: Get rid of user provided for empty tuple refs, makes no sense. return ExpressionConstantTupleEmptyRef( user_provided=False, source_ref=source_ref ) def makeExpressionMakeTupleOrConstant(elements, user_provided, source_ref): for element in elements: # TODO: Compile time constant ought to be the criterion. if not element.isExpressionConstantRef(): result = makeExpressionMakeTuple(elements, source_ref) break else: result = makeConstantRefNode( constant=tuple(element.getCompileTimeConstant() for element in elements), user_provided=user_provided, source_ref=source_ref, ) if elements: result.setCompatibleSourceReference( source_ref=elements[-1].getCompatibleSourceReference() ) return result class ExpressionMakeTuple(ExpressionTupleShapeExactMixin, ExpressionMakeSequenceBase): kind = "EXPRESSION_MAKE_TUPLE" def __init__(self, elements, source_ref): ExpressionMakeSequenceBase.__init__( self, sequence_kind="TUPLE", elements=elements, source_ref=source_ref ) @staticmethod def getSimulator(): return tuple def getIterationLength(self): return len(self.subnode_elements) def makeExpressionMakeList(elements, source_ref): if elements: return ExpressionMakeList(elements, source_ref) else: # TODO: Get rid of user provided for empty list refs, makes no sense. return ExpressionConstantListEmptyRef( user_provided=False, source_ref=source_ref ) def makeExpressionMakeListOrConstant(elements, user_provided, source_ref): assert type(elements) is list for element in elements: # TODO: Compile time constant ought to be the criterion. if not element.isExpressionConstantRef(): result = makeExpressionMakeList(elements, source_ref) break else: result = makeConstantRefNode( constant=[element.getCompileTimeConstant() for element in elements], user_provided=user_provided, source_ref=source_ref, ) if elements: result.setCompatibleSourceReference( source_ref=elements[-1].getCompatibleSourceReference() ) return result class ExpressionMakeList(ExpressionListShapeExactMixin, ExpressionMakeSequenceBase): kind = "EXPRESSION_MAKE_LIST" def __init__(self, elements, source_ref): ExpressionMakeSequenceBase.__init__( self, sequence_kind="LIST", elements=elements, source_ref=source_ref ) @staticmethod def getSimulator(): return list def getIterationLength(self): return len(self.subnode_elements) def computeExpressionIter1(self, iter_node, trace_collection): result = ExpressionMakeTuple( elements=self.subnode_elements, source_ref=self.source_ref ) self.parent.replaceChild(self, result) del self.parent return ( iter_node, "new_expression", """\ Iteration over list lowered to iteration over tuple.""", ) class ExpressionMakeSet(ExpressionSetShapeExactMixin, ExpressionMakeSequenceBase): kind = "EXPRESSION_MAKE_SET" def __init__(self, elements, source_ref): ExpressionMakeSequenceBase.__init__( self, sequence_kind="SET", elements=elements, source_ref=source_ref ) @staticmethod def getSimulator(): return set def getIterationLength(self): element_count = len(self.subnode_elements) # Hashing and equality may consume elements of the produced set. if element_count >= 2: return None else: return element_count @staticmethod def getIterationMinLength(): # Hashing and equality may consume elements of the produced set. return 1 def computeExpression(self, trace_collection): # For sets, we need to consider elements = self.subnode_elements are_constants = True are_hashable = True for count, element in enumerate(elements): if element.willRaiseException(BaseException): result = wrapExpressionWithSideEffects( side_effects=elements[:count], new_node=element, old_node=self ) return result, "new_raise", "Sequence creation raises exception" if are_constants and not element.isCompileTimeConstant(): are_constants = False if are_hashable and not element.isKnownToBeHashable(): are_hashable = False if not are_hashable and not are_constants: break if not are_constants: if not are_hashable: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None simulator = self.getSimulator() assert simulator is not None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( element.getCompileTimeConstant() for element in elements ), description="%s with constant arguments." % simulator.__name__.capitalize(), user_provided=True, ) def mayRaiseException(self, exception_type): for element in self.subnode_elements: if not element.isKnownToBeHashable(): return True if element.mayRaiseException(exception_type): return True return False def computeExpressionIter1(self, iter_node, trace_collection): result = ExpressionMakeTuple( elements=self.subnode_elements, source_ref=self.source_ref ) self.parent.replaceChild(self, result) del self.parent return ( iter_node, "new_expression", """\ Iteration over set lowered to iteration over tuple.""", ) needs_set_literal_reverse = needsSetLiteralReverseInsertion() def makeExpressionMakeSetLiteral(elements, source_ref): if elements: if needs_set_literal_reverse: return ExpressionMakeSetLiteral(elements, source_ref) else: return ExpressionMakeSet(elements, source_ref) else: # TODO: Get rid of user provided for empty set refs, makes no sense. return ExpressionConstantSetEmptyRef(user_provided=False, source_ref=source_ref) @functools.wraps(set) def reversed_set(value): return set(reversed(tuple(value))) def makeExpressionMakeSetLiteralOrConstant(elements, user_provided, source_ref): for element in elements: # TODO: Compile time constant ought to be the criterion. if not element.isExpressionConstantRef(): result = makeExpressionMakeSetLiteral(elements, source_ref) break else: # Need to reverse now if needed. if needs_set_literal_reverse: elements = tuple(reversed(elements)) result = makeConstantRefNode( constant=set(element.getCompileTimeConstant() for element in elements), user_provided=user_provided, source_ref=source_ref, ) if elements: result.setCompatibleSourceReference( source_ref=elements[-1].getCompatibleSourceReference() ) return result class ExpressionMakeSetLiteral(ExpressionMakeSet): kind = "EXPRESSION_MAKE_SET_LITERAL" @staticmethod def getSimulator(): return reversed_set Nuitka-0.6.19.1/nuitka/nodes/GlobalsLocalsNodes.py0000600000372100037210000001610014166627112026754 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Globals/locals/single arg dir nodes These nodes give access to variables, highly problematic, because using them, the code may change or access anything about them, so nothing can be trusted anymore, if we start to not know where their value goes. The "dir()" call without arguments is reformulated to locals or globals calls. """ from .ConstantRefNodes import makeConstantRefNode from .DictionaryNodes import ExpressionKeyValuePair, makeExpressionMakeDict from .ExpressionBases import ( ExpressionBase, ExpressionBuiltinSingleArgBase, ExpressionNoSideEffectsMixin, ) from .VariableRefNodes import ExpressionTempVariableRef, ExpressionVariableRef class ExpressionBuiltinGlobals(ExpressionNoSideEffectsMixin, ExpressionBase): kind = "EXPRESSION_BUILTIN_GLOBALS" def __init__(self, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent def computeExpressionRaw(self, trace_collection): return self, None, None class ExpressionBuiltinLocalsBase(ExpressionNoSideEffectsMixin, ExpressionBase): # Base classes can be abstract, pylint: disable=abstract-method __slots__ = ("variable_traces", "locals_scope") def __init__(self, locals_scope, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.variable_traces = None self.locals_scope = locals_scope def finalize(self): del self.locals_scope del self.variable_traces def getVariableTraces(self): return self.variable_traces def getLocalsScope(self): return self.locals_scope class ExpressionBuiltinLocalsUpdated(ExpressionBuiltinLocalsBase): kind = "EXPRESSION_BUILTIN_LOCALS_UPDATED" def __init__(self, locals_scope, source_ref): ExpressionBuiltinLocalsBase.__init__( self, locals_scope=locals_scope, source_ref=source_ref ) assert locals_scope is not None def computeExpressionRaw(self, trace_collection): # Just inform the collection that all escaped. self.variable_traces = trace_collection.onLocalsUsage(self.locals_scope) trace_collection.onLocalsDictEscaped(self.locals_scope) return self, None, None class ExpressionBuiltinLocalsRef(ExpressionBuiltinLocalsBase): kind = "EXPRESSION_BUILTIN_LOCALS_REF" def __init__(self, locals_scope, source_ref): ExpressionBuiltinLocalsBase.__init__( self, locals_scope=locals_scope, source_ref=source_ref ) def getLocalsScope(self): return self.locals_scope def computeExpressionRaw(self, trace_collection): if self.locals_scope.isMarkedForPropagation(): result = makeExpressionMakeDict( pairs=( ExpressionKeyValuePair( key=makeConstantRefNode( constant=variable_name, source_ref=self.source_ref ), value=ExpressionTempVariableRef( variable=variable, source_ref=self.source_ref ), source_ref=self.source_ref, ) for variable_name, variable in self.locals_scope.getPropagationVariables().items() ), source_ref=self.source_ref, ) new_result = result.computeExpressionRaw(trace_collection) assert new_result[0] is result self.finalize() return result, "new_expression", "Propagated locals dictionary reference." # Just inform the collection that all escaped unless it is abortative. if not self.getParent().isStatementReturn(): trace_collection.onLocalsUsage(locals_scope=self.locals_scope) return self, None, None class ExpressionBuiltinLocalsCopy(ExpressionBuiltinLocalsBase): kind = "EXPRESSION_BUILTIN_LOCALS_COPY" def computeExpressionRaw(self, trace_collection): # Just inform the collection that all escaped. self.variable_traces = trace_collection.onLocalsUsage( locals_scope=self.locals_scope ) for variable, variable_trace in self.variable_traces: if ( not variable_trace.mustHaveValue() and not variable_trace.mustNotHaveValue() ): return self, None, None # Other locals elsewhere. if variable_trace.getNameUsageCount() > 1: return self, None, None pairs = [] for variable, variable_trace in self.variable_traces: if variable_trace.mustHaveValue(): pairs.append( ExpressionKeyValuePair( key=makeConstantRefNode( constant=variable.getName(), user_provided=True, source_ref=self.source_ref, ), value=ExpressionVariableRef( variable=variable, source_ref=self.source_ref ), source_ref=self.source_ref, ) ) # Locals is sorted of course. def _sorted(pairs): names = [ variable.getName() for variable in self.locals_scope.getProvidedVariables() ] return tuple( sorted( pairs, key=lambda pair: names.index( pair.subnode_key.getCompileTimeConstant() ), ) ) result = makeExpressionMakeDict( pairs=_sorted(pairs), source_ref=self.source_ref ) return result, "new_expression", "Statically predicted locals dictionary." class ExpressionBuiltinDir1(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_BUILTIN_DIR1" def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict and this # should be using a slot, with "__dir__" being overloaded or not. # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/PrintNodes.py0000600000372100037210000001313114166627112025330 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Print nodes. Right now there is only the print statement, but in principle, there should also be the print function here. These perform output, which can be combined if possible, and could be detected to fail, which would be perfect. Predicting the behavior of 'print' is not trivial at all, due to many special cases. """ from .NodeBases import StatementChildHavingBase, StatementChildrenHavingBase from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, makeStatementsSequenceReplacementNode, wrapStatementWithSideEffects, ) class StatementPrintValue(StatementChildrenHavingBase): kind = "STATEMENT_PRINT_VALUE" named_children = ("dest", "value") def __init__(self, dest, value, source_ref): StatementChildrenHavingBase.__init__( self, values={"value": value, "dest": dest}, source_ref=source_ref ) assert value is not None def computeStatement(self, trace_collection): dest = trace_collection.onExpression( expression=self.subnode_dest, allow_none=True ) if dest is not None and dest.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if dest is not None and dest.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=dest, node=self ) return ( result, "new_raise", """\ Exception raise in 'print' statement destination converted to explicit raise.""", ) value = trace_collection.onExpression(expression=self.subnode_value) if value.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if value.willRaiseException(BaseException): if dest is not None: result = wrapStatementWithSideEffects( new_node=makeStatementExpressionOnlyReplacementNode( expression=value, node=self ), old_node=dest, ) else: result = makeStatementExpressionOnlyReplacementNode( expression=value, node=self ) return ( result, "new_raise", """\ Exception raise in 'print' statement arguments converted to explicit raise.""", ) trace_collection.onExceptionRaiseExit(BaseException) if dest is None: if value.isExpressionSideEffects(): self.setChild("value", value.subnode_expression) statements = [ makeStatementExpressionOnlyReplacementNode(side_effect, self) for side_effect in value.subnode_side_effects ] statements.append(self) result = makeStatementsSequenceReplacementNode( statements=statements, node=self ) return ( result, "new_statements", """\ Side effects printed item promoted to statements.""", ) if value.isCompileTimeConstant(): # Avoid unicode encoding issues. if not value.isExpressionConstantUnicodeRef(): new_value = value.getStrValue() assert new_value is not None, value if value is not new_value: self.setChild("value", new_value) return self, None, None @staticmethod def mayRaiseException(exception_type): # Output may always fail due to external reasons. return True class StatementPrintNewline(StatementChildHavingBase): kind = "STATEMENT_PRINT_NEWLINE" named_child = "dest" def __init__(self, dest, source_ref): StatementChildHavingBase.__init__(self, value=dest, source_ref=source_ref) def computeStatement(self, trace_collection): dest = trace_collection.onExpression( expression=self.subnode_dest, allow_none=True ) if dest is not None and dest.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if dest is not None and dest.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=dest, node=self ) return ( result, "new_raise", """\ Exception raise in 'print' statement destination converted to explicit raise.""", ) trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def mayRaiseException(exception_type): # Output may always fail due to external reasons. return True Nuitka-0.6.19.1/nuitka/nodes/BuiltinLenNodes.py0000600000372100037210000000371414166627112026307 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in iterator nodes. These play a role in for loops, and in unpacking. They can something be predicted to succeed or fail, in which case, code can become less complex. The length of things is an important optimization issue for these to be good. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ExpressionBuiltinSingleArgBase from .ExpressionShapeMixins import ExpressionIntOrLongExactMixin class ExpressionBuiltinLen( ExpressionIntOrLongExactMixin, ExpressionBuiltinSingleArgBase ): kind = "EXPRESSION_BUILTIN_LEN" builtin_spec = BuiltinParameterSpecs.builtin_len_spec def getIntegerValue(self): value = self.subnode_value if value.hasShapeSlotLen(): return value.getIterationLength() else: return None def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionLen( len_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): value = self.subnode_value if value.mayRaiseException(exception_type): return True return not value.getTypeShape().hasShapeSlotLen() Nuitka-0.6.19.1/nuitka/nodes/BuiltinDictNodes.py0000600000372100037210000001206114166627112026447 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'dict' built-in. """ from nuitka.specs.BuiltinParameterSpecs import builtin_dict_spec from .BuiltinIteratorNodes import ExpressionBuiltinIter1 from .ConstantRefNodes import makeConstantRefNode from .DictionaryNodes import ExpressionKeyValuePair, makeExpressionMakeDict from .ExpressionBases import ExpressionChildrenHavingBase from .ExpressionShapeMixins import ExpressionDictShapeExactMixin from .NodeMakingHelpers import wrapExpressionWithNodeSideEffects class ExpressionBuiltinDict( ExpressionDictShapeExactMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_DICT" named_children = ("pos_arg", "pairs") def __init__(self, pos_arg, pairs, source_ref): assert type(pos_arg) not in (tuple, list), source_ref assert type(pairs) in (tuple, list), source_ref ExpressionChildrenHavingBase.__init__( self, values={ "pos_arg": pos_arg, "pairs": tuple( ExpressionKeyValuePair( makeConstantRefNode(key, source_ref), value, value.getSourceReference(), ) for key, value in pairs ), }, source_ref=source_ref, ) def hasOnlyConstantArguments(self): pos_arg = self.subnode_pos_arg if pos_arg is not None and not pos_arg.isCompileTimeConstant(): return False for arg_pair in self.subnode_pairs: if not arg_pair.subnode_key.isCompileTimeConstant(): return False if not arg_pair.subnode_value.isCompileTimeConstant(): return False return True def computeExpression(self, trace_collection): pos_arg = self.subnode_pos_arg pairs = self.subnode_pairs if pos_arg is None: new_node = makeExpressionMakeDict( pairs=self.subnode_pairs, source_ref=self.source_ref ) # This cannot raise anymore than its arguments, as the keys will # be known as hashable, due to being Python parameters before. return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments.", ) pos_iteration_length = pos_arg.getIterationLength() if pos_iteration_length == 0: new_node = makeExpressionMakeDict( pairs=self.subnode_pairs, source_ref=self.source_ref ) # Maintain potential side effects from the positional arguments. new_node = wrapExpressionWithNodeSideEffects( old_node=ExpressionBuiltinIter1( value=pos_arg, source_ref=self.source_ref ), new_node=new_node, ) # Just in case, the iteration may do that. if not pos_arg.hasShapeSlotIter(): trace_collection.onExceptionRaiseExit(BaseException) return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments.", ) if ( pos_iteration_length is not None and pos_iteration_length + len(pairs) < 256 and self.hasOnlyConstantArguments() ): if pos_arg is not None: pos_args = (pos_arg,) else: pos_args = None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: builtin_dict_spec.simulateCall( (pos_args, self.subnode_pairs) ), description="Replace 'dict' call with constant arguments.", ) else: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): pos_arg = self.subnode_pos_arg # TODO: Determining if it's sufficient is not easy but possible. if pos_arg is not None: return True for arg_pair in self.subnode_pairs: if arg_pair.mayRaiseException(exception_type): return True return False Nuitka-0.6.19.1/nuitka/nodes/OutlineNodes.py0000600000372100037210000002775214166627112025671 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Outline nodes. We use them for re-formulations and for in-lining of code. They are expressions that get their value from return statements in their code body. They do not own anything by themselves. It's just a way of having try/finally for the expressions, or multiple returns, without running in a too different context. """ from .ConstantRefNodes import makeConstantRefNode from .ExceptionNodes import ExpressionRaiseException from .ExpressionBases import ExpressionChildHavingBase from .FunctionNodes import ExpressionFunctionBodyBase from .LocalsScopes import getLocalsDictHandle class ExpressionOutlineBody(ExpressionChildHavingBase): """Outlined expression code. This is for a call to a piece of code to be executed in a specific context. It contains an exclusively owned function body, that has no other references, and can be considered part of the calling context. It must return a value, to use as expression value. """ kind = "EXPRESSION_OUTLINE_BODY" named_child = "body" __slots__ = ("provider", "name", "temp_scope") @staticmethod def isExpressionOutlineBody(): return True def __init__(self, provider, name, source_ref, body=None): assert name != "" ExpressionChildHavingBase.__init__(self, value=body, source_ref=source_ref) self.provider = provider self.name = name self.temp_scope = None # Hack: This allows some APIs to work although this is not yet # officially a child yet. Important during building. self.parent = provider def getDetails(self): return {"provider": self.provider, "name": self.name} def getOutlineTempScope(self): # We use our own name as a temp_scope, cached from the parent, if the # scope is None. if self.temp_scope is None: self.temp_scope = self.provider.allocateTempScope(self.name) return self.temp_scope def allocateTempVariable(self, temp_scope, name, temp_type=None): if temp_scope is None: temp_scope = self.getOutlineTempScope() return self.provider.allocateTempVariable( temp_scope=temp_scope, name=name, temp_type=temp_type ) def allocateTempScope(self, name): # Let's scope the temporary scopes by the outline they come from. return self.provider.allocateTempScope(name=self.name + "$" + name) def getContainingClassDictCreation(self): return self.getParentVariableProvider().getContainingClassDictCreation() def computeExpressionRaw(self, trace_collection): owning_module = self.getParentModule() # Make sure the owning module is added to the used set. This is most # important for helper functions, or modules, which otherwise have # become unused. from nuitka.ModuleRegistry import addUsedModule addUsedModule( module=owning_module, using_module=None, usage_tag="outline", reason="Owning module", source_ref=self.source_ref, ) abort_context = trace_collection.makeAbortStackContext( catch_breaks=False, catch_continues=False, catch_returns=True, catch_exceptions=False, ) with abort_context: body = self.subnode_body result = body.computeStatementsSequence(trace_collection=trace_collection) if result is not body: self.setChild("body", result) body = result return_collections = trace_collection.getFunctionReturnCollections() if return_collections: trace_collection.mergeMultipleBranches(return_collections) first_statement = body.subnode_statements[0] if first_statement.isStatementReturnConstant(): return ( makeConstantRefNode( constant=first_statement.getConstant(), source_ref=first_statement.source_ref, ), "new_expression", "Outline '%s' is now simple return, use directly." % self.name, ) if first_statement.isStatementReturn(): return ( first_statement.subnode_expression, "new_expression", "Outline '%s' is now simple return, use directly." % self.name, ) if first_statement.isStatementRaiseException(): # Exception exit was already annotated, need not repeat it. result = ExpressionRaiseException( exception_type=first_statement.subnode_exception_type, exception_value=first_statement.subnode_exception_value, source_ref=first_statement.getSourceReference(), ) return ( result, "new_expression", "Outline is now exception raise, use directly.", ) # TODO: Function outline may become too trivial to outline and return # collections may tell us something. return self, None, None def mayRaiseException(self, exception_type): return self.subnode_body.mayRaiseException(exception_type) def willRaiseException(self, exception_type): return self.subnode_body.willRaiseException(exception_type) def getEntryPoint(self): """Entry point for code. Normally ourselves. Only outlines will refer to their parent which technically owns them. """ return self.provider.getEntryPoint() def getCodeName(self): return self.provider.getCodeName() class ExpressionOutlineFunctionBase(ExpressionFunctionBodyBase): """Outlined function code. This is for a call to a function to be called in-line to be executed in a specific context. It contains an exclusively owned function body, that has no other references, and can be considered part of the calling context. As normal function it must return a value, to use as expression value, but we know we only exist once. Once this has no frame, it can be changed to a mere outline expression. """ __slots__ = ("temp_scope", "locals_scope") def __init__(self, provider, name, body, code_prefix, source_ref): ExpressionFunctionBodyBase.__init__( self, provider=provider, name=name, body=body, code_prefix=code_prefix, flags=None, source_ref=source_ref, ) self.temp_scope = None self.locals_scope = None @staticmethod def isExpressionOutlineFunctionBase(): return True def getDetails(self): return {"name": self.name, "provider": self.provider} def getDetailsForDisplay(self): return {"name": self.name, "provider": self.provider.getCodeName()} def computeExpressionRaw(self, trace_collection): # Keep track of these, so they can provide what variables are to be # setup. trace_collection.addOutlineFunction(self) abort_context = trace_collection.makeAbortStackContext( catch_breaks=False, catch_continues=False, catch_returns=True, catch_exceptions=False, ) with abort_context: body = self.subnode_body result = body.computeStatementsSequence(trace_collection=trace_collection) if result is not body: self.setChild("body", result) body = result return_collections = trace_collection.getFunctionReturnCollections() if return_collections: trace_collection.mergeMultipleBranches(return_collections) first_statement = body.subnode_statements[0] if first_statement.isStatementReturnConstant(): return ( makeConstantRefNode( constant=first_statement.getConstant(), source_ref=first_statement.source_ref, ), "new_expression", "Outline function '%s' is now simple return, use directly." % self.name, ) if first_statement.isStatementReturn(): return ( first_statement.subnode_expression, "new_expression", "Outline function '%s' is now simple return, use directly." % self.name, ) if first_statement.isStatementRaiseException(): # Exception exit was already annotated, need not repeat it. result = ExpressionRaiseException( exception_type=first_statement.subnode_exception_type, exception_value=first_statement.subnode_exception_value, source_ref=first_statement.getSourceReference(), ) return ( result, "new_expression", "Outline function is now exception raise, use directly.", ) # TODO: Function outline may become too trivial to outline and return # collections may tell us something. return self, None, None def mayRaiseException(self, exception_type): return self.subnode_body.mayRaiseException(exception_type) def willRaiseException(self, exception_type): return self.subnode_body.willRaiseException(exception_type) def getTraceCollection(self): return self.provider.getTraceCollection() def getOutlineTempScope(self): # We use our own name as a temp_scope, cached from the parent, if the # scope is None. if self.temp_scope is None: self.temp_scope = self.provider.allocateTempScope(self.name) return self.temp_scope def allocateTempVariable(self, temp_scope, name, temp_type=None): if temp_scope is None: temp_scope = self.getOutlineTempScope() return self.provider.allocateTempVariable( temp_scope=temp_scope, name=name, temp_type=None ) def allocateTempScope(self, name): # Let's scope the temporary scopes by the outline they come from. return self.provider.allocateTempScope(name=self.name + "$" + name) def getEntryPoint(self): """Entry point for code. Normally ourselves. Only outlines will refer to their parent which technically owns them. """ return self.provider.getEntryPoint() def getClosureVariable(self, variable_name): # Simply try and get from our parent. return self.provider.getVariableForReference(variable_name=variable_name) def getLocalsScope(self): return self.locals_scope def isEarlyClosure(self): return self.provider.isEarlyClosure() def isUnoptimized(self): return self.provider.isUnoptimized() class ExpressionOutlineFunction(ExpressionOutlineFunctionBase): kind = "EXPRESSION_OUTLINE_FUNCTION" __slots__ = ("locals_scope",) def __init__(self, provider, name, source_ref, body=None): ExpressionOutlineFunctionBase.__init__( self, provider=provider, name=name, code_prefix="outline", body=body, source_ref=source_ref, ) self.locals_scope = getLocalsDictHandle( "locals_%s" % self.getCodeName(), "python_function", self ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinRangeNodes.py0000600000372100037210000004334714166627112026633 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node the calls to the 'range' built-in. This is a rather complex beast as it has many cases, is difficult to know if it's sizable enough to compute, and there are complex cases, where the bad result of it can be predicted still, and these are interesting for warnings. """ import math from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .ExpressionShapeMixins import ExpressionListShapeExactMixin from .IterationHandles import ( IterationHandleRange1, IterationHandleRange2, IterationHandleRange3, ) from .NodeMakingHelpers import makeConstantReplacementNode from .shapes.BuiltinTypeShapes import tshape_xrange class ExpressionBuiltinRangeMixin(ExpressionListShapeExactMixin): """Mixin class for range nodes with 1/2/3 arguments.""" # Mixins are required to slots __slots__ = () builtin_spec = BuiltinParameterSpecs.builtin_range_spec def getTruthValue(self): length = self.getIterationLength() if length is None: return None else: return length > 0 def mayHaveSideEffects(self): for child in self.getVisitableNodes(): if child.mayHaveSideEffects(): return True if child.getIntegerValue() is None: return True if python_version >= 0x270 and child.isExpressionConstantFloatRef(): return True return False def mayRaiseException(self, exception_type): for child in self.getVisitableNodes(): if child.mayRaiseException(exception_type): return True # TODO: Should take exception_type value into account here. if child.getIntegerValue() is None: return True if python_version >= 0x270 and child.isExpressionConstantFloatRef(): return True step = self.subnode_step # A step of 0 will raise. if step is not None and step.getIntegerValue() == 0: return True return False def computeBuiltinSpec(self, trace_collection, given_values): assert self.builtin_spec is not None, self if not self.builtin_spec.isCompileTimeComputable(given_values): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Raise exception known step 0. return self, None, None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin_spec.simulateCall(given_values), description="Built-in call to '%s' computed." % (self.builtin_spec.getName()), ) def computeExpressionIter1(self, iter_node, trace_collection): assert python_version < 0x300 # TODO: The xrange is always faster and more memory usage than range, so this makes no sense, to # use it as a source for any iteration, esp. as xrange is the Python3 only type that will be # best optimized. result = makeExpressionBuiltinXrange( low=self.subnode_low, high=self.subnode_high, step=self.subnode_step, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) del self.parent return ( iter_node, "new_expression", "Replaced 'range' with 'xrange' built-in call for iteration.", ) def canPredictIterationValues(self): return self.getIterationLength() is not None class ExpressionBuiltinRange1(ExpressionBuiltinRangeMixin, ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_RANGE1" named_child = "low" subnode_high = None subnode_step = None def __init__(self, low, source_ref): assert low is not None assert python_version < 0x300 ExpressionChildHavingBase.__init__(self, value=low, source_ref=source_ref) def computeExpression(self, trace_collection): low = self.subnode_low return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low,) ) def getIterationLength(self): low = self.subnode_low.getIntegerValue() if low is None: return None return max(0, low) def getIterationHandle(self): low = self.subnode_low.getIntegerValue() if low is None: return None return IterationHandleRange1(low, self.source_ref) def getIterationValue(self, element_index): length = self.getIterationLength() if length is None: return None if element_index > length: return None # TODO: Make sure to cast element_index to what CPython will give, for # now a downcast will do. return makeConstantReplacementNode( constant=int(element_index), node=self, user_provided=False ) def isKnownToBeIterable(self, count): return count is None or count == self.getIterationLength() class ExpressionBuiltinRange2( ExpressionBuiltinRangeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_RANGE2" named_children = ("low", "high") subnode_step = None def __init__(self, low, high, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"low": low, "high": high}, source_ref=source_ref ) builtin_spec = BuiltinParameterSpecs.builtin_range_spec def computeExpression(self, trace_collection): assert python_version < 0x300 low = self.subnode_low high = self.subnode_high return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low, high) ) def getIterationLength(self): low = self.subnode_low high = self.subnode_high low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None return max(0, high - low) def getIterationHandle(self): low = self.subnode_low.getIntegerValue() if low is None: return None high = self.subnode_high.getIntegerValue() if high is None: return None return IterationHandleRange2(low, high, self.source_ref) def getIterationValue(self, element_index): low = self.subnode_low high = self.subnode_high low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None result = low + element_index if result >= high: return None else: return makeConstantReplacementNode( constant=result, node=self, user_provided=False ) def isKnownToBeIterable(self, count): return count is None or count == self.getIterationLength() class ExpressionBuiltinRange3( ExpressionBuiltinRangeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_RANGE3" named_children = ("low", "high", "step") def __init__(self, low, high, step, source_ref): assert python_version < 0x300 ExpressionChildrenHavingBase.__init__( self, values={"low": low, "high": high, "step": step}, source_ref=source_ref ) builtin_spec = BuiltinParameterSpecs.builtin_range_spec def computeExpression(self, trace_collection): low = self.subnode_low high = self.subnode_high step = self.subnode_step return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low, high, step) ) def getIterationLength(self): low = self.subnode_low high = self.subnode_high step = self.subnode_step low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None step = step.getIntegerValue() if step is None: return None # Give up on this, will raise ValueError. if step == 0: return None if low < high: if step < 0: estimate = 0 else: estimate = math.ceil(float(high - low) / step) else: if step > 0: estimate = 0 else: estimate = math.ceil(float(high - low) / step) estimate = round(estimate) assert estimate >= 0 return int(estimate) def canPredictIterationValues(self): return self.getIterationLength() is not None def getIterationHandle(self): low = self.subnode_low.getIntegerValue() if low is None: return None high = self.subnode_high.getIntegerValue() if high is None: return None step = self.subnode_step.getIntegerValue() if step is None: return None # Give up on this, will raise ValueError. if step == 0: return None return IterationHandleRange3(low, high, step, self.source_ref) def getIterationValue(self, element_index): low = self.subnode_low.getIntegerValue() if low is None: return None high = self.subnode_high.getIntegerValue() if high is None: return None step = self.subnode_step.getIntegerValue() result = low + step * element_index if result >= high: return None else: return makeConstantReplacementNode( constant=result, node=self, user_provided=False ) def isKnownToBeIterable(self, count): return count is None or count == self.getIterationLength() class ExpressionBuiltinXrangeMixin(object): """Mixin class for xrange nodes with 1/2/3 arguments.""" # Mixins are required to slots __slots__ = () builtin_spec = BuiltinParameterSpecs.builtin_xrange_spec @staticmethod def getTypeShape(): return tshape_xrange def canPredictIterationValues(self): return self.getIterationLength() is not None def getTruthValue(self): length = self.getIterationLength() if length is None: return None else: return length > 0 def mayHaveSideEffects(self): for child in self.getVisitableNodes(): if child.mayHaveSideEffects(): return True if child.getIntegerValue() is None: return True return False def mayRaiseException(self, exception_type): for child in self.getVisitableNodes(): if child.mayRaiseException(exception_type): return True # TODO: Should take exception_type value into account here. if child.getIntegerValue() is None: return True step = self.subnode_step # A step of 0 will raise. if step is not None and step.getIntegerValue() == 0: return True return False def computeBuiltinSpec(self, trace_collection, given_values): assert self.builtin_spec is not None, self if not self.builtin_spec.isCompileTimeComputable(given_values): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Raise exception known step 0. return self, None, None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin_spec.simulateCall(given_values), description="Built-in call to '%s' computed." % (self.builtin_spec.getName()), ) def computeExpressionIter1(self, iter_node, trace_collection): # No exception will be raised on xrange iteration, but there is nothing to # lower for, virtual method: pylint: disable=no-self-use return iter_node, None, None class ExpressionBuiltinXrange1(ExpressionBuiltinXrangeMixin, ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_XRANGE1" named_child = "low" subnode_high = None subnode_step = None def __init__(self, low, source_ref): ExpressionChildHavingBase.__init__(self, value=low, source_ref=source_ref) def computeExpression(self, trace_collection): low = self.subnode_low # TODO: Optimize this if self.subnode_low.getIntegerValue() is Not None return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low,) ) def getIterationLength(self): low = self.subnode_low.getIntegerValue() if low is None: return None return max(0, low) def getIterationValue(self, element_index): length = self.getIterationLength() if length is None: return None if element_index > length: return None # TODO: Make sure to cast element_index to what CPython will give, for # now a downcast will do. return makeConstantReplacementNode( constant=int(element_index), node=self, user_provided=False ) class ExpressionBuiltinXrange2( ExpressionBuiltinXrangeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_XRANGE2" named_children = ("low", "high") subnode_step = None def __init__(self, low, high, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"low": low, "high": high}, source_ref=source_ref ) def computeExpression(self, trace_collection): low = self.subnode_low high = self.subnode_high return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low, high) ) def getIterationLength(self): low = self.subnode_low high = self.subnode_high low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None return max(0, high - low) def getIterationValue(self, element_index): low = self.subnode_low high = self.subnode_high low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None result = low + element_index if result >= high: return None else: return makeConstantReplacementNode( constant=result, node=self, user_provided=False ) class ExpressionBuiltinXrange3( ExpressionBuiltinXrangeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_XRANGE3" named_children = ("low", "high", "step") def __init__(self, low, high, step, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"low": low, "high": high, "step": step}, source_ref=source_ref ) def computeExpression(self, trace_collection): low = self.subnode_low high = self.subnode_high step = self.subnode_step return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(low, high, step) ) def getIterationLength(self): low = self.subnode_low high = self.subnode_high step = self.subnode_step low = low.getIntegerValue() if low is None: return None high = high.getIntegerValue() if high is None: return None step = step.getIntegerValue() if step is None: return None # Give up on this, will raise ValueError. if step == 0: return None if low < high: if step < 0: estimate = 0 else: estimate = math.ceil(float(high - low) / step) else: if step > 0: estimate = 0 else: estimate = math.ceil(float(high - low) / step) estimate = round(estimate) assert estimate >= 0 return int(estimate) def getIterationValue(self, element_index): low = self.subnode_low.getIntegerValue() if low is None: return None high = self.subnode_high.getIntegerValue() if high is None: return None step = self.subnode_step.getIntegerValue() result = low + step * element_index if result >= high: return None else: return makeConstantReplacementNode( constant=result, node=self, user_provided=False ) def makeExpressionBuiltinXrange(low, high, step, source_ref): if high is None: return ExpressionBuiltinXrange1(low=low, source_ref=source_ref) elif step is None: return ExpressionBuiltinXrange2(low=low, high=high, source_ref=source_ref) else: return ExpressionBuiltinXrange3( low=low, high=high, step=step, source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/nodes/ExceptionNodes.py0000600000372100037210000002510514166627112026176 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes related to raising and making exceptions. """ from .ExpressionBases import ( ExpressionBase, ExpressionChildrenHavingBase, ExpressionChildTupleHavingBase, ExpressionNoSideEffectsMixin, ) from .NodeBases import StatementBase, StatementChildrenHavingBase from .NodeMakingHelpers import makeStatementOnlyNodesFromExpressions class StatementRaiseExceptionMixin(object): # Mixins are required to also specify slots __slots__ = () @staticmethod def isStatementAborting(): return True @staticmethod def isStatementRaiseException(): return True class StatementRaiseException( StatementRaiseExceptionMixin, StatementChildrenHavingBase ): kind = "STATEMENT_RAISE_EXCEPTION" named_children = ( "exception_type", "exception_value", "exception_trace", "exception_cause", ) __slots__ = ("reraise_finally",) def __init__( self, exception_type, exception_value, exception_trace, exception_cause, source_ref, ): assert exception_type is not None if exception_type is None: assert exception_value is None if exception_value is None: assert exception_trace is None StatementChildrenHavingBase.__init__( self, values={ "exception_type": exception_type, "exception_value": exception_value, "exception_trace": exception_trace, "exception_cause": exception_cause, }, source_ref=source_ref, ) self.reraise_finally = False def computeStatement(self, trace_collection): exception_type = trace_collection.onExpression( expression=self.subnode_exception_type, allow_none=True ) # TODO: Limit by type. trace_collection.onExceptionRaiseExit(BaseException) if exception_type is not None and exception_type.willRaiseException( BaseException ): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=exception_type, node=self ) return ( result, "new_raise", """\ Explicit raise already raises implicitly building exception type.""", ) exception_value = trace_collection.onExpression( expression=self.subnode_exception_value, allow_none=True ) if exception_value is not None and exception_value.willRaiseException( BaseException ): result = makeStatementOnlyNodesFromExpressions( expressions=(exception_type, exception_value) ) return ( result, "new_raise", """\ Explicit raise already raises implicitly building exception value.""", ) exception_trace = trace_collection.onExpression( expression=self.subnode_exception_trace, allow_none=True ) if exception_trace is not None and exception_trace.willRaiseException( BaseException ): result = makeStatementOnlyNodesFromExpressions( expressions=(exception_type, exception_value, exception_trace) ) return ( result, "new_raise", """\ Explicit raise already raises implicitly building exception traceback.""", ) exception_cause = trace_collection.onExpression( expression=self.subnode_exception_cause, allow_none=True ) if exception_cause is not None and exception_cause.willRaiseException( BaseException ): result = makeStatementOnlyNodesFromExpressions( expressions=(exception_type, exception_cause) ) return ( result, "new_raise", """ Explicit raise already raises implicitly building exception cause.""", ) return self, None, None @staticmethod def needsFrame(): return True @staticmethod def getStatementNiceName(): return "exception raise statement" class StatementRaiseExceptionImplicit(StatementRaiseException): kind = "STATEMENT_RAISE_EXCEPTION_IMPLICIT" @staticmethod def getStatementNiceName(): return "implicit exception raise statement" class StatementReraiseException(StatementRaiseExceptionMixin, StatementBase): kind = "STATEMENT_RERAISE_EXCEPTION" def finalize(self): del self.parent def computeStatement(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None # TODO: Not actually true, leads to wrong frame attached if there is # no pending exception. @staticmethod def needsFrame(): return False @staticmethod def getStatementNiceName(): return "exception re-raise statement" class ExpressionRaiseException(ExpressionChildrenHavingBase): """This node type is only produced via optimization. CPython only knows exception raising as a statement, but often the raising of exceptions can be predicted to occur as part of an expression, which it replaces then. """ kind = "EXPRESSION_RAISE_EXCEPTION" named_children = ("exception_type", "exception_value") def __init__(self, exception_type, exception_value, source_ref): ExpressionChildrenHavingBase.__init__( self, values={ "exception_type": exception_type, "exception_value": exception_value, }, source_ref=source_ref, ) def willRaiseException(self, exception_type): # One thing is clear, it will raise. TODO: Match exception_type more # closely if it is predictable. return exception_type is BaseException def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def computeExpressionDrop(self, statement, trace_collection): result = self.asStatement() del self.parent return ( result, "new_raise", """\ Propagated implicit raise expression to raise statement.""", ) def asStatement(self): return StatementRaiseExceptionImplicit( exception_type=self.subnode_exception_type, exception_value=self.subnode_exception_value, exception_trace=None, exception_cause=None, source_ref=self.source_ref, ) class ExpressionBuiltinMakeException(ExpressionChildTupleHavingBase): kind = "EXPRESSION_BUILTIN_MAKE_EXCEPTION" named_child = "args" __slots__ = ("exception_name",) def __init__(self, exception_name, args, source_ref): ExpressionChildTupleHavingBase.__init__( self, value=tuple(args), source_ref=source_ref ) self.exception_name = exception_name def getDetails(self): return {"exception_name": self.exception_name} def getExceptionName(self): return self.exception_name def computeExpression(self, trace_collection): return self, None, None def mayRaiseException(self, exception_type): for arg in self.subnode_args: if arg.mayRaiseException(exception_type): return True return False class ExpressionBuiltinMakeExceptionImportError(ExpressionChildrenHavingBase): """Python3 ImportError dedicated node with extra arguments.""" kind = "EXPRESSION_BUILTIN_MAKE_EXCEPTION_IMPORT_ERROR" named_children = ("args", "name", "path") __slots__ = ("exception_name",) def __init__(self, exception_name, args, name, path, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"args": tuple(args), "name": name, "path": path}, source_ref=source_ref, ) self.exception_name = exception_name def getDetails(self): return {"exception_name": self.exception_name} def getExceptionName(self): return self.exception_name def computeExpression(self, trace_collection): return self, None, None def mayRaiseException(self, exception_type): for arg in self.subnode_args: if arg.mayRaiseException(exception_type): return True return False class ExpressionCaughtMixin(ExpressionNoSideEffectsMixin): """Common things for all caught exception references.""" __slots__ = () def finalize(self): del self.parent class ExpressionCaughtExceptionTypeRef(ExpressionCaughtMixin, ExpressionBase): kind = "EXPRESSION_CAUGHT_EXCEPTION_TYPE_REF" def __init__(self, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) def computeExpressionRaw(self, trace_collection): # TODO: Might be predictable based on the exception handler this is in. return self, None, None class ExpressionCaughtExceptionValueRef(ExpressionCaughtMixin, ExpressionBase): kind = "EXPRESSION_CAUGHT_EXCEPTION_VALUE_REF" def __init__(self, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) def computeExpressionRaw(self, trace_collection): # TODO: Might be predictable based on the exception handler this is in. return self, None, None class ExpressionCaughtExceptionTracebackRef(ExpressionCaughtMixin, ExpressionBase): kind = "EXPRESSION_CAUGHT_EXCEPTION_TRACEBACK_REF" def __init__(self, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) def computeExpressionRaw(self, trace_collection): return self, None, None Nuitka-0.6.19.1/nuitka/nodes/StatementNodes.py0000600000372100037210000002230314166627112026201 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for statements. """ from .NodeBases import StatementBase, StatementChildHavingBase def checkStatements(value): """Check that statements list value property. Must not be None, must not contain None, and of course only statements, may be empty. """ assert value is not None assert None not in value for statement in value: assert ( statement.isStatement() or statement.isStatementsFrame() ), statement.asXmlText() return tuple(value) class StatementsSequence(StatementChildHavingBase): kind = "STATEMENTS_SEQUENCE" named_child = "statements" checker = checkStatements def __init__(self, statements, source_ref): StatementChildHavingBase.__init__( self, value=tuple(statements), source_ref=source_ref ) def finalize(self): del self.parent for s in self.subnode_statements: s.finalize() # Overloading name based automatic check, so that derived ones know it too. def isStatementsSequence(self): # Virtual method, pylint: disable=no-self-use return True def trimStatements(self, statement): assert statement.parent is self old_statements = list(self.subnode_statements) assert statement in old_statements, (statement, self) new_statements = old_statements[: old_statements.index(statement) + 1] self.setChild("statements", new_statements) def removeStatement(self, statement): assert statement.parent is self statements = list(self.subnode_statements) statements.remove(statement) self.setChild("statements", statements) if statements: return self else: return None def replaceStatement(self, statement, statements): old_statements = list(self.subnode_statements) merge_index = old_statements.index(statement) new_statements = ( tuple(old_statements[:merge_index]) + tuple(statements) + tuple(old_statements[merge_index + 1 :]) ) self.setChild("statements", new_statements) def mayHaveSideEffects(self): # Statement sequences have a side effect if one of the statements does. for statement in self.subnode_statements: if statement.mayHaveSideEffects(): return True return False def mayRaiseException(self, exception_type): for statement in self.subnode_statements: if statement.mayRaiseException(exception_type): return True return False def needsFrame(self): for statement in self.subnode_statements: if statement.needsFrame(): return True return False def mayReturn(self): for statement in self.subnode_statements: if statement.mayReturn(): return True return False def mayBreak(self): for statement in self.subnode_statements: if statement.mayBreak(): return True return False def mayContinue(self): for statement in self.subnode_statements: if statement.mayContinue(): return True return False def mayRaiseExceptionOrAbort(self, exception_type): return ( self.mayRaiseException(exception_type) or self.mayReturn() or self.mayBreak() or self.mayContinue() ) def isStatementAborting(self): return self.subnode_statements[-1].isStatementAborting() def computeStatement(self, trace_collection): # Don't want to be called like this. assert False, self def computeStatementsSequence(self, trace_collection): new_statements = [] statements = self.subnode_statements assert statements, self for count, statement in enumerate(statements): # May be frames embedded. if statement.isStatementsFrame(): new_statement = statement.computeStatementsSequence(trace_collection) else: new_statement = trace_collection.onStatement(statement=statement) if new_statement is not None: if ( new_statement.isStatementsSequence() and not new_statement.isStatementsFrame() ): new_statements.extend(new_statement.subnode_statements) else: new_statements.append(new_statement) if ( statement is not statements[-1] and new_statement.isStatementAborting() ): trace_collection.signalChange( "new_statements", statements[count + 1].getSourceReference(), "Removed dead statements.", ) for s in statements[statements.index(statement) + 1 :]: s.finalize() break if statements != new_statements: if new_statements: self.setChild("statements", new_statements) return self else: return None else: return self @staticmethod def getStatementNiceName(): return "statements sequence" class StatementExpressionOnly(StatementChildHavingBase): kind = "STATEMENT_EXPRESSION_ONLY" named_child = "expression" def __init__(self, expression, source_ref): assert expression.isExpression() StatementChildHavingBase.__init__(self, value=expression, source_ref=source_ref) def mayHaveSideEffects(self): return self.subnode_expression.mayHaveSideEffects() def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseException(exception_type) def computeStatement(self, trace_collection): expression = trace_collection.onExpression(expression=self.subnode_expression) return expression.computeExpressionDrop( statement=self, trace_collection=trace_collection ) @staticmethod def getStatementNiceName(): return "expression only statement" def getDetailsForDisplay(self): return {"expression": self.subnode_expression.kind} class StatementPreserveFrameException(StatementBase): kind = "STATEMENT_PRESERVE_FRAME_EXCEPTION" __slots__ = ("preserver_id",) def __init__(self, preserver_id, source_ref): StatementBase.__init__(self, source_ref=source_ref) self.preserver_id = preserver_id def finalize(self): del self.parent def getDetails(self): return {"preserver_id": self.preserver_id} def getPreserverId(self): return self.preserver_id def computeStatement(self, trace_collection): # For Python2 generators, it's not necessary to preserve, the frame # decides it. TODO: This check makes only sense once. if self.getParentStatementsFrame().needsExceptionFramePreservation(): return self, None, None else: return ( None, "new_statements", "Removed frame preservation for generators.", ) @staticmethod def mayRaiseException(exception_type): return False @staticmethod def needsFrame(): return True class StatementRestoreFrameException(StatementBase): kind = "STATEMENT_RESTORE_FRAME_EXCEPTION" __slots__ = ("preserver_id",) def __init__(self, preserver_id, source_ref): StatementBase.__init__(self, source_ref=source_ref) self.preserver_id = preserver_id def finalize(self): del self.parent def getDetails(self): return {"preserver_id": self.preserver_id} def getPreserverId(self): return self.preserver_id def computeStatement(self, trace_collection): return self, None, None @staticmethod def mayRaiseException(exception_type): return False class StatementPublishException(StatementBase): kind = "STATEMENT_PUBLISH_EXCEPTION" def __init__(self, source_ref): StatementBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent def computeStatement(self, trace_collection): # TODO: Determine the need for it. return self, None, None @staticmethod def mayRaiseException(exception_type): return False Nuitka-0.6.19.1/nuitka/nodes/Checkers.py0000600000372100037210000000221714166627112024775 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node children checkers. The role of checkers is to make sure that node children have specific value types only. """ def checkStatementsSequenceOrNone(value): assert value is None or value.kind == "STATEMENTS_SEQUENCE", value return value def checkStatementsSequence(value): assert value is not None and value.kind == "STATEMENTS_SEQUENCE", value return value Nuitka-0.6.19.1/nuitka/nodes/TryNodes.py0000600000372100037210000004326014166627112025020 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for try/except/finally handling. This is the unified low level solution to trying a block, and executing code when it returns, break, continues, or raises an exception. See Developer Manual for how this maps to try/finally and try/except as in Python. """ from nuitka.Errors import NuitkaOptimizationError from nuitka.optimizations.TraceCollections import TraceCollectionBranch from .Checkers import checkStatementsSequence, checkStatementsSequenceOrNone from .NodeBases import StatementChildrenHavingBase from .StatementNodes import StatementsSequence class StatementTry(StatementChildrenHavingBase): kind = "STATEMENT_TRY" named_children = ( "tried", "except_handler", "break_handler", "continue_handler", "return_handler", ) checkers = { "tried": checkStatementsSequence, "except_handler": checkStatementsSequenceOrNone, "break_handler": checkStatementsSequenceOrNone, "continue_handler": checkStatementsSequenceOrNone, "return_handler": checkStatementsSequenceOrNone, } __slots__ = ("tried_may_raise",) def __init__( self, tried, except_handler, break_handler, continue_handler, return_handler, source_ref, ): StatementChildrenHavingBase.__init__( self, values={ "tried": tried, "except_handler": except_handler, "break_handler": break_handler, "continue_handler": continue_handler, "return_handler": return_handler, }, source_ref=source_ref, ) self.tried_may_raise = None def getDetailsForDisplay(self): return {"aborting": self.isStatementAborting()} def computeStatement(self, trace_collection): # This node has many children to handle, pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements tried = self.subnode_tried except_handler = self.subnode_except_handler break_handler = self.subnode_break_handler continue_handler = self.subnode_continue_handler return_handler = self.subnode_return_handler # The tried block must be considered as a branch, if it is not empty # already. collection_start = TraceCollectionBranch( parent=trace_collection, name="try start" ) abort_context = trace_collection.makeAbortStackContext( catch_breaks=break_handler is not None, catch_continues=continue_handler is not None, catch_returns=return_handler is not None, catch_exceptions=True, ) with abort_context: # As a branch point for the many types of handlers. result = tried.computeStatementsSequence(trace_collection=trace_collection) # We might be done entirely already. if result is None: return None, "new_statements", "Removed now empty try statement." # Might be changed. if result is not tried: self.setChild("tried", result) tried = result break_collections = trace_collection.getLoopBreakCollections() continue_collections = trace_collection.getLoopContinueCollections() return_collections = trace_collection.getFunctionReturnCollections() exception_collections = trace_collection.getExceptionRaiseCollections() # Not raising never turns into raising, but None (never calculated) and True # may no longer be true. if self.tried_may_raise is not False: self.tried_may_raise = tried.mayRaiseException(BaseException) # Exception handling is useless if no exception is to be raised. if not self.tried_may_raise: if except_handler is not None: except_handler.finalize() self.clearChild("except_handler") trace_collection.signalChange( tags="new_statements", message="Removed useless exception handler.", source_ref=except_handler.source_ref, ) except_handler = None # If tried may raise, even empty exception handler has a meaning to # ignore that exception. if self.tried_may_raise: collection_exception_handling = TraceCollectionBranch( parent=collection_start, name="except handler" ) # When no exception exits are there, this is a problem, we just # found an inconsistency that is a bug. if not exception_collections: for statement in tried.subnode_statements: if statement.mayRaiseException(BaseException): raise NuitkaOptimizationError( "This statement does raise but didn't annotate an exception exit.", statement, ) raise NuitkaOptimizationError( "Falsely assuming tried block may raise, but no statement says so.", tried, ) collection_exception_handling.mergeMultipleBranches(exception_collections) if except_handler is not None: result = except_handler.computeStatementsSequence( trace_collection=collection_exception_handling ) # Might be changed. if result is not except_handler: self.setChild("except_handler", result) except_handler = result if break_handler is not None: if not tried.mayBreak(): break_handler.finalize() self.clearChild("break_handler") break_handler = None if break_handler is not None: collection_break = TraceCollectionBranch( parent=collection_start, name="break handler" ) collection_break.mergeMultipleBranches(break_collections) result = break_handler.computeStatementsSequence( trace_collection=collection_break ) # Might be changed. if result is not break_handler: self.setChild("break_handler", result) break_handler = result if continue_handler is not None: if not tried.mayContinue(): continue_handler.finalize() self.clearChild("continue_handler") continue_handler = None if continue_handler is not None: collection_continue = TraceCollectionBranch( parent=collection_start, name="continue handler" ) collection_continue.mergeMultipleBranches(continue_collections) result = continue_handler.computeStatementsSequence( trace_collection=collection_continue ) # Might be changed. if result is not continue_handler: self.setChild("continue_handler", result) continue_handler = result if return_handler is not None: if not tried.mayReturn(): return_handler.finalize() self.clearChild("return_handler") return_handler = None if return_handler is not None: collection_return = TraceCollectionBranch( parent=collection_start, name="return handler" ) collection_return.mergeMultipleBranches(return_collections) result = return_handler.computeStatementsSequence( trace_collection=collection_return ) # Might be changed. if result is not return_handler: self.setChild("return_handler", result) return_handler = result # Check for trivial return handlers that immediately return, they can # just be removed. if return_handler is not None: if return_handler.subnode_statements[0].isStatementReturnReturnedValue(): return_handler.finalize() self.clearChild("return_handler") return_handler = None # Merge exception handler only if it is used. Empty means it is not # aborting, as it swallows the exception. if self.tried_may_raise and ( except_handler is None or not except_handler.isStatementAborting() ): trace_collection.mergeBranches( collection_yes=collection_exception_handling, collection_no=None ) # An empty exception handler means we have to swallow exception. if ( ( not self.tried_may_raise or ( except_handler is not None and except_handler.subnode_statements[ 0 ].isStatementReraiseException() ) ) and break_handler is None and continue_handler is None and return_handler is None ): return tried, "new_statements", "Removed useless try, all handlers removed." tried_statements = tried.subnode_statements pre_statements = [] while tried_statements: tried_statement = tried_statements[0] if tried_statement.mayRaiseException(BaseException): break if break_handler is not None and tried_statement.mayBreak(): break if continue_handler is not None and tried_statement.mayContinue(): break if return_handler is not None and tried_statement.mayReturn(): break pre_statements.append(tried_statement) tried_statements = list(tried_statements) del tried_statements[0] post_statements = [] if except_handler is not None and except_handler.isStatementAborting(): while tried_statements: tried_statement = tried_statements[-1] if tried_statement.mayRaiseException(BaseException): break if break_handler is not None and tried_statement.mayBreak(): break if continue_handler is not None and tried_statement.mayContinue(): break if return_handler is not None and tried_statement.mayReturn(): break post_statements.insert(0, tried_statement) tried_statements = list(tried_statements) del tried_statements[-1] if pre_statements or post_statements: assert tried_statements # Should be dealt with already tried.setChild("statements", tried_statements) result = StatementsSequence( statements=pre_statements + [self] + post_statements, source_ref=self.source_ref, ) def explain(): # TODO: We probably don't want to say this for re-formulation ones. result = "Reduced scope of tried block." if pre_statements: result += " Leading statements at %s." % ( ",".join( x.getSourceReference().getAsString() + "/" + str(x) for x in pre_statements ) ) if post_statements: result += " Trailing statements at %s." % ( ",".join( x.getSourceReference().getAsString() + "/" + str(x) for x in post_statements ) ) return result return (result, "new_statements", explain) return self, None, None def mayReturn(self): # TODO: If we optimized return handler away, this would be not needed # or even non-optimal. if self.subnode_tried.mayReturn(): return True if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is not None and except_handler.mayReturn(): return True break_handler = self.subnode_break_handler if break_handler is not None and break_handler.mayReturn(): return True continue_handler = self.subnode_continue_handler if continue_handler is not None and continue_handler.mayReturn(): return True return_handler = self.subnode_return_handler if return_handler is not None and return_handler.mayReturn(): return True return False def mayBreak(self): # TODO: If we optimized return handler away, this would be not needed # or even non-optimal. if self.subnode_tried.mayBreak(): return True if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is not None and except_handler.mayBreak(): return True break_handler = self.subnode_break_handler if break_handler is not None and break_handler.mayBreak(): return True continue_handler = self.subnode_continue_handler if continue_handler is not None and continue_handler.mayBreak(): return True return_handler = self.subnode_return_handler if return_handler is not None and return_handler.mayBreak(): return True return False def mayContinue(self): # TODO: If we optimized return handler away, this would be not needed # or even non-optimal. if self.subnode_tried.mayContinue(): return True if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is not None and except_handler.mayContinue(): return True break_handler = self.subnode_break_handler if break_handler is not None and break_handler.mayContinue(): return True continue_handler = self.subnode_continue_handler if continue_handler is not None and continue_handler.mayContinue(): return True return_handler = self.subnode_return_handler if return_handler is not None and return_handler.mayContinue(): return True return False def isStatementAborting(self): if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is None or not except_handler.isStatementAborting(): return False break_handler = self.subnode_break_handler if break_handler is not None and not break_handler.isStatementAborting(): return False continue_handler = self.subnode_continue_handler if continue_handler is not None and not continue_handler.isStatementAborting(): return False return_handler = self.subnode_return_handler if return_handler is not None and not return_handler.isStatementAborting(): return False return self.subnode_tried.isStatementAborting() def mayRaiseException(self, exception_type): if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is not None and except_handler.mayRaiseException( exception_type ): return True break_handler = self.subnode_break_handler if break_handler is not None and break_handler.mayRaiseException( exception_type ): return True continue_handler = self.subnode_continue_handler if continue_handler is not None and continue_handler.mayRaiseException( exception_type ): return True return_handler = self.subnode_return_handler if return_handler is not None and return_handler.mayRaiseException( exception_type ): return True return False def needsFrame(self): if self.tried_may_raise is not False: except_handler = self.subnode_except_handler if except_handler is not None and except_handler.needsFrame(): return True break_handler = self.subnode_break_handler if break_handler is not None and break_handler.needsFrame(): return True continue_handler = self.subnode_continue_handler if continue_handler is not None and continue_handler.needsFrame(): return True return_handler = self.subnode_return_handler if return_handler is not None and return_handler.needsFrame(): return True return self.subnode_tried.needsFrame() @staticmethod def getStatementNiceName(): return "tried block statement" Nuitka-0.6.19.1/nuitka/nodes/NodeBases.py0000600000372100037210000010454014166627112025113 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node base classes. These classes provide the generic base classes available for nodes, statements or expressions alike. There is a dedicated module for expression only stuff. """ # from abc import abstractmethod from abc import abstractmethod from nuitka import Options, Tracing, TreeXML, Variables from nuitka.__past__ import iterItems from nuitka.Errors import NuitkaNodeDesignError, NuitkaNodeError from nuitka.PythonVersions import python_version from nuitka.SourceCodeReferences import SourceCodeReference from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) from .FutureSpecs import fromFlags from .NodeMakingHelpers import makeStatementOnlyNodesFromExpressions from .NodeMetaClasses import NodeCheckMetaClass, NodeMetaClassBase class NodeBase(NodeMetaClassBase): __slots__ = "parent", "source_ref" # This can trigger if this is included to early. assert Options.is_fullcompat is not None # Avoid the attribute unless it's really necessary. if Options.is_fullcompat: __slots__ += ("effective_source_ref",) # String to identify the node class, to be consistent with its name. kind = None @counted_init def __init__(self, source_ref): # The base class has no __init__ worth calling. # Check source reference to meet basic standards, so we note errors # when they occur. assert source_ref is not None assert source_ref.line is not None self.parent = None self.source_ref = source_ref if isCountingInstances(): __del__ = counted_del() @abstractmethod def finalize(self): pass def __repr__(self): return "" % (self.getDescription()) def getDescription(self): """Description of the node, intended for use in __repr__ and graphical display. """ details = self.getDetailsForDisplay() if details: return "'%s' with %s" % (self.kind, details) else: return "'%s'" % self.kind def getDetails(self): """Details of the node, intended for re-creation. We are not using the pickle mechanisms, but this is basically part of what the constructor call needs. Real children will also be added. """ # Virtual method, pylint: disable=no-self-use return {} def getDetailsForDisplay(self): """Details of the node, intended for use in __repr__ and dumps. This is also used for XML. """ return self.getDetails() def getCloneArgs(self): return self.getDetails() def makeClone(self): try: # Using star dictionary arguments here for generic use. result = self.__class__(source_ref=self.source_ref, **self.getCloneArgs()) except TypeError as e: raise NuitkaNodeError("Problem cloning node", self, e) effective_source_ref = self.getCompatibleSourceReference() if effective_source_ref is not self.source_ref: result.setCompatibleSourceReference(effective_source_ref) return result def makeCloneShallow(self): args = self.getDetails() args.update(self.getVisitableNodesNamed()) try: # Using star dictionary arguments here for generic use. result = self.__class__(source_ref=self.source_ref, **args) except TypeError as e: raise NuitkaNodeError("Problem cloning node", self, e) effective_source_ref = self.getCompatibleSourceReference() if effective_source_ref is not self.source_ref: result.setCompatibleSourceReference(effective_source_ref) return result def getParent(self): """Parent of the node. Every node except modules has to have a parent.""" if self.parent is None and not self.isCompiledPythonModule(): assert False, (self, self.source_ref) return self.parent def getChildName(self): """Return the role in the current parent, subject to changes.""" parent = self.getParent() for key, value in parent.getVisitableNodesNamed(): if self is value: return key if type(value) is tuple: if self in value: return key, value.index(self) return None def getChildNameNice(self): child_name = self.getChildName() if hasattr(self.parent, "nice_children"): return self.parent.nice_children[ self.parent.named_children.index(child_name) ] elif hasattr(self.parent, "nice_child"): return self.parent.nice_child else: return child_name def getParentFunction(self): """Return the parent that is a function.""" parent = self.getParent() while parent is not None and not parent.isExpressionFunctionBodyBase(): parent = parent.getParent() return parent def getParentModule(self): """Return the parent that is module.""" parent = self while not parent.isCompiledPythonModule(): if hasattr(parent, "provider"): # After we checked, we can use it, will be much faster route # to take. parent = parent.provider else: parent = parent.getParent() return parent def isParentVariableProvider(self): # Check if it's a closure giver, in which cases it can provide variables, return isinstance(self, ClosureGiverNodeMixin) def getParentVariableProvider(self): parent = self.getParent() while not parent.isParentVariableProvider(): parent = parent.getParent() return parent def getParentReturnConsumer(self): parent = self.getParent() while ( not parent.isParentVariableProvider() and not parent.isExpressionOutlineBody() ): parent = parent.getParent() return parent def getParentStatementsFrame(self): current = self.getParent() while True: if current.isStatementsFrame(): return current if current.isParentVariableProvider(): return None if current.isExpressionOutlineBody(): return None current = current.getParent() def getSourceReference(self): return self.source_ref def setCompatibleSourceReference(self, source_ref): """Bug compatible line numbers information. As CPython outputs the last bit of bytecode executed, and not the line of the operation. For example calls, output the line of the last argument, as opposed to the line of the operation start. For tests, we wants to be compatible. In improved more, we are not being fully compatible, and just drop it altogether. """ # Getting the same source reference can be dealt with quickly, so do # this first. if ( self.source_ref is not source_ref and Options.is_fullcompat and self.source_ref != source_ref ): # An attribute outside of "__init__", so we save one memory for the # most cases. Very few cases involve splitting across lines. # false alarm for non-slot: # pylint: disable=I0021,assigning-non-slot,attribute-defined-outside-init self.effective_source_ref = source_ref def getCompatibleSourceReference(self): """Bug compatible line numbers information. See above. """ return getattr(self, "effective_source_ref", self.source_ref) def asXml(self): line = self.source_ref.getLineNumber() result = TreeXML.Element("node", kind=self.__class__.__name__, line=str(line)) compat_line = self.getCompatibleSourceReference().getLineNumber() if compat_line != line: result.attrib["compat_line"] = str(compat_line) for key, value in iterItems(self.getDetailsForDisplay()): result.set(key, str(value)) for name, children in self.getVisitableNodesNamed(): role = TreeXML.Element("role", name=name) result.append(role) if children is None: role.attrib["type"] = "none" elif type(children) not in (list, tuple): role.append(children.asXml()) else: role.attrib["type"] = "list" for child in children: role.append(child.asXml()) return result @classmethod def fromXML(cls, provider, source_ref, **args): # Only some things need a provider, pylint: disable=unused-argument return cls(source_ref=source_ref, **args) def asXmlText(self): xml = self.asXml() return TreeXML.toString(xml) def dump(self, level=0): Tracing.printIndented(level, self) Tracing.printSeparator(level) for visitable in self.getVisitableNodes(): visitable.dump(level + 1) Tracing.printSeparator(level) @staticmethod def isStatementsFrame(): return False @staticmethod def isCompiledPythonModule(): # For overload by module nodes return False def isExpression(self): return self.kind.startswith("EXPRESSION_") def isStatement(self): return self.kind.startswith("STATEMENT_") def isExpressionBuiltin(self): return self.kind.startswith("EXPRESSION_BUILTIN_") @staticmethod def isExpressionConstantRef(): return False @staticmethod def isExpressionConstantBoolRef(): return False @staticmethod def isExpressionOperationUnary(): return False @staticmethod def isExpressionOperationBinary(): return False @staticmethod def isExpressionOperationInplace(): return False @staticmethod def isExpressionComparison(): return False @staticmethod def isExpressionSideEffects(): return False @staticmethod def isExpressionMakeSequence(): return False @staticmethod def isNumberConstant(): return False @staticmethod def isExpressionCall(): return False @staticmethod def isExpressionFunctionBodyBase(): return False @staticmethod def isExpressionOutlineFunctionBase(): return False def visit(self, context, visitor): visitor(self) for visitable in self.getVisitableNodes(): visitable.visit(context, visitor) @staticmethod def getVisitableNodes(): return () @staticmethod def getVisitableNodesNamed(): """Named children dictionary. For use in debugging and XML output. """ return () @staticmethod def getName(): """Name of the node if any.""" return None @staticmethod def mayHaveSideEffects(): """Unless we are told otherwise, everything may have a side effect.""" return True def isOrderRelevant(self): return self.mayHaveSideEffects() def extractSideEffects(self): """Unless defined otherwise, the expression is the side effect.""" return (self,) @staticmethod def mayRaiseException(exception_type): """Unless we are told otherwise, everything may raise everything.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayReturn(): """May this node do a return exit, to be overloaded for things that might.""" return False @staticmethod def mayBreak(): return False @staticmethod def mayContinue(): return False def needsFrame(self): """Unless we are tolder otherwise, this depends on exception raise.""" return self.mayRaiseException(BaseException) @staticmethod def willRaiseException(exception_type): """Unless we are told otherwise, nothing may raise anything.""" # Virtual method, pylint: disable=unused-argument return False @staticmethod def isStatementAborting(): """Is the node aborting, control flow doesn't continue after this node.""" return False class CodeNodeMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self, name, code_prefix): assert name is not None self.name = name self.code_prefix = code_prefix # The code name is determined on demand only. self.code_name = None # The "UID" values of children kinds are kept here. self.uids = {} def getName(self): return self.name def getCodeName(self): if self.code_name is None: provider = self.getParentVariableProvider().getEntryPoint() parent_name = provider.getCodeName() uid = "_%d" % provider.getChildUID(self) assert isinstance(self, CodeNodeMixin) if self.name: name = uid + "_" + self.name.strip("<>") else: name = uid if str is not bytes: name = name.encode("ascii", "c_identifier").decode() self.code_name = "%s$$$%s_%s" % (parent_name, self.code_prefix, name) return self.code_name def getChildUID(self, node): if node.kind not in self.uids: self.uids[node.kind] = 0 self.uids[node.kind] += 1 return self.uids[node.kind] class ChildrenHavingMixin(object): # Mixins are not allow to specify slots. __slots__ = () named_children = () checkers = {} def __init__(self, values): assert ( type(self.named_children) is tuple and self.named_children ), self.named_children # TODO: Make this true. # assert len(self.named_children) > 1, self.kind # Check for completeness of given values, everything should be there # but of course, might be put to None. if set(values.keys()) != set(self.named_children): raise NuitkaNodeDesignError( "Must pass named children in value dictionary", set(values.keys()), set(self.named_children), ) for name, value in values.items(): if name in self.checkers: value = self.checkers[name](value) if type(value) is tuple: assert None not in value, name for val in value: val.parent = self elif value is None: pass else: value.parent = self attr_name = "subnode_" + name setattr(self, attr_name, value) def setChild(self, name, value): """Set a child value. Do not overload, provider self.checkers instead. """ # Only accept legal child names assert name in self.named_children, name # Lists as inputs are OK, but turn them into tuples. if type(value) is list: value = tuple(value) if name in self.checkers: value = self.checkers[name](value) # Re-parent value to us. if type(value) is tuple: for val in value: val.parent = self elif value is not None: value.parent = self attr_name = "subnode_" + name # Determine old value, and inform it about losing its parent. old_value = getattr(self, attr_name) assert old_value is not value, value setattr(self, attr_name, value) def clearChild(self, name): # Only accept legal child names assert name in self.named_children, name if name in self.checkers: self.checkers[name](None) attr_name = "subnode_" + name # Determine old value, and inform it about losing its parent. old_value = getattr(self, attr_name) assert old_value is not None setattr(self, attr_name, None) def getChild(self, name): attr_name = "subnode_" + name return getattr(self, attr_name) def getVisitableNodes(self): # TODO: Consider if a generator would be faster. result = [] for name in self.named_children: attr_name = "subnode_" + name value = getattr(self, attr_name) if value is None: pass elif type(value) is tuple: result += list(value) elif isinstance(value, NodeBase): result.append(value) else: raise AssertionError( self, "has illegal child", name, value, value.__class__ ) return tuple(result) def getVisitableNodesNamed(self): """Named children dictionary. For use in debugging and XML output. """ for name in self.named_children: attr_name = "subnode_" + name value = getattr(self, attr_name) yield name, value def replaceChild(self, old_node, new_node): if new_node is not None and not isinstance(new_node, NodeBase): raise AssertionError( "Cannot replace with", new_node, "old", old_node, "in", self ) # Find the replaced node, as an added difficulty, what might be # happening, is that the old node is an element of a tuple, in which we # may also remove that element, by setting it to None. for key in self.named_children: value = self.getChild(key) if value is None: pass elif type(value) is tuple: if old_node in value: if new_node is not None: self.setChild( key, tuple( (val if val is not old_node else new_node) for val in value ), ) else: self.setChild( key, tuple(val for val in value if val is not old_node) ) return key elif isinstance(value, NodeBase): if old_node is value: self.setChild(key, new_node) return key else: assert False, (key, value, value.__class__) raise AssertionError("Didn't find child", old_node, "in", self) def getCloneArgs(self): values = {} for key in self.named_children: value = self.getChild(key) assert type(value) is not list, key if value is None: values[key] = None elif type(value) is tuple: values[key] = tuple(v.makeClone() for v in value) else: values[key] = value.makeClone() values.update(self.getDetails()) return values def finalize(self): del self.parent for c in self.getVisitableNodes(): c.finalize() class ClosureGiverNodeMixin(CodeNodeMixin): """Base class for nodes that provide variables for closure takers.""" # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self, name, code_prefix): CodeNodeMixin.__init__(self, name=name, code_prefix=code_prefix) self.temp_variables = {} self.temp_scopes = {} self.preserver_id = 0 def hasProvidedVariable(self, variable_name): return self.locals_scope.hasProvidedVariable(variable_name) def getProvidedVariable(self, variable_name): if not self.locals_scope.hasProvidedVariable(variable_name): variable = self.createProvidedVariable(variable_name=variable_name) self.locals_scope.registerProvidedVariable(variable) return self.locals_scope.getProvidedVariable(variable_name) @abstractmethod def createProvidedVariable(self, variable_name): """Create a variable provided by this function.""" def allocateTempScope(self, name): self.temp_scopes[name] = self.temp_scopes.get(name, 0) + 1 return "%s_%d" % (name, self.temp_scopes[name]) def allocateTempVariable(self, temp_scope, name, temp_type=None): if temp_scope is not None: full_name = "%s__%s" % (temp_scope, name) else: assert name != "result" full_name = name # No duplicates please. assert full_name not in self.temp_variables, full_name result = self.createTempVariable(temp_name=full_name, temp_type=temp_type) # Late added temp variables should be treated with care for the # remaining trace. if self.trace_collection is not None: self.trace_collection.initVariableUnknown(result).addUsage() return result def createTempVariable(self, temp_name, temp_type): if temp_name in self.temp_variables: return self.temp_variables[temp_name] if temp_type is None: temp_class = Variables.TempVariable elif temp_type == "bool": temp_class = Variables.TempVariableBool else: assert False, temp_type result = temp_class(owner=self, variable_name=temp_name) self.temp_variables[temp_name] = result return result def getTempVariable(self, temp_scope, name): if temp_scope is not None: full_name = "%s__%s" % (temp_scope, name) else: full_name = name return self.temp_variables[full_name] def getTempVariables(self): return self.temp_variables.values() def _removeTempVariable(self, variable): del self.temp_variables[variable.getName()] def optimizeUnusedTempVariables(self): remove = [] for temp_variable in self.getTempVariables(): empty = self.trace_collection.hasEmptyTraces(variable=temp_variable) if empty: remove.append(temp_variable) for temp_variable in remove: self._removeTempVariable(temp_variable) def allocatePreserverId(self): if python_version >= 0x300: self.preserver_id += 1 return self.preserver_id class ClosureTakerMixin(object): """Mixin for nodes that accept variables from closure givers.""" # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self, provider): self.provider = provider self.taken = set() def getParentVariableProvider(self): return self.provider def getClosureVariable(self, variable_name): result = self.provider.getVariableForClosure(variable_name=variable_name) assert result is not None, variable_name if not result.isModuleVariable(): self.addClosureVariable(result) return result def addClosureVariable(self, variable): self.taken.add(variable) return variable def getClosureVariables(self): return tuple( sorted( [take for take in self.taken if not take.isModuleVariable()], key=lambda x: x.getName(), ) ) def getClosureVariableIndex(self, variable): closure_variables = self.getClosureVariables() for count, closure_variable in enumerate(closure_variables): if variable is closure_variable: return count raise IndexError(variable) def hasTakenVariable(self, variable_name): for variable in self.taken: if variable.getName() == variable_name: return True return False def getTakenVariable(self, variable_name): for variable in self.taken: if variable.getName() == variable_name: return variable return None class StatementBase(NodeBase): """Base class for all statements.""" # Base classes can be abstract, pylint: disable=abstract-method # TODO: Have them all. # @abstractmethod @staticmethod def getStatementNiceName(): return "undescribed statement" def computeStatementSubExpressions(self, trace_collection): """Compute a statement. Default behavior is to just visit the child expressions first, and then the node "computeStatement". For a few cases this needs to be overloaded. """ expressions = self.getVisitableNodes() for count, expression in enumerate(expressions): assert expression.isExpression(), (self, expression) expression = trace_collection.onExpression(expression=expression) if expression.willRaiseException(BaseException): wrapped_expression = makeStatementOnlyNodesFromExpressions( expressions[: count + 1] ) assert wrapped_expression is not None return ( wrapped_expression, "new_raise", lambda: "For %s the child expression '%s' will raise." % (self.getStatementNiceName(), expression.getChildNameNice()), ) return self, None, None class StatementChildrenHavingBase(ChildrenHavingMixin, StatementBase): def __init__(self, values, source_ref): StatementBase.__init__(self, source_ref=source_ref) ChildrenHavingMixin.__init__(self, values=values) class StatementChildHavingBase(StatementBase): named_child = "" checker = None def __init__(self, value, source_ref): StatementBase.__init__(self, source_ref=source_ref) if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable assert type(value) is not list, self.named_child if type(value) is tuple: assert None not in value, self.named_child for val in value: val.parent = self elif value is not None: value.parent = self elif value is None: pass else: assert False, type(value) attr_name = "subnode_" + self.named_child setattr(self, attr_name, value) def setChild(self, name, value): """Set a child value. Do not overload, provider self.checkers instead. """ # Only accept legal child names assert name == self.named_child, name # Lists as inputs are OK, but turn them into tuples. if type(value) is list: value = tuple(value) if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable # Re-parent value to us. if type(value) is tuple: for val in value: val.parent = self elif value is not None: value.parent = self attr_name = "subnode_" + name # Determine old value, and inform it about losing its parent. old_value = getattr(self, attr_name) assert old_value is not value, value setattr(self, attr_name, value) def getChild(self, name): # Only accept legal child names attr_name = "subnode_" + name return getattr(self, attr_name) def getVisitableNodes(self): # TODO: Consider if a generator would be faster. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) if value is None: return () elif type(value) is tuple: return value elif isinstance(value, NodeBase): return (value,) else: raise AssertionError(self, "has illegal child", value, value.__class__) def getVisitableNodesNamed(self): """Named children dictionary. For use in debugging and XML output. """ attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) yield self.named_child, value def replaceChild(self, old_node, new_node): if new_node is not None and not isinstance(new_node, NodeBase): raise AssertionError( "Cannot replace with", new_node, "old", old_node, "in", self ) # Find the replaced node, as an added difficulty, what might be # happening, is that the old node is an element of a tuple, in which we # may also remove that element, by setting it to None. key = self.named_child value = self.getChild(key) if value is None: pass elif type(value) is tuple: if old_node in value: if new_node is not None: self.setChild( key, tuple( (val if val is not old_node else new_node) for val in value ), ) else: self.setChild( key, tuple(val for val in value if val is not old_node) ) return key elif isinstance(value, NodeBase): if old_node is value: self.setChild(key, new_node) return key else: assert False, (key, value, value.__class__) raise AssertionError("Didn't find child", old_node, "in", self) def getCloneArgs(self): # Make clones of child nodes too. values = {} key = self.named_child value = self.getChild(key) assert type(value) is not list, key if value is None: values[key] = None elif type(value) is tuple: values[key] = tuple(v.makeClone() for v in value) else: values[key] = value.makeClone() values.update(self.getDetails()) return values def finalize(self): del self.parent attr_name = "subnode_" + self.named_child child = getattr(self, attr_name) if child is not None: child.finalize() delattr(self, attr_name) class SideEffectsFromChildrenMixin(object): # Mixins are not allow to specify slots. __slots__ = () def mayHaveSideEffects(self): for child in self.getVisitableNodes(): if child.mayHaveSideEffects(): return True return False def extractSideEffects(self): # No side effects at all but from the children. result = [] for child in self.getVisitableNodes(): result.extend(child.extractSideEffects()) return tuple(result) def computeExpressionDrop(self, statement, trace_collection): # Expression only statement plays no role, pylint: disable=unused-argument side_effects = self.extractSideEffects() # TODO: Have a method for nicer output and remove existing overloads # by using classes and prefer generic implementation here. if side_effects: return ( makeStatementOnlyNodesFromExpressions(side_effects), "new_statements", "Lowered unused expression %s to its side effects." % self.kind, ) else: return ( None, "new_statements", "Removed %s without side effects." % self.kind, ) def makeChild(provider, child, source_ref): child_type = child.attrib.get("type") if child_type == "list": return [ fromXML(provider=provider, xml=sub_child, source_ref=source_ref) for sub_child in child ] elif child_type == "none": return None else: return fromXML(provider=provider, xml=child[0], source_ref=source_ref) def getNodeClassFromKind(kind): return NodeCheckMetaClass.kinds[kind] def extractKindAndArgsFromXML(xml, source_ref): kind = xml.attrib["kind"] args = dict(xml.attrib) del args["kind"] if source_ref is None: source_ref = SourceCodeReference.fromFilenameAndLine( args["filename"], int(args["line"]) ) del args["filename"] del args["line"] else: source_ref = source_ref.atLineNumber(int(args["line"])) del args["line"] node_class = getNodeClassFromKind(kind) return kind, node_class, args, source_ref def fromXML(provider, xml, source_ref=None): assert xml.tag == "node", xml kind, node_class, args, source_ref = extractKindAndArgsFromXML(xml, source_ref) if "constant" in args: # TODO: Try and reduce/avoid this, use marshal and/or pickle from a file # global stream instead. For now, this will do. pylint: disable=eval-used args["constant"] = eval(args["constant"]) if kind in ( "ExpressionFunctionBody", "PythonMainModule", "PythonCompiledModule", "PythonCompiledPackage", "PythonInternalModule", ): delayed = node_class.named_children if "code_flags" in args: args["future_spec"] = fromFlags(args["code_flags"]) else: delayed = () for child in xml: assert child.tag == "role", child.tag child_name = child.attrib["name"] # Might want to want until provider is updated with some # children. In these cases, we pass the XML node, rather # than a Nuitka node. if child_name not in delayed: args[child_name] = makeChild(provider, child, source_ref) else: args[child_name] = child try: return node_class.fromXML(provider=provider, source_ref=source_ref, **args) except (TypeError, AttributeError): Tracing.printLine(node_class, args, source_ref) raise Nuitka-0.6.19.1/nuitka/nodes/SliceNodes.py0000600000372100037210000003111414166627112025274 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Slice nodes. Slices are important when working with lists. Tracking them can allow to achieve more compact code, or predict results at compile time. There will be a method "computeExpressionSlice" to aid predicting them. """ from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from .ConstantRefNodes import ExpressionConstantNoneRef, makeConstantRefNode from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionSpecBasedComputationNoRaiseMixin, ) from .ExpressionShapeMixins import ExpressionSliceShapeExactMixin from .NodeBases import ( SideEffectsFromChildrenMixin, StatementChildrenHavingBase, ) from .NodeMakingHelpers import ( convertNoneConstantToNone, makeStatementExpressionOnlyReplacementNode, makeStatementOnlyNodesFromExpressions, wrapExpressionWithSideEffects, ) class StatementAssignmentSlice(StatementChildrenHavingBase): kind = "STATEMENT_ASSIGNMENT_SLICE" named_children = ("source", "expression", "lower", "upper") def __init__(self, expression, lower, upper, source, source_ref): assert python_version < 0x300 StatementChildrenHavingBase.__init__( self, values={ "source": source, "expression": expression, "lower": lower, "upper": upper, }, source_ref=source_ref, ) def computeStatement(self, trace_collection): source = trace_collection.onExpression(self.subnode_source) # No assignment will occur, if the assignment source raises, so strip it # away. if source.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=source, node=self ) return ( result, "new_raise", """\ Slice assignment raises exception in assigned value, removed assignment.""", ) lookup_source = trace_collection.onExpression(self.subnode_expression) if lookup_source.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(source, lookup_source) ) return ( result, "new_raise", """\ Slice assignment raises exception in sliced value, removed assignment.""", ) lower = trace_collection.onExpression(self.subnode_lower, allow_none=True) if lower is not None and lower.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(source, lookup_source, lower) ) return ( result, "new_raise", """\ Slice assignment raises exception in lower slice boundary value, removed \ assignment.""", ) upper = trace_collection.onExpression(self.subnode_upper, allow_none=True) if upper is not None and upper.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(source, lookup_source, lower, upper) ) return ( result, "new_raise", """\ Slice assignment raises exception in upper slice boundary value, removed \ assignment.""", ) return lookup_source.computeExpressionSetSlice( set_node=self, lower=lower, upper=upper, value_node=source, trace_collection=trace_collection, ) class StatementDelSlice(StatementChildrenHavingBase): kind = "STATEMENT_DEL_SLICE" named_children = ("expression", "lower", "upper") def __init__(self, expression, lower, upper, source_ref): StatementChildrenHavingBase.__init__( self, values={"expression": expression, "lower": lower, "upper": upper}, source_ref=source_ref, ) def computeStatement(self, trace_collection): lookup_source = trace_collection.onExpression(self.subnode_expression) if lookup_source.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=lookup_source, node=self ) return ( result, "new_raise", """\ Slice del raises exception in sliced value, removed del""", ) lower = trace_collection.onExpression(self.subnode_lower, allow_none=True) if lower is not None and lower.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(lookup_source, lower) ) return ( result, "new_raise", """ Slice del raises exception in lower slice boundary value, removed del""", ) trace_collection.onExpression(self.subnode_upper, allow_none=True) upper = self.subnode_upper if upper is not None and upper.willRaiseException(BaseException): result = makeStatementOnlyNodesFromExpressions( expressions=(lookup_source, lower, upper) ) return ( result, "new_raise", """ Slice del raises exception in upper slice boundary value, removed del""", ) return lookup_source.computeExpressionDelSlice( set_node=self, lower=lower, upper=upper, trace_collection=trace_collection ) class ExpressionSliceLookup(ExpressionChildrenHavingBase): kind = "EXPRESSION_SLICE_LOOKUP" named_children = ("expression", "lower", "upper") checkers = {"upper": convertNoneConstantToNone, "lower": convertNoneConstantToNone} def __init__(self, expression, lower, upper, source_ref): assert python_version < 0x300 ExpressionChildrenHavingBase.__init__( self, values={"expression": expression, "upper": upper, "lower": lower}, source_ref=source_ref, ) def computeExpression(self, trace_collection): lookup_source = self.subnode_expression return lookup_source.computeExpressionSlice( lookup_node=self, lower=self.subnode_lower, upper=self.subnode_upper, trace_collection=trace_collection, ) @staticmethod def isKnownToBeIterable(count): # TODO: Should ask SliceRegistry return None def makeExpressionBuiltinSlice(start, stop, step, source_ref): if ( (start is None or start.isCompileTimeConstant()) and (stop is None or stop.isCompileTimeConstant()) and (step is None or step.isCompileTimeConstant()) ): # Avoid going slices for what is effectively constant. start_value = None if start is None else start.getCompileTimeConstant() stop_value = None if stop is None else stop.getCompileTimeConstant() step_value = None if step is None else step.getCompileTimeConstant() return makeConstantRefNode( constant=slice(start_value, stop_value, step_value), source_ref=source_ref ) if start is None and step is None: return ExpressionBuiltinSlice1(stop=stop, source_ref=source_ref) if start is None: start = ExpressionConstantNoneRef(source_ref=source_ref) if stop is None: stop = ExpressionConstantNoneRef(source_ref=source_ref) if step is None: return ExpressionBuiltinSlice2(start=start, stop=stop, source_ref=source_ref) return ExpressionBuiltinSlice3( start=start, stop=stop, step=step, source_ref=source_ref ) class ExpressionBuiltinSliceMixin( ExpressionSliceShapeExactMixin, SideEffectsFromChildrenMixin ): # Mixins are required to slots __slots__ = () builtin_spec = BuiltinParameterSpecs.builtin_slice_spec # We use SideEffectsFromChildrenMixin for the other things. def mayHaveSideEffects(self): return self.mayRaiseException(BaseException) class ExpressionBuiltinSlice3( ExpressionBuiltinSliceMixin, ExpressionSpecBasedComputationNoRaiseMixin, ExpressionChildrenHavingBase, ): kind = "EXPRESSION_BUILTIN_SLICE3" named_children = ("start", "stop", "step") def __init__(self, start, stop, step, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"start": start, "stop": stop, "step": step}, source_ref=source_ref, ) def computeExpression(self, trace_collection): if ( self.subnode_step.isExpressionConstantNoneRef() or self.subnode_step.getIndexValue() == 1 ): return trace_collection.computedExpressionResult( wrapExpressionWithSideEffects( old_node=self, new_node=ExpressionBuiltinSlice2( start=self.subnode_start, stop=self.subnode_stop, source_ref=self.source_ref, ), side_effects=self.subnode_step.extractSideEffects(), ), "new_expression", "Reduce 3 argument slice object creation to two argument form.", ) return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(self.subnode_start, self.subnode_stop, self.subnode_step), ) def mayRaiseException(self, exception_type): return ( self.subnode_start.mayRaiseException(exception_type) or self.subnode_stop.mayRaiseException(exception_type) or self.subnode_step.mayRaiseException(exception_type) ) class ExpressionBuiltinSlice2( ExpressionBuiltinSliceMixin, ExpressionSpecBasedComputationNoRaiseMixin, ExpressionChildrenHavingBase, ): kind = "EXPRESSION_BUILTIN_SLICE2" named_children = ("start", "stop") def __init__(self, start, stop, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"start": start, "stop": stop}, source_ref=source_ref, ) def computeExpression(self, trace_collection): if self.subnode_start.isExpressionConstantNoneRef(): return trace_collection.computedExpressionResult( wrapExpressionWithSideEffects( old_node=self, new_node=ExpressionBuiltinSlice1( stop=self.subnode_stop, source_ref=self.source_ref ), side_effects=self.subnode_start.extractSideEffects(), ), "new_expression", "Reduce 2 argument slice object creation to single argument form.", ) return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(self.subnode_start, self.subnode_stop), ) def mayRaiseException(self, exception_type): return self.subnode_start.mayRaiseException( exception_type ) or self.subnode_stop.mayRaiseException(exception_type) class ExpressionBuiltinSlice1( ExpressionBuiltinSliceMixin, ExpressionSpecBasedComputationNoRaiseMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_BUILTIN_SLICE1" named_child = "stop" def __init__(self, stop, source_ref): ExpressionChildHavingBase.__init__( self, value=stop, source_ref=source_ref, ) def computeExpression(self, trace_collection): return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(self.subnode_stop,), ) def mayRaiseException(self, exception_type): return self.subnode_stop.mayRaiseException(exception_type) Nuitka-0.6.19.1/nuitka/nodes/ComparisonNodes.py0000600000372100037210000005174114166627112026357 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for comparisons. """ from nuitka import PythonOperators from nuitka.Errors import NuitkaAssumptionError from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildrenHavingBase from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseExceptionReplacementExpressionFromInstance, wrapExpressionWithSideEffects, ) from .shapes.BuiltinTypeShapes import tshape_bool, tshape_exception_class from .shapes.StandardShapes import tshape_unknown class ExpressionComparisonBase(ExpressionChildrenHavingBase): named_children = ("left", "right") def __init__(self, left, right, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"left": left, "right": right}, source_ref=source_ref ) @staticmethod def copyTraceStateFrom(source): pass def getOperands(self): return (self.subnode_left, self.subnode_right) def getComparator(self): return self.comparator def getDetails(self): return {"comparator": self.comparator} @staticmethod def isExpressionComparison(): return True def getSimulator(self): return PythonOperators.all_comparison_functions[self.comparator] def _computeCompileTimeConstantComparision(self, trace_collection): left_value = self.subnode_left.getCompileTimeConstant() right_value = self.subnode_right.getCompileTimeConstant() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getSimulator()(left_value, right_value), description="Comparison of constant arguments.", ) def makeInverseComparision(self): # Making this accessing for tree building phase as well. return makeComparisonExpression( left=self.subnode_left, right=self.subnode_right, comparator=PythonOperators.comparison_inversions[self.comparator], source_ref=self.source_ref, ) def computeExpressionOperationNot(self, not_node, trace_collection): if self.getTypeShape() is tshape_bool: result = self.makeInverseComparision() result.copyTraceStateFrom(self) return ( result, "new_expression", """Replaced negated comparison '%s' with inverse comparison '%s'.""" % (self.comparator, result.comparator), ) return not_node, None, None class ExpressionComparisonRichBase(ExpressionComparisonBase): __slots__ = ( "type_shape", "escape_desc", "left_available", "left_comparable", "right_available", "right_comparable", ) def __init__(self, left, right, source_ref): ExpressionComparisonBase.__init__( self, left=left, right=right, source_ref=source_ref ) self.type_shape = tshape_unknown self.escape_desc = None self.left_available = False self.left_comparable = None self.right_available = False self.right_comparable = None def getTypeShape(self): return self.type_shape @staticmethod def getDetails(): return {} def copyTraceStateFrom(self, source): self.type_shape = source.type_shape self.escape_desc = source.escape_desc def canCreateUnsupportedException(self): return hasattr(self.subnode_left.getTypeShape(), "typical_value") and hasattr( self.subnode_right.getTypeShape(), "typical_value" ) def createUnsupportedException(self): left = self.subnode_left.getTypeShape().typical_value right = self.subnode_right.getTypeShape().typical_value try: self.getSimulator()(left, right) except TypeError as e: return e else: raise NuitkaAssumptionError( "Unexpected no-exception doing comparison simulation", self.operator, self.simulator, self.subnode_left.getTypeShape(), self.subnode_right.getTypeShape(), repr(left), repr(right), ) def computeExpression(self, trace_collection): left = self.subnode_left right = self.subnode_right if not self.left_available: self.left_available, self.left_comparable = left.getComparisonValue() if self.left_available: if not self.right_available: self.right_available, self.right_comparable = right.getComparisonValue() if self.right_available: return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getSimulator()( self.left_comparable, self.right_comparable ), description="Comparison of constant arguments.", ) left_shape = left.getTypeShape() right_shape = right.getTypeShape() self.type_shape, self.escape_desc = self.getComparisonShape( left_shape, right_shape ) exception_raise_exit = self.escape_desc.getExceptionExit() if exception_raise_exit is not None: trace_collection.onExceptionRaiseExit(exception_raise_exit) if ( self.escape_desc.isUnsupported() and self.canCreateUnsupportedException() ): result = wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpressionFromInstance( expression=self, exception=self.createUnsupportedException() ), old_node=self, side_effects=(self.subnode_left, self.subnode_right), ) return ( result, "new_raise", """Replaced comparator '%s' with %s %s arguments that cannot work.""" % ( self.comparator, self.subnode_left.getTypeShape(), self.subnode_right.getTypeShape(), ), ) # The value of these nodes escaped and could change its contents. # TODO: Comparisons don't do much, but add this. # if self.escape_desc.isValueEscaping(): # trace_collection.onValueEscapeRichComparison(left, right, self.comparator) if self.escape_desc.isControlFlowEscape(): # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self, None, None def mayRaiseException(self, exception_type): # TODO: Match more precisely return ( self.escape_desc is None or self.escape_desc.getExceptionExit() is not None or self.subnode_left.mayRaiseException(exception_type) or self.subnode_right.mayRaiseException(exception_type) ) def mayRaiseExceptionBool(self, exception_type): return self.type_shape.hasShapeSlotBool() is not True def mayRaiseExceptionComparison(self): return ( self.escape_desc is None or self.escape_desc.getExceptionExit() is not None ) class ExpressionComparisonLt(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_LT" comparator = "Lt" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonLtShape(right_shape) class ExpressionComparisonLte(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_LTE" comparator = "LtE" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonLteShape(right_shape) class ExpressionComparisonGt(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_GT" comparator = "Gt" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonGtShape(right_shape) class ExpressionComparisonGte(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_GTE" comparator = "GtE" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonGteShape(right_shape) class ExpressionComparisonEq(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_EQ" comparator = "Eq" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonEqShape(right_shape) class ExpressionComparisonNeq(ExpressionComparisonRichBase): kind = "EXPRESSION_COMPARISON_NEQ" comparator = "NotEq" def __init__(self, left, right, source_ref): ExpressionComparisonRichBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def getComparisonShape(left_shape, right_shape): return left_shape.getComparisonNeqShape(right_shape) class ExpressionComparisonIsIsNotBase( ExpressionBoolShapeExactMixin, ExpressionComparisonBase ): __slots__ = ( "left_available", "left_comparable", "right_available", "right_comparable", ) def __init__(self, left, right, source_ref): ExpressionComparisonBase.__init__( self, left=left, right=right, source_ref=source_ref ) self.left_available = False self.left_comparable = None self.right_available = False self.right_comparable = None @staticmethod def getDetails(): return {} def mayRaiseException(self, exception_type): return self.subnode_left.mayRaiseException( exception_type ) or self.subnode_right.mayRaiseException(exception_type) def computeExpression(self, trace_collection): left = self.subnode_left right = self.subnode_right if trace_collection.mustAlias(left, right): result = makeConstantReplacementNode( constant=self.comparator == "Is", node=self, user_provided=False ) if left.mayHaveSideEffects() or right.mayHaveSideEffects(): result = wrapExpressionWithSideEffects( side_effects=self.extractSideEffects(), old_node=self, new_node=result, ) return ( result, "new_constant", """\ Determined values to alias and therefore result of %s comparison.""" % (self.comparator), ) if trace_collection.mustNotAlias(left, right): result = makeConstantReplacementNode( constant=self.comparator != "Is", node=self, user_provided=False ) if left.mayHaveSideEffects() or right.mayHaveSideEffects(): result = wrapExpressionWithSideEffects( side_effects=self.extractSideEffects(), old_node=self, new_node=result, ) return ( result, "new_constant", """\ Determined values to not alias and therefore result of '%s' comparison.""" % (self.comparator), ) if not self.left_available: self.left_available, self.left_comparable = left.getComparisonValue() if self.left_available: if not self.right_available: self.right_available, self.right_comparable = right.getComparisonValue() if self.right_available: return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getSimulator()( self.left_comparable, self.right_comparable ), description="Comparison '%s' with constant arguments." % self.comparator, ) return self, None, None def extractSideEffects(self): return ( self.subnode_left.extractSideEffects() + self.subnode_right.extractSideEffects() ) def computeExpressionDrop(self, statement, trace_collection): from .NodeMakingHelpers import makeStatementOnlyNodesFromExpressions result = makeStatementOnlyNodesFromExpressions(expressions=self.getOperands()) del self.parent return ( result, "new_statements", """\ Removed %s comparison for unused result.""" % self.comparator, ) class ExpressionComparisonIs(ExpressionComparisonIsIsNotBase): kind = "EXPRESSION_COMPARISON_IS" comparator = "Is" def __init__(self, left, right, source_ref): ExpressionComparisonIsIsNotBase.__init__( self, left=left, right=right, source_ref=source_ref ) class ExpressionComparisonIsNot(ExpressionComparisonIsIsNotBase): kind = "EXPRESSION_COMPARISON_IS_NOT" comparator = "IsNot" def __init__(self, left, right, source_ref): ExpressionComparisonIsIsNotBase.__init__( self, left=left, right=right, source_ref=source_ref ) class ExpressionComparisonExceptionMatchBase( ExpressionBoolShapeExactMixin, ExpressionComparisonBase ): __slots__ = ( "left_available", "left_comparable", "right_available", "right_comparable", ) def __init__(self, left, right, source_ref): ExpressionComparisonBase.__init__( self, left=left, right=right, source_ref=source_ref ) self.left_available = False self.left_comparable = None self.right_available = False self.right_comparable = None @staticmethod def getDetails(): return {} def computeExpression(self, trace_collection): if not self.left_available: ( self.left_available, self.left_comparable, ) = self.subnode_left.getComparisonValue() if self.left_available: if not self.right_available: ( self.right_available, self.right_comparable, ) = self.subnode_right.getComparisonValue() if self.right_available: return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getSimulator()( self.left_comparable, self.right_comparable ), description="Exception matched with constant arguments.", ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def getSimulator(self): # TODO: Doesn't happen yet, but will once we trace exceptions. assert False return PythonOperators.all_comparison_functions[self.comparator] def mayRaiseException(self, exception_type): # TODO: Match errors that exception comparisons might raise more accurately. return ( self.subnode_left.mayRaiseException(exception_type) or self.subnode_right.mayRaiseException(exception_type) or self.mayRaiseExceptionComparison() ) def mayRaiseExceptionComparison(self): if python_version < 0x300: return False # TODO: Add shape for exceptions. type_shape = self.subnode_right.getTypeShape() if type_shape is tshape_exception_class: return False return True class ExpressionComparisonExceptionMatch(ExpressionComparisonExceptionMatchBase): kind = "EXPRESSION_COMPARISON_EXCEPTION_MATCH" comparator = "exception_match" class ExpressionComparisonExceptionMismatch(ExpressionComparisonExceptionMatchBase): kind = "EXPRESSION_COMPARISON_EXCEPTION_MISMATCH" comparator = "exception_mismatch" class ExpressionComparisonInNotInBase( ExpressionBoolShapeExactMixin, ExpressionComparisonBase ): __slots__ = ( "left_available", "left_comparable", "right_available", "right_comparable", ) def __init__(self, left, right, source_ref): ExpressionComparisonBase.__init__( self, left=left, right=right, source_ref=source_ref ) assert self.comparator in ("In", "NotIn") self.left_available = False self.left_comparable = None self.right_available = False self.right_comparable = None @staticmethod def getDetails(): return {} def mayRaiseException(self, exception_type): left = self.subnode_left if left.mayRaiseException(exception_type): return True right = self.subnode_right if right.mayRaiseException(exception_type): return True return right.mayRaiseExceptionIn(exception_type, left) def getSimulator(self): return PythonOperators.other_comparison_functions[self.comparator] def computeExpression(self, trace_collection): if not self.left_available: ( self.left_available, self.left_comparable, ) = self.subnode_left.getComparisonValue() if self.left_available: if not self.right_available: ( self.right_available, self.right_comparable, ) = self.subnode_right.getComparisonValue() if self.right_available: return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getSimulator()( self.left_comparable, self.right_comparable ), description="Contains check %s of constant arguments." % self.comparator, ) return self.subnode_right.computeExpressionComparisonIn( in_node=self, value_node=self.subnode_left, trace_collection=trace_collection, ) class ExpressionComparisonIn(ExpressionComparisonInNotInBase): kind = "EXPRESSION_COMPARISON_IN" comparator = "In" def __init__(self, left, right, source_ref): ExpressionComparisonInNotInBase.__init__( self, left=left, right=right, source_ref=source_ref ) class ExpressionComparisonNotIn(ExpressionComparisonInNotInBase): kind = "EXPRESSION_COMPARISON_NOT_IN" comparator = "NotIn" def __init__(self, left, right, source_ref): ExpressionComparisonInNotInBase.__init__( self, left=left, right=right, source_ref=source_ref ) _comparator_to_nodeclass = { "Is": ExpressionComparisonIs, "IsNot": ExpressionComparisonIsNot, "In": ExpressionComparisonIn, "NotIn": ExpressionComparisonNotIn, "Lt": ExpressionComparisonLt, "LtE": ExpressionComparisonLte, "Gt": ExpressionComparisonGt, "GtE": ExpressionComparisonGte, "Eq": ExpressionComparisonEq, "NotEq": ExpressionComparisonNeq, "exception_match": ExpressionComparisonExceptionMatch, "exception_mismatch": ExpressionComparisonExceptionMismatch, } def makeComparisonExpression(left, right, comparator, source_ref): return _comparator_to_nodeclass[comparator]( left=left, right=right, source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/nodes/IndicatorMixins.py0000600000372100037210000000524714166627112026360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module for node class mixins that indicate runtime determined node facts. These come into play after finalization only. All of the these attributes (and we could use properties instead) are determined once or from a default and then used like this. """ class MarkUnoptimizedFunctionIndicatorMixin(object): """Mixin for indication that a function contains an exec or star import. These do not access global variables directly, but check a locals dictionary first, because they do. """ # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self, flags): self.unoptimized_locals = flags is not None and "has_exec" in flags self.unqualified_exec = flags is not None and "has_unqualified_exec" in flags def isUnoptimized(self): return self.unoptimized_locals def isUnqualifiedExec(self): return self.unoptimized_locals and self.unqualified_exec class MarkNeedsAnnotationsMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self): self.needs_annotations_dict = False def markAsNeedsAnnotationsDictionary(self): """For use during building only. Indicate "__annotations__" need.""" self.needs_annotations_dict = True def needsAnnotationsDictionary(self): """For use during building only. Indicate "__annotations__" need.""" return self.needs_annotations_dict class EntryPointMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def __init__(self): self.trace_collection = None def setTraceCollection(self, trace_collection): previous = self.trace_collection self.trace_collection = trace_collection return previous def getTraceCollection(self): return self.trace_collection Nuitka-0.6.19.1/nuitka/nodes/AttributeLookupNodes.py0000600000372100037210000000705114166627112027375 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Attribute lookup nodes, generic one and base for generated ones. See AttributeNodes otherwise. """ from .ExpressionBases import ExpressionChildHavingBase class ExpressionAttributeLookup(ExpressionChildHavingBase): """Looking up an attribute of an object. Typically code like: source.attribute_name """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP" named_child = "expression" __slots__ = ("attribute_name",) def __init__(self, expression, attribute_name, source_ref): ExpressionChildHavingBase.__init__( self, value=expression, source_ref=source_ref ) self.attribute_name = attribute_name def getAttributeName(self): return self.attribute_name def getDetails(self): return {"attribute_name": self.attribute_name} def computeExpression(self, trace_collection): return self.subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name=self.attribute_name, trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseException( exception_type ) or self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name=self.attribute_name ) @staticmethod def isKnownToBeIterable(count): # TODO: Could be known. We would need for computeExpressionAttribute to # either return a new node, or a decision maker. return None class ExpressionAttributeLookupFixedBase(ExpressionChildHavingBase): """Looking up an attribute of an object. Typically code like: source.attribute_name """ attribute_name = None named_child = "expression" def __init__(self, expression, source_ref): ExpressionChildHavingBase.__init__( self, value=expression, source_ref=source_ref ) def getAttributeName(self): return self.attribute_name @staticmethod def getDetails(): return {} def computeExpression(self, trace_collection): return self.subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name=self.attribute_name, trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseException( exception_type ) or self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name=self.attribute_name ) @staticmethod def isKnownToBeIterable(count): # TODO: Could be known. We would need for computeExpressionAttribute to # either return a new node, or a decision maker. return None Nuitka-0.6.19.1/nuitka/nodes/ModuleAttributeNodes.py0000600000372100037210000001460614166627112027355 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module/Package attribute nodes The represent special values of the modules. The "__name__", "__package__", "__file__", and "__spec__" values can all be highly dynamic and version dependent These nodes are intended to allow for as much compile time optimization as possible, despite this difficulty. In some modes these node become constants quickly, in others they will present boundaries for optimization. """ from nuitka import Options from .ConstantRefNodes import makeConstantRefNode from .ExpressionBases import ExpressionBase, ExpressionNoSideEffectsMixin class ExpressionModuleAttributeBase(ExpressionBase): """Expression base class for module attributes. This """ # Base classes can be abstract, pylint: disable=abstract-method __slots__ = ("variable",) def __init__(self, variable, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.variable = variable def finalize(self): del self.parent del self.variable def getDetails(self): return {"variable": self.variable} def getVariable(self): return self.variable @staticmethod def mayRaiseException(exception_type): # These attributes can be expected to be present. return False class ExpressionModuleAttributeFileRef(ExpressionModuleAttributeBase): """Expression that represents accesses to __file__ of module. The __file__ is a static or dynamic value depending on the file reference mode. If it requests runtime, i.e. looks at where it is loaded from, then there is not a lot to be said about its value, otherwise it becomes a constant value quickly. """ kind = "EXPRESSION_MODULE_ATTRIBUTE_FILE_REF" def computeExpressionRaw(self, trace_collection): # There is not a whole lot to do here, the path will change at run # time, but options may disable that and make it predictable. if Options.getFileReferenceMode() != "runtime": result = makeConstantRefNode( constant=self.variable.getModule().getRunTimeFilename(), source_ref=self.source_ref, ) return result, "new_expression", "Using original '__file__' value." return self, None, None class ExpressionModuleAttributeNameRef(ExpressionModuleAttributeBase): """Expression that represents accesses to __name__ of module. For binaries this can be relatively well known, but modules living in a package, go by what loads them to ultimately determine their name. """ kind = "EXPRESSION_MODULE_ATTRIBUTE_NAME_REF" def computeExpressionRaw(self, trace_collection): # For binaries, we can know it definite, but not for modules. if not Options.shallMakeModule(): result = makeConstantRefNode( constant=self.variable.getModule().getRuntimeNameValue(), source_ref=self.source_ref, ) return result, "new_expression", "Using constant '__name__' value." return self, None, None class ExpressionModuleAttributePackageRef(ExpressionModuleAttributeBase): """Expression that represents accesses to __package__ of module. For binaries this can be relatively well known, but modules living in a package, go by what loads them to ultimately determine their parent package. """ kind = "EXPRESSION_MODULE_ATTRIBUTE_PACKAGE_REF" def computeExpressionRaw(self, trace_collection): # For binaries, we can know it definite, but not for modules. if not Options.shallMakeModule(): provider = self.variable.getModule() value = provider.getRuntimePackageValue() result = makeConstantRefNode(constant=value, source_ref=self.source_ref) return result, "new_expression", "Using constant '__package__' value." return self, None, None class ExpressionModuleAttributeLoaderRef(ExpressionModuleAttributeBase): """Expression that represents accesses to __loader__ of module. The loader of Nuitka is going to load the module, and there is not a whole lot to be said about it here, it is assumed to be largely ignored in user code. """ kind = "EXPRESSION_MODULE_ATTRIBUTE_LOADER_REF" def computeExpressionRaw(self, trace_collection): return self, None, None class ExpressionModuleAttributeSpecRef(ExpressionModuleAttributeBase): """Expression that represents accesses to __spec__ of module. The __spec__ is used by the loader mechanism and sometimes by code checking e.g. if something is a package. It exists only for modern Python. For the main program module, it's always None (it is also not really loaded in the same way as other code). """ kind = "EXPRESSION_MODULE_ATTRIBUTE_SPEC_REF" def computeExpressionRaw(self, trace_collection): if self.variable.getModule().isMainModule(): result = makeConstantRefNode(constant=None, source_ref=self.source_ref) return ( result, "new_expression", "Using constant '__spec__' value for main module.", ) return self, None, None class ExpressionNuitkaLoaderCreation(ExpressionNoSideEffectsMixin, ExpressionBase): __slots__ = ("provider",) kind = "EXPRESSION_NUITKA_LOADER_CREATION" def __init__(self, provider, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.provider = provider def finalize(self): del self.parent del self.provider def computeExpressionRaw(self, trace_collection): # Nothing can be done here. return self, None, None Nuitka-0.6.19.1/nuitka/nodes/BuiltinNextNodes.py0000600000372100037210000000701714166627112026507 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'next' built-in and unpacking special next. The unpacking next has only special that it raises a different exception text, explaining things about its context. """ from .ExpressionBases import ( ExpressionBuiltinSingleArgBase, ExpressionChildrenHavingBase, ) class ExpressionBuiltinNext1(ExpressionBuiltinSingleArgBase): __slots__ = ("may_not_raise",) kind = "EXPRESSION_BUILTIN_NEXT1" def __init__(self, value, source_ref): ExpressionBuiltinSingleArgBase.__init__( self, value=value, source_ref=source_ref ) self.may_not_raise = False def computeExpression(self, trace_collection): self.may_not_raise, result = self.subnode_value.computeExpressionNext1( next_node=self, trace_collection=trace_collection ) return result def mayRaiseExceptionOperation(self): return not self.may_not_raise def mayRaiseException(self, exception_type): return ( self.subnode_value.mayRaiseException(exception_type) or self.mayRaiseExceptionOperation() ) class ExpressionSpecialUnpack(ExpressionBuiltinNext1): __slots__ = ("count", "expected", "starred") kind = "EXPRESSION_SPECIAL_UNPACK" def __init__(self, value, count, expected, starred, source_ref): ExpressionBuiltinNext1.__init__(self, value=value, source_ref=source_ref) self.count = int(count) # TODO: Unused before 3.5 or higher, and even then starred is rare, maybe specialize for it. self.expected = int(expected) self.starred = starred def getDetails(self): result = ExpressionBuiltinNext1.getDetails(self) result["count"] = self.getCount() result["expected"] = self.getExpected() result["starred"] = self.getStarred() return result def getCount(self): return self.count def getExpected(self): return self.expected def getStarred(self): return self.starred class ExpressionBuiltinNext2(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_NEXT2" named_children = ("iterator", "default") def __init__(self, iterator, default, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"iterator": iterator, "default": default}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: The "iterator" should be investigated here, if it is iterable, # or if the default is raising. # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/SideEffectNodes.py0000600000372100037210000001076714166627112026251 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node that models side effects. Sometimes, the effect of an expression needs to be had, but the value itself does not matter at all. """ from .ExpressionBases import ExpressionChildrenHavingBase from .NodeMakingHelpers import makeStatementOnlyNodesFromExpressions def checkSideEffects(value): real_value = [] for child in value: if child.isExpressionSideEffects(): real_value.extend(child.subnode_side_effects) real_value.append(child.subnode_expression) else: assert child.isExpression() real_value.append(child) return tuple(real_value) class ExpressionSideEffects(ExpressionChildrenHavingBase): kind = "EXPRESSION_SIDE_EFFECTS" named_children = ("side_effects", "expression") checkers = {"side_effects": checkSideEffects} def __init__(self, side_effects, expression, source_ref): # We expect to be not used without there actually being side effects. assert side_effects ExpressionChildrenHavingBase.__init__( self, values={"side_effects": tuple(side_effects), "expression": expression}, source_ref=source_ref, ) @staticmethod def isExpressionSideEffects(): return True def getTypeShape(self): return self.subnode_expression.getTypeShape() def computeExpressionRaw(self, trace_collection): new_side_effects = [] side_effects = self.subnode_side_effects for count, side_effect in enumerate(side_effects): side_effect = trace_collection.onExpression(side_effect) if side_effect.willRaiseException(BaseException): for c in side_effects[count + 1 :]: c.finalize() if new_side_effects: expression = self.subnode_expression expression.finalize() self.setChild("expression", side_effect) return ( self, "new_expression", "Side effects caused exception raise.", ) else: del self.parent del self.subnode_side_effects return ( side_effect, "new_expression", "Side effects caused exception raise.", ) if side_effect.isExpressionSideEffects(): new_side_effects.extend(side_effect.subnode_side_effects) del side_effect.parent del side_effect.subnode_side_effects if side_effect is not None and side_effect.mayHaveSideEffects(): new_side_effects.append(side_effect) trace_collection.onExpression(self.subnode_expression) if not new_side_effects: return ( self.subnode_expression, "new_expression", "Removed empty side effects.", ) return self, None, None def willRaiseException(self, exception_type): for child in self.getVisitableNodes(): if child.willRaiseException(exception_type): return True return False def getTruthValue(self): return self.subnode_expression.getTruthValue() def computeExpressionDrop(self, statement, trace_collection): # Side effects can become statements. expressions = self.subnode_side_effects + (self.subnode_expression,) result = makeStatementOnlyNodesFromExpressions(expressions=expressions) return ( result, "new_statements", """\ Turned side effects of expression only statement into statements.""", ) Nuitka-0.6.19.1/nuitka/nodes/OperatorNodes.py0000600000372100037210000007356414166627112026047 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for unary and binary operations. No short-circuit involved, boolean 'not' is an unary operation like '-' is, no real difference. """ import copy import math from abc import abstractmethod from nuitka import PythonOperators from nuitka.Errors import NuitkaAssumptionError from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildrenHavingBase from .NodeMakingHelpers import ( makeRaiseExceptionReplacementExpressionFromInstance, wrapExpressionWithSideEffects, ) from .shapes.BuiltinTypeShapes import tshape_bool, tshape_int_or_long from .shapes.StandardShapes import ( ShapeLargeConstantValue, ShapeLargeConstantValuePredictable, tshape_unknown, vshape_unknown, ) class ExpressionPropertiesFromTypeShapeMixin(object): """Given a self.type_shape, this can derive default properties from there.""" # Mixins are required to slots __slots__ = () def isKnownToBeHashable(self): return self.type_shape.hasShapeSlotHash() class ExpressionOperationBinaryBase( ExpressionPropertiesFromTypeShapeMixin, ExpressionChildrenHavingBase ): """Base class for all binary operation expression.""" __slots__ = ("type_shape", "escape_desc", "inplace_suspect", "shape") named_children = ("left", "right") nice_children = tuple(child_name + " operand" for child_name in named_children) def __init__(self, left, right, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"left": left, "right": right}, source_ref=source_ref ) # Question might be asked early on, later this is cached from last computation. self.type_shape = tshape_unknown self.escape_desc = None self.inplace_suspect = False self.shape = vshape_unknown @staticmethod def isExpressionOperationBinary(): return True def getOperator(self): return self.operator def markAsInplaceSuspect(self): self.inplace_suspect = True def unmarkAsInplaceSuspect(self): self.inplace_suspect = False def isInplaceSuspect(self): return self.inplace_suspect def getOperands(self): return (self.subnode_left, self.subnode_right) def mayRaiseExceptionOperation(self): return self.escape_desc.getExceptionExit() is not None def mayRaiseException(self, exception_type): # TODO: Match getExceptionExit() more precisely against exception type given return ( self.escape_desc is None or self.escape_desc.getExceptionExit() is not None or self.subnode_left.mayRaiseException(exception_type) or self.subnode_right.mayRaiseException(exception_type) ) def getTypeShape(self): return self.type_shape @abstractmethod def _getOperationShape(self, left_shape, right_shape): pass @staticmethod def canCreateUnsupportedException(left_shape, right_shape): return hasattr(left_shape, "typical_value") and hasattr( right_shape, "typical_value" ) def createUnsupportedException(self, left_shape, right_shape): left = left_shape.typical_value right = right_shape.typical_value try: self.simulator(left, right) except TypeError as e: return e except Exception as e: raise NuitkaAssumptionError( "Unexpected exception type doing operation simulation", self.operator, self.simulator, left_shape, right_shape, repr(left), repr(right), e, "!=", ) else: raise NuitkaAssumptionError( "Unexpected no-exception doing operation simulation", self.operator, self.simulator, left_shape, right_shape, repr(left), repr(right), ) @staticmethod def _isTooLarge(): return False def _simulateOperation(self, trace_collection): left_value = self.subnode_left.getCompileTimeConstant() right_value = self.subnode_right.getCompileTimeConstant() # Avoid mutating owned by nodes values and potentially shared. if self.subnode_left.isMutable(): left_value = copy.copy(left_value) return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.simulator(left_value, right_value), description="Operator '%s' with constant arguments." % self.operator, ) def computeExpression(self, trace_collection): # Nothing to do anymore for large constants. if self.shape is not None and self.shape.isConstant(): return self, None, None left = self.subnode_left left_shape = left.getTypeShape() right = self.subnode_right right_shape = right.getTypeShape() self.type_shape, self.escape_desc = self._getOperationShape( left_shape, right_shape ) if left.isCompileTimeConstant() and right.isCompileTimeConstant(): if not self._isTooLarge(): return self._simulateOperation(trace_collection) exception_raise_exit = self.escape_desc.getExceptionExit() if exception_raise_exit is not None: trace_collection.onExceptionRaiseExit(exception_raise_exit) if self.escape_desc.isUnsupported() and self.canCreateUnsupportedException( left_shape, right_shape ): result = wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpressionFromInstance( expression=self, exception=self.createUnsupportedException( left_shape, right_shape, ), ), old_node=self, side_effects=(left, right), ) return ( result, "new_raise", "Replaced operator '%s' with %s %s arguments that cannot work." % (self.operator, left_shape, right_shape), ) if self.escape_desc.isValueEscaping(): # The value of these nodes escaped and could change its contents. trace_collection.removeKnowledge(left) trace_collection.removeKnowledge(right) if self.escape_desc.isControlFlowEscape(): # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self, None, None def canPredictIterationValues(self): # TODO: Actually we could very well, esp. for sequence repeats. # pylint: disable=no-self-use return False class ExpressionOperationAddMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def getValueShape(self): return self.shape def _isTooLarge(self): if self.subnode_left.isKnownToBeIterable( None ) and self.subnode_right.isKnownToBeIterable(None): size = ( self.subnode_left.getIterationLength() + self.subnode_right.getIterationLength() ) # TODO: Actually could make a predictor, but we don't use it yet. self.shape = ShapeLargeConstantValuePredictable( size=size, predictor=None, # predictValuesFromRightAndLeftValue, shape=self.subnode_left.getTypeShape(), ) return size > 256 else: return False class ExpressionOperationBinaryAdd( ExpressionOperationAddMixin, ExpressionOperationBinaryBase ): kind = "EXPRESSION_OPERATION_BINARY_ADD" def __init__(self, left, right, source_ref): ExpressionOperationBinaryBase.__init__( self, left=left, right=right, source_ref=source_ref ) operator = "Add" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryAddShape(right_shape) class ExpressionOperationBinarySub(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_SUB" operator = "Sub" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinarySubShape(right_shape) class ExpressionOperationMultMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def getValueShape(self): return self.shape def _isTooLarge(self): if self.subnode_right.isNumberConstant(): iter_length = self.subnode_left.getIterationLength() if iter_length is not None: size = iter_length * self.subnode_right.getCompileTimeConstant() if size > 256: self.shape = ShapeLargeConstantValuePredictable( size=size, predictor=None, # predictValuesFromRightAndLeftValue, shape=self.subnode_left.getTypeShape(), ) return True if self.subnode_left.isNumberConstant(): if ( self.subnode_left.isIndexConstant() and self.subnode_right.isIndexConstant() ): # Estimate with logarithm, if the result of number # calculations is computable with acceptable effort, # otherwise, we will have to do it at runtime. left_value = self.subnode_left.getCompileTimeConstant() if left_value != 0: right_value = self.subnode_right.getCompileTimeConstant() # TODO: Is this really useful, can this be really slow. if right_value != 0: if ( math.log10(abs(left_value)) + math.log10(abs(right_value)) > 20 ): self.shape = ShapeLargeConstantValue( size=None, shape=tshape_int_or_long ) return True elif self.subnode_left.isNumberConstant(): iter_length = self.subnode_right.getIterationLength() if iter_length is not None: left_value = self.subnode_left.getCompileTimeConstant() size = iter_length * left_value if iter_length * left_value > 256: self.shape = ShapeLargeConstantValuePredictable( size=size, predictor=None, # predictValuesFromRightAndLeftValue, shape=self.subnode_right.getTypeShape(), ) return True return False class ExpressionOperationBinaryMult( ExpressionOperationMultMixin, ExpressionOperationBinaryBase ): kind = "EXPRESSION_OPERATION_BINARY_MULT" operator = "Mult" simulator = PythonOperators.binary_operator_functions[operator] def __init__(self, left, right, source_ref): ExpressionOperationBinaryBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryMultShape(right_shape) def getIterationLength(self): left_length = self.subnode_left.getIterationLength() if left_length is not None: right_value = self.subnode_right.getIntegerValue() if right_value is not None: return left_length * right_value right_length = self.subnode_right.getIterationLength() if right_length is not None: left_value = self.subnode_left.getIntegerValue() if left_value is not None: return right_length * left_value return ExpressionOperationBinaryBase.getIterationLength(self) def extractSideEffects(self): left_length = self.subnode_left.getIterationLength() if left_length is not None: right_value = self.subnode_right.getIntegerValue() if right_value is not None: return ( self.subnode_left.extractSideEffects() + self.subnode_right.extractSideEffects() ) right_length = self.subnode_right.getIterationLength() if right_length is not None: left_value = self.subnode_left.getIntegerValue() if left_value is not None: return ( self.subnode_left.extractSideEffects() + self.subnode_right.extractSideEffects() ) return ExpressionOperationBinaryBase.extractSideEffects(self) class ExpressionOperationBinaryFloorDiv(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_FLOOR_DIV" operator = "FloorDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryFloorDivShape(right_shape) if python_version < 0x300: class ExpressionOperationBinaryOldDiv(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_OLD_DIV" operator = "OldDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryOldDivShape(right_shape) class ExpressionOperationBinaryTrueDiv(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_TRUE_DIV" operator = "TrueDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryTrueDivShape(right_shape) class ExpressionOperationBinaryMod(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_MOD" operator = "Mod" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryModShape(right_shape) class ExpressionOperationBinaryDivmod(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_DIVMOD" operator = "Divmod" simulator = PythonOperators.binary_operator_functions[operator] def __init__(self, left, right, source_ref): ExpressionOperationBinaryBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryDivmodShape(right_shape) class ExpressionOperationBinaryPow(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_POW" operator = "Pow" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryPowShape(right_shape) class ExpressionOperationLshiftMixin(object): # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () def getValueShape(self): return self.shape def _isTooLarge(self): if self.subnode_right.isNumberConstant(): if self.subnode_left.isNumberConstant(): # Estimate with logarithm, if the result of number # calculations is computable with acceptable effort, # otherwise, we will have to do it at runtime. left_value = self.subnode_left.getCompileTimeConstant() if left_value != 0: right_value = self.subnode_right.getCompileTimeConstant() # More than a typical shift, most likely a stupid test. if right_value > 64: self.shape = ShapeLargeConstantValue( size=None, shape=tshape_int_or_long ) return True return False class ExpressionOperationBinaryLshift( ExpressionOperationLshiftMixin, ExpressionOperationBinaryBase ): kind = "EXPRESSION_OPERATION_BINARY_LSHIFT" operator = "LShift" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryLShiftShape(right_shape) class ExpressionOperationBinaryRshift(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_RSHIFT" operator = "RShift" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryRShiftShape(right_shape) class ExpressionOperationBinaryBitOr(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_BIT_OR" operator = "BitOr" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitOrShape(right_shape) class ExpressionOperationBinaryBitAnd(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_BIT_AND" operator = "BitAnd" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitAndShape(right_shape) class ExpressionOperationBinaryBitXor(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_BIT_XOR" operator = "BitXor" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitXorShape(right_shape) if python_version >= 0x350: class ExpressionOperationBinaryMatMult(ExpressionOperationBinaryBase): kind = "EXPRESSION_OPERATION_BINARY_MAT_MULT" operator = "MatMult" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryMatMultShape(right_shape) _operator2binary_operation_nodeclass = { "Add": ExpressionOperationBinaryAdd, "Sub": ExpressionOperationBinarySub, "Mult": ExpressionOperationBinaryMult, "FloorDiv": ExpressionOperationBinaryFloorDiv, "TrueDiv": ExpressionOperationBinaryTrueDiv, "Mod": ExpressionOperationBinaryMod, # Divmod only from built-in call. "Pow": ExpressionOperationBinaryPow, "LShift": ExpressionOperationBinaryLshift, "RShift": ExpressionOperationBinaryRshift, "BitOr": ExpressionOperationBinaryBitOr, "BitAnd": ExpressionOperationBinaryBitAnd, "BitXor": ExpressionOperationBinaryBitXor, } if python_version < 0x300: _operator2binary_operation_nodeclass["OldDiv"] = ExpressionOperationBinaryOldDiv if python_version >= 0x350: _operator2binary_operation_nodeclass["MatMult"] = ExpressionOperationBinaryMatMult def makeBinaryOperationNode(operator, left, right, source_ref): node_class = _operator2binary_operation_nodeclass[operator] return node_class(left=left, right=right, source_ref=source_ref) class ExpressionOperationBinaryInplaceBase(ExpressionOperationBinaryBase): # Base classes can be abstract, pylint: disable=abstract-method """Base class for all inplace operations.""" def __init__(self, left, right, source_ref): ExpressionOperationBinaryBase.__init__( self, left=left, right=right, source_ref=source_ref ) self.inplace_suspect = True @staticmethod def isExpressionOperationInplace(): return True def computeExpression(self, trace_collection): # Nothing to do anymore for large constants. if self.shape is not None and self.shape.isConstant(): return self, None, None left = self.subnode_left left_shape = left.getTypeShape() right = self.subnode_right right_shape = right.getTypeShape() self.type_shape, self.escape_desc = self._getOperationShape( left_shape, right_shape ) if left.isCompileTimeConstant() and right.isCompileTimeConstant(): if not self._isTooLarge(): return self._simulateOperation(trace_collection) exception_raise_exit = self.escape_desc.getExceptionExit() if exception_raise_exit is not None: trace_collection.onExceptionRaiseExit(exception_raise_exit) if self.escape_desc.isUnsupported() and self.canCreateUnsupportedException( left_shape, right_shape ): result = wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpressionFromInstance( expression=self, exception=self.createUnsupportedException( left_shape, right_shape, ), ), old_node=self, side_effects=(left, right), ) return ( result, "new_raise", "Replaced inplace-operator '%s' with %s %s arguments that cannot work." % (self.operator, left_shape, right_shape), ) if self.escape_desc.isValueEscaping(): # The value of these nodes escaped and could change its contents. trace_collection.removeKnowledge(left) trace_collection.removeKnowledge(right) if self.escape_desc.isControlFlowEscape(): # Any code could be run, note that. trace_collection.onControlFlowEscape(self) if left_shape is tshape_bool: result = makeBinaryOperationNode( self.operator[1:], left, right, self.source_ref ) return trace_collection.computedExpressionResult( result, "new_expression", "Lowered inplace-operator '%s' to binary operation." % self.operator, ) return self, None, None class ExpressionOperationInplaceAdd( ExpressionOperationAddMixin, ExpressionOperationBinaryInplaceBase ): kind = "EXPRESSION_OPERATION_INPLACE_ADD" operator = "IAdd" simulator = PythonOperators.binary_operator_functions[operator] def __init__(self, left, right, source_ref): ExpressionOperationBinaryInplaceBase.__init__( self, left=left, right=right, source_ref=source_ref ) @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationInplaceAddShape(right_shape) class ExpressionOperationInplaceSub(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_SUB" operator = "ISub" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinarySubShape(right_shape) class ExpressionOperationInplaceMult(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_MULT" operator = "IMult" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryMultShape(right_shape) class ExpressionOperationInplaceFloorDiv(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_FLOOR_DIV" operator = "IFloorDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryFloorDivShape(right_shape) if python_version < 0x300: class ExpressionOperationInplaceOldDiv(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_OLD_DIV" operator = "IOldDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryOldDivShape(right_shape) class ExpressionOperationInplaceTrueDiv(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_TRUE_DIV" operator = "ITrueDiv" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryTrueDivShape(right_shape) class ExpressionOperationInplaceMod(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_MOD" operator = "IMod" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryModShape(right_shape) class ExpressionOperationInplacePow(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_POW" operator = "IPow" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryPowShape(right_shape) class ExpressionOperationInplaceLshift(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_LSHIFT" operator = "ILShift" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryLShiftShape(right_shape) class ExpressionOperationInplaceRshift(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_RSHIFT" operator = "IRShift" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryRShiftShape(right_shape) class ExpressionOperationInplaceBitOr(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_BIT_OR" operator = "IBitOr" simulator = PythonOperators.binary_operator_functions[operator] # No inplace bitor special handling before 3.9 if python_version < 0x390: @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitOrShape(right_shape) else: @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationInplaceBitOrShape(right_shape) class ExpressionOperationInplaceBitAnd(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_BIT_AND" operator = "IBitAnd" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitAndShape(right_shape) class ExpressionOperationInplaceBitXor(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_BIT_XOR" operator = "IBitXor" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryBitXorShape(right_shape) if python_version >= 0x350: class ExpressionOperationInplaceMatMult(ExpressionOperationBinaryInplaceBase): kind = "EXPRESSION_OPERATION_INPLACE_MAT_MULT" operator = "IMatMult" simulator = PythonOperators.binary_operator_functions[operator] @staticmethod def _getOperationShape(left_shape, right_shape): return left_shape.getOperationBinaryMatMultShape(right_shape) _operator2binary_inplace_nodeclass = { "IAdd": ExpressionOperationInplaceAdd, "ISub": ExpressionOperationInplaceSub, "IMult": ExpressionOperationInplaceMult, "IFloorDiv": ExpressionOperationInplaceFloorDiv, "ITrueDiv": ExpressionOperationInplaceTrueDiv, "IMod": ExpressionOperationInplaceMod, "IPow": ExpressionOperationInplacePow, "ILShift": ExpressionOperationInplaceLshift, "IRShift": ExpressionOperationInplaceRshift, "IBitOr": ExpressionOperationInplaceBitOr, "IBitAnd": ExpressionOperationInplaceBitAnd, "IBitXor": ExpressionOperationInplaceBitXor, } if python_version < 0x300: _operator2binary_inplace_nodeclass["IOldDiv"] = ExpressionOperationInplaceOldDiv if python_version >= 0x350: _operator2binary_inplace_nodeclass["IMatMult"] = ExpressionOperationInplaceMatMult def makeExpressionOperationBinaryInplace(operator, left, right, source_ref): node_class = _operator2binary_inplace_nodeclass[operator] return node_class(left=left, right=right, source_ref=source_ref) Nuitka-0.6.19.1/nuitka/nodes/FrameNodes.py0000600000372100037210000002545414166627112025301 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Frame nodes. The frame attaches name and other frame properties to a scope, where it is optional. For use in tracebacks, their created frame objects, potentially cached are essential. Otherwise, they are similar to statement sequences, so they inherit from them. """ from nuitka.PythonVersions import python_version from .CodeObjectSpecs import CodeObjectSpec from .FutureSpecs import fromFlags from .StatementNodes import StatementsSequence def checkFrameStatements(value): """Check that frames statements list value proper. Must not be None, must not contain None, and of course only statements sequences, or statements, may be empty. """ assert value is not None assert None not in value for statement in value: assert statement.isStatement() or statement.isStatementsFrame(), statement return tuple(value) class StatementsFrameBase(StatementsSequence): checkers = {"statements": checkFrameStatements} __slots__ = ("guard_mode", "code_object", "needs_frame_exception_preserve") def __init__(self, statements, guard_mode, code_object, source_ref): StatementsSequence.__init__(self, statements=statements, source_ref=source_ref) # TODO: Why not have multiple classes for this. self.guard_mode = guard_mode self.code_object = code_object self.needs_frame_exception_preserve = False def isStatementsFrame(self): return True def getDetails(self): result = {"code_object": self.code_object} result.update(StatementsSequence.getDetails(self)) return result def getDetailsForDisplay(self): result = StatementsSequence.getDetails(self) result.update() result.update(self.code_object.getDetails()) return result @classmethod def fromXML(cls, provider, source_ref, **args): code_object_args = {} other_args = {} for key, value in args.items(): if key.startswith("co_"): code_object_args[key] = value elif key == "code_flags": code_object_args["future_spec"] = fromFlags(args["code_flags"]) else: other_args[key] = value code_object = CodeObjectSpec(**code_object_args) return cls(code_object=code_object, source_ref=source_ref, **other_args) def getGuardMode(self): return self.guard_mode def needsExceptionFramePreservation(self): if python_version < 0x300: return self.guard_mode != "generator" else: return True def getVarNames(self): return self.code_object.getVarNames() def updateLocalNames(self): """For use during variable closure phase. Finalize attributes.""" provider = self.getParentVariableProvider() if not provider.isCompiledPythonModule(): if ( provider.isExpressionGeneratorObjectBody() or provider.isExpressionCoroutineObjectBody() or provider.isExpressionAsyncgenObjectBody() ): closure_provider = provider.getParentVariableProvider() else: closure_provider = provider if closure_provider.isExpressionFunctionBody(): closure_variables = closure_provider.getClosureVariables() else: closure_variables = () self.code_object.updateLocalNames( [variable.getName() for variable in provider.getLocalVariables()], [ variable.getName() for variable in closure_variables if variable.getOwner() is not closure_provider ], ) entry_point = provider.getEntryPoint() is_optimized = ( not entry_point.isCompiledPythonModule() and not entry_point.isExpressionClassBody() and not entry_point.isUnoptimized() ) self.code_object.setFlagIsOptimizedValue(is_optimized) new_locals = not provider.isCompiledPythonModule() and ( python_version < 0x340 or (not provider.isExpressionClassBody() and not provider.isUnoptimized()) ) self.code_object.setFlagNewLocalsValue(new_locals) def markAsFrameExceptionPreserving(self): self.needs_frame_exception_preserve = True def needsFrameExceptionPreserving(self): return self.needs_frame_exception_preserve def getCodeObject(self): return self.code_object def computeStatementsSequence(self, trace_collection): # The extraction of parts of the frame that can be moved before or after # the frame scope, takes it toll to complexity, pylint: disable=too-many-branches new_statements = [] statements = self.subnode_statements for count, statement in enumerate(statements): # May be frames embedded. if statement.isStatementsFrame(): new_statement = statement.computeStatementsSequence( trace_collection=trace_collection ) else: new_statement = trace_collection.onStatement(statement=statement) if new_statement is not None: if ( new_statement.isStatementsSequence() and not new_statement.isStatementsFrame() ): new_statements.extend(new_statement.subnode_statements) else: new_statements.append(new_statement) if ( statement is not statements[-1] and new_statement.isStatementAborting() ): trace_collection.signalChange( "new_statements", statements[count + 1].getSourceReference(), "Removed dead statements.", ) break if not new_statements: trace_collection.signalChange( "new_statements", self.source_ref, "Removed empty frame object of '%s'." % self.code_object.getCodeObjectName(), ) return None # If our statements changed just now, they are not immediately usable, # so do this in two steps. Next time we can reduce the frame scope just # as well. if statements != tuple(new_statements): self.setChild("statements", new_statements) return self # Determine statements inside the frame, that need not be in a frame, # because they wouldn't raise an exception. outside_pre = [] while new_statements and not new_statements[0].needsFrame(): outside_pre.append(new_statements[0]) del new_statements[0] outside_post = [] while new_statements and not new_statements[-1].needsFrame(): outside_post.insert(0, new_statements[-1]) del new_statements[-1] if outside_pre or outside_post: from .NodeMakingHelpers import ( makeStatementsSequenceReplacementNode, ) if new_statements: self.setChild("statements", new_statements) return makeStatementsSequenceReplacementNode( statements=outside_pre + [self] + outside_post, node=self ) else: trace_collection.signalChange( "new_statements", self.source_ref, "Removed useless frame object of '%s'." % self.code_object.getCodeObjectName(), ) return makeStatementsSequenceReplacementNode( statements=outside_pre + outside_post, node=self ) else: if statements != new_statements: self.setChild("statements", new_statements) return self class StatementsFrameModule(StatementsFrameBase): kind = "STATEMENTS_FRAME_MODULE" def __init__(self, statements, code_object, source_ref): StatementsFrameBase.__init__( self, statements=statements, code_object=code_object, guard_mode="once", source_ref=source_ref, ) @staticmethod def hasStructureMember(): return False class StatementsFrameFunction(StatementsFrameBase): kind = "STATEMENTS_FRAME_FUNCTION" def __init__(self, statements, code_object, source_ref): StatementsFrameBase.__init__( self, statements=statements, code_object=code_object, guard_mode="full", source_ref=source_ref, ) @staticmethod def hasStructureMember(): return False class StatementsFrameGenerator(StatementsFrameBase): kind = "STATEMENTS_FRAME_GENERATOR" def __init__(self, statements, code_object, source_ref): StatementsFrameBase.__init__( self, statements=statements, code_object=code_object, guard_mode="generator", source_ref=source_ref, ) @staticmethod def hasStructureMember(): return True class StatementsFrameCoroutine(StatementsFrameBase): kind = "STATEMENTS_FRAME_COROUTINE" def __init__(self, statements, code_object, source_ref): StatementsFrameBase.__init__( self, statements=statements, code_object=code_object, guard_mode="generator", source_ref=source_ref, ) @staticmethod def hasStructureMember(): return True class StatementsFrameAsyncgen(StatementsFrameBase): kind = "STATEMENTS_FRAME_ASYNCGEN" def __init__(self, statements, code_object, source_ref): StatementsFrameBase.__init__( self, statements=statements, code_object=code_object, guard_mode="generator", source_ref=source_ref, ) @staticmethod def hasStructureMember(): return True Nuitka-0.6.19.1/nuitka/nodes/ConditionalNodes.py0000600000372100037210000006401214166627112026503 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Conditional nodes. These is the conditional expression '(a if b else c)' and the conditional statement, 'if a: ... else: ...' and there is no 'elif', because that is expressed via nesting of conditional statements. """ from nuitka.optimizations.TraceCollections import TraceCollectionBranch from .BuiltinTypeNodes import ExpressionBuiltinBool from .Checkers import checkStatementsSequenceOrNone from .ExpressionBases import ExpressionChildrenHavingBase from .NodeBases import StatementChildrenHavingBase from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, wrapExpressionWithNodeSideEffects, wrapStatementWithSideEffects, ) from .OperatorNodesUnary import ExpressionOperationNot from .shapes.BuiltinTypeShapes import tshape_bool, tshape_unknown from .StatementNodes import StatementsSequence class ExpressionConditional(ExpressionChildrenHavingBase): kind = "EXPRESSION_CONDITIONAL" named_children = ("condition", "expression_yes", "expression_no") def __init__(self, condition, expression_yes, expression_no, source_ref): ExpressionChildrenHavingBase.__init__( self, values={ "condition": condition, "expression_yes": expression_yes, "expression_no": expression_no, }, source_ref=source_ref, ) def getTypeShape(self): yes_shape = self.subnode_expression_yes.getTypeShape() if yes_shape is tshape_unknown: return tshape_unknown else: no_shape = self.subnode_expression_no.getTypeShape() if no_shape is yes_shape: return no_shape else: return tshape_unknown def getBranches(self): return (self.subnode_expression_yes, self.subnode_expression_no) def computeExpressionRaw(self, trace_collection): # This is rather complex stuff, pylint: disable=too-many-branches # Query the truth value after the expression is evaluated, once it is # evaluated in onExpression, it is known. condition = trace_collection.onExpression(expression=self.subnode_condition) # No need to look any further, if the condition raises, the branches do # not matter at all. if condition.willRaiseException(BaseException): return ( condition, "new_raise", """\ Conditional expression already raises implicitly in condition, removing \ branches.""", ) # Tell it we are evaluation it for boolean value only, it may demote # itself possibly. condition.computeExpressionBool(trace_collection) condition = self.subnode_condition # Decide this based on truth value of condition. truth_value = condition.getTruthValue() # TODO: We now know that condition evaluates to true for the yes branch # and to not true for no branch, the branch should know that. yes_branch = self.subnode_expression_yes # Continue to execute for yes branch unless we know it's not going to be # relevant. if truth_value is not False: branch_yes_collection = TraceCollectionBranch( parent=trace_collection, name="conditional expression yes branch" ) branch_yes_collection.computeBranch(branch=yes_branch) # May have just gone away, so fetch it again. yes_branch = self.subnode_expression_yes # If it's aborting, it doesn't contribute to merging. if yes_branch.willRaiseException(BaseException): branch_yes_collection = None else: branch_yes_collection = None no_branch = self.subnode_expression_no # Continue to execute for yes branch. if truth_value is not True: branch_no_collection = TraceCollectionBranch( parent=trace_collection, name="conditional expression no branch" ) branch_no_collection.computeBranch(branch=no_branch) # May have just gone away, so fetch it again. no_branch = self.subnode_expression_no # If it's aborting, it doesn't contribute to merging. if no_branch.willRaiseException(BaseException): branch_no_collection = None else: branch_no_collection = None if truth_value is True: trace_collection.replaceBranch(branch_yes_collection) elif truth_value is False: trace_collection.replaceBranch(branch_no_collection) else: # Merge into parent execution. trace_collection.mergeBranches(branch_yes_collection, branch_no_collection) if truth_value is True: return ( wrapExpressionWithNodeSideEffects( new_node=self.subnode_expression_yes, old_node=condition ), "new_expression", "Conditional expression predicted to yes case.", ) elif truth_value is False: return ( wrapExpressionWithNodeSideEffects( new_node=self.subnode_expression_no, old_node=condition ), "new_expression", "Conditional expression predicted to no case.", ) else: return self, None, None def computeExpressionDrop(self, statement, trace_collection): result = makeStatementConditional( condition=self.subnode_condition, yes_branch=makeStatementExpressionOnlyReplacementNode( expression=self.subnode_expression_yes, node=self.subnode_expression_yes ), no_branch=makeStatementExpressionOnlyReplacementNode( expression=self.subnode_expression_no, node=self.subnode_expression_no ), source_ref=self.source_ref, ) del self.parent return ( result, "new_statements", """\ Convert conditional expression with unused result into conditional statement.""", ) def mayHaveSideEffectsBool(self): # The bool will me made on either side. if self.subnode_expression_yes.mayHaveSideEffectsBool(): return True if self.subnode_expression_no.mayHaveSideEffectsBool(): return True return False def mayRaiseException(self, exception_type): condition = self.subnode_condition if condition.mayRaiseException(exception_type): return True if condition.mayRaiseExceptionBool(exception_type): return True yes_branch = self.subnode_expression_yes # Handle branches that became empty behind our back if yes_branch is not None and yes_branch.mayRaiseException(exception_type): return True no_branch = self.subnode_expression_no # Handle branches that became empty behind our back if no_branch is not None and no_branch.mayRaiseException(exception_type): return True return False def mayRaiseExceptionBool(self, exception_type): if self.subnode_condition.mayRaiseExceptionBool(exception_type): return True if self.subnode_expression_yes.mayRaiseExceptionBool(exception_type): return True if self.subnode_expression_no.mayRaiseExceptionBool(exception_type): return True return False def getIntegerValue(self): result_yes = self.subnode_expression_yes.getIntegerValue() result_no = self.subnode_expression_no.getIntegerValue() if result_yes == result_no: return result_yes else: return None class ExpressionConditionalBoolBase(ExpressionChildrenHavingBase): named_children = ("left", "right") def __init__(self, left, right, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"left": left, "right": right}, source_ref=source_ref ) def computeExpressionRaw(self, trace_collection): # Query the truth value after the expression is evaluated, once it is # evaluated in onExpression, it is known. left = trace_collection.onExpression(expression=self.subnode_left) # No need to look any further, if the condition raises, the branches do # not matter at all. if left.willRaiseException(BaseException): return ( left, "new_raise", """\ Conditional %s statements already raises implicitly in condition, removing \ branches.""" % self.conditional_kind, ) if not left.mayRaiseException(BaseException) and left.mayRaiseExceptionBool( BaseException ): trace_collection.onExceptionRaiseExit(BaseException) # Decide this based on truth value of condition. truth_value = left.getTruthValue() truth_value_use_left = self.conditional_kind == "or" truth_value_use_right = not truth_value_use_left right = self.subnode_right # Continue to execute for yes branch unless we know it's not going to be # relevant. if truth_value is not truth_value_use_left: # TODO: We now know that left evaluates and we should tell the # branch that. branch_yes_collection = TraceCollectionBranch( parent=trace_collection, name="boolean %s right branch" % self.conditional_kind, ) branch_yes_collection.computeBranch(branch=right) # May have just gone away, so fetch it again. right = self.subnode_right # If it's aborting, it doesn't contribute to merging. if right.willRaiseException(BaseException): branch_yes_collection = None else: branch_yes_collection = None if branch_yes_collection: # Merge into parent execution. trace_collection.mergeBranches(branch_yes_collection, None) if truth_value is truth_value_use_left: return ( left, "new_expression", "Conditional '%s' expression predicted to left value." % self.conditional_kind, ) elif truth_value is truth_value_use_right: return ( wrapExpressionWithNodeSideEffects(new_node=right, old_node=left), "new_expression", "Conditional '%s' expression predicted right value." % self.conditional_kind, ) else: return self, None, None def mayRaiseException(self, exception_type): left = self.subnode_left if left.mayRaiseException(exception_type): return True if left.mayRaiseExceptionBool(exception_type): return True right = self.subnode_right if right.mayRaiseException(exception_type): return True return False def mayRaiseExceptionBool(self, exception_type): # The and/or bool will be working on either side. if self.subnode_left.mayRaiseExceptionBool(exception_type): return True if self.subnode_right.mayRaiseExceptionBool(exception_type): return True return False def mayHaveSideEffectsBool(self): if self.subnode_left.mayHaveSideEffectsBool(): return True if self.subnode_right.mayHaveSideEffectsBool(): return True return False class ExpressionConditionalOr(ExpressionConditionalBoolBase): kind = "EXPRESSION_CONDITIONAL_OR" conditional_kind = "or" def __init__(self, left, right, source_ref): ExpressionConditionalBoolBase.__init__( self, left=left, right=right, source_ref=source_ref ) def computeExpressionDrop(self, statement, trace_collection): result = makeStatementConditional( condition=self.subnode_left, yes_branch=None, no_branch=makeStatementExpressionOnlyReplacementNode( expression=self.subnode_right, node=self.subnode_right ), source_ref=self.source_ref, ) del self.parent return ( result, "new_statements", """\ Convert conditional 'or' expression with unused result into conditional statement.""", ) class ExpressionConditionalAnd(ExpressionConditionalBoolBase): kind = "EXPRESSION_CONDITIONAL_AND" conditional_kind = "and" def __init__(self, left, right, source_ref): ExpressionConditionalBoolBase.__init__( self, left=left, right=right, source_ref=source_ref ) def computeExpressionDrop(self, statement, trace_collection): result = makeStatementConditional( condition=self.subnode_left, no_branch=None, yes_branch=makeStatementExpressionOnlyReplacementNode( expression=self.subnode_right, node=self.subnode_right ), source_ref=self.source_ref, ) del self.parent return ( result, "new_statements", """\ Convert conditional 'and' expression with unused result into conditional statement.""", ) class StatementConditional(StatementChildrenHavingBase): kind = "STATEMENT_CONDITIONAL" named_children = ("condition", "yes_branch", "no_branch") checkers = { "yes_branch": checkStatementsSequenceOrNone, "no_branch": checkStatementsSequenceOrNone, } def __init__(self, condition, yes_branch, no_branch, source_ref): StatementChildrenHavingBase.__init__( self, values={ "condition": condition, "yes_branch": yes_branch, "no_branch": no_branch, }, source_ref=source_ref, ) def isStatementAborting(self): yes_branch = self.subnode_yes_branch if yes_branch is not None: if yes_branch.isStatementAborting(): no_branch = self.subnode_no_branch if no_branch is not None: return no_branch.isStatementAborting() else: return False else: return False else: return False def mayRaiseException(self, exception_type): condition = self.subnode_condition if condition.mayRaiseException(exception_type): return True if condition.mayRaiseExceptionBool(exception_type): return True yes_branch = self.subnode_yes_branch # Handle branches that became empty behind our back if yes_branch is not None and yes_branch.mayRaiseException(exception_type): return True no_branch = self.subnode_no_branch # Handle branches that became empty behind our back if no_branch is not None and no_branch.mayRaiseException(exception_type): return True return False def needsFrame(self): condition = self.subnode_condition if condition.mayRaiseException(BaseException): return True if condition.mayRaiseExceptionBool(BaseException): return True yes_branch = self.subnode_yes_branch # Handle branches that became empty behind our back if yes_branch is not None and yes_branch.needsFrame(): return True no_branch = self.subnode_no_branch # Handle branches that became empty behind our back if no_branch is not None and no_branch.needsFrame(): return True return False def computeStatement(self, trace_collection): # This is rather complex stuff, pylint: disable=too-many-branches,too-many-statements condition = trace_collection.onExpression(expression=self.subnode_condition) # No need to look any further, if the condition raises, the branches do # not matter at all. if condition.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=condition, node=self ) return ( result, "new_raise", """\ Conditional statements already raises implicitly in condition, removing \ branches.""", ) # Tell it we are evaluation it for boolean value only, it may demote # itself possibly. condition.computeExpressionBool(trace_collection) condition = self.subnode_condition # Query the truth value after the expression is evaluated, once it is # evaluated in onExpression, it is known. truth_value = condition.getTruthValue() # TODO: We now know that condition evaluates to true for the yes branch # and to not true for no branch, the branch collection should know that. yes_branch = self.subnode_yes_branch no_branch = self.subnode_no_branch # Handle branches that became empty behind our back. if yes_branch is not None: if not yes_branch.subnode_statements: yes_branch.finalize() yes_branch = None self.clearChild("yes_branch") if no_branch is not None: if not no_branch.subnode_statements: no_branch.finalize() no_branch = None self.clearChild("no_branch") # Consider to not remove branches that we know won't be taken. if yes_branch is not None and truth_value is False: trace_collection.signalChange( tags="new_statements", source_ref=yes_branch.source_ref, message="Removed conditional branch that cannot be taken due to false condition value.", ) yes_branch.finalize() self.clearChild("yes_branch") yes_branch = None if no_branch is not None and truth_value is True: trace_collection.signalChange( tags="new_statements", source_ref=no_branch.source_ref, message="Removed 'else' branch that cannot be taken due to true condition value.", ) no_branch.finalize() self.clearChild("no_branch") no_branch = None # Continue to execute for yes branch unless we know it's not going to be # relevant. if yes_branch is not None: branch_yes_collection = TraceCollectionBranch( parent=trace_collection, name="conditional yes branch" ) branch_yes_collection.computeBranch(branch=yes_branch) # May have just gone away, so fetch it again. yes_branch = self.subnode_yes_branch # If it's aborting, it doesn't contribute to merging. if yes_branch is None or yes_branch.isStatementAborting(): branch_yes_collection = None else: branch_yes_collection = None # Continue to execute for yes branch. if no_branch is not None: branch_no_collection = TraceCollectionBranch( parent=trace_collection, name="conditional no branch" ) branch_no_collection.computeBranch(branch=no_branch) # May have just gone away, so fetch it again. no_branch = self.subnode_no_branch # If it's aborting, it doesn't contribute to merging. if no_branch is None or no_branch.isStatementAborting(): branch_no_collection = None else: branch_no_collection = None if truth_value is True: if branch_yes_collection is not None: trace_collection.replaceBranch(branch_yes_collection) elif truth_value is False: if branch_no_collection is not None: trace_collection.replaceBranch(branch_no_collection) else: trace_collection.mergeBranches(branch_yes_collection, branch_no_collection) # Both branches may have become empty, which case, the statement needs # not remain. if yes_branch is None and no_branch is None: # Need to keep the boolean check. if truth_value is None: condition = ExpressionBuiltinBool( value=condition, source_ref=condition.getSourceReference() ) if condition.mayHaveSideEffects(): # With both branches eliminated, the condition remains as a side # effect. result = makeStatementExpressionOnlyReplacementNode( expression=condition, node=self ) del self.parent return ( result, "new_statements", """\ Both branches have no effect, reduced to evaluate condition.""", ) else: self.finalize() return ( None, "new_statements", """\ Removed conditional statement without effect.""", ) # Note: Checking the condition late, so that the surviving branch got # processed already. Returning without doing that, will corrupt the SSA # results. TODO: Could pretend the other branch didn't exist to save # complexity the merging of processing. if truth_value is not None: if truth_value is True: choice = "true" new_statement = yes_branch if no_branch is not None: no_branch.finalize() else: choice = "false" new_statement = no_branch if yes_branch is not None: yes_branch.finalize() new_statement = wrapStatementWithSideEffects( new_node=new_statement, old_node=condition, allow_none=True, # surviving branch may empty ) del self.parent return ( new_statement, "new_statements", """\ Condition for branch statement was predicted to be always %s.""" % choice, ) # If there is no "yes" branch, remove that. Maybe a bad idea though. if yes_branch is None: # Would be eliminated already, if there wasn't any "no" branch # either. assert no_branch is not None new_statement = makeStatementConditional( condition=ExpressionOperationNot( operand=condition, source_ref=condition.getSourceReference() ), yes_branch=no_branch, no_branch=None, source_ref=self.source_ref, ) del self.parent return ( new_statement, "new_statements", """\ Empty 'yes' branch for conditional statement treated with inverted condition check.""", ) return self, None, None def mayReturn(self): yes_branch = self.subnode_yes_branch if yes_branch is not None and yes_branch.mayReturn(): return True no_branch = self.subnode_no_branch if no_branch is not None and no_branch.mayReturn(): return True return False def mayBreak(self): yes_branch = self.subnode_yes_branch if yes_branch is not None and yes_branch.mayBreak(): return True no_branch = self.subnode_no_branch if no_branch is not None and no_branch.mayBreak(): return True return False def mayContinue(self): yes_branch = self.subnode_yes_branch if yes_branch is not None and yes_branch.mayContinue(): return True no_branch = self.subnode_no_branch if no_branch is not None and no_branch.mayContinue(): return True return False @staticmethod def getStatementNiceName(): return "branch statement" def makeNotExpression(expression): # These are invertible with bool type shape. if expression.isExpressionComparison() and expression.getTypeShape() is tshape_bool: return expression.makeInverseComparision() else: return ExpressionOperationNot( operand=expression, source_ref=expression.getSourceReference() ) def makeStatementConditional(condition, yes_branch, no_branch, source_ref): """Create conditional statement, with yes_branch not being empty. May have to invert condition to achieve that. """ if yes_branch is None: condition = makeNotExpression(expression=condition) yes_branch, no_branch = no_branch, yes_branch if yes_branch is not None and not yes_branch.isStatementsSequence(): yes_branch = StatementsSequence( statements=(yes_branch,), source_ref=yes_branch.source_ref ) if no_branch is not None and not no_branch.isStatementsSequence(): no_branch = StatementsSequence( statements=(no_branch,), source_ref=no_branch.source_ref ) return StatementConditional( condition=condition, yes_branch=yes_branch, no_branch=no_branch, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinTypeNodes.py0000600000372100037210000002617114166627112026514 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in type nodes tuple/list/set/float/str/unicode etc. These are all very simple and have predictable properties, because we know their type and that should allow some important optimizations. """ from nuitka.specs import BuiltinParameterSpecs from .ConstantRefNodes import makeConstantRefNode from .ExpressionBases import ( CompileTimeConstantExpressionBase, ExpressionBuiltinSingleArgBase, ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionSpecBasedComputationMixin, ) from .ExpressionShapeMixins import ( ExpressionBoolShapeExactMixin, ExpressionBytearrayShapeExactMixin, ExpressionBytesShapeExactMixin, ExpressionFrozensetShapeExactMixin, ExpressionListShapeExactMixin, ExpressionSetShapeExactMixin, ExpressionTupleShapeExactMixin, ) from .NodeMakingHelpers import ( makeConstantReplacementNode, wrapExpressionWithNodeSideEffects, ) from .shapes.BuiltinTypeShapes import ( tshape_bytes_derived, tshape_float_derived, tshape_str_derived, tshape_unicode_derived, ) class ExpressionBuiltinTypeBase(ExpressionBuiltinSingleArgBase): pass class ExpressionBuiltinContainerBase( ExpressionSpecBasedComputationMixin, ExpressionChildHavingBase ): builtin_spec = None named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) def computeExpression(self, trace_collection): value = self.subnode_value if value is None: return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=() ) elif value.isExpressionConstantXrangeRef(): if value.getIterationLength() <= 256: return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(value,) ) else: return self, None, None else: return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(value,) ) class ExpressionBuiltinTuple( ExpressionTupleShapeExactMixin, ExpressionBuiltinContainerBase ): kind = "EXPRESSION_BUILTIN_TUPLE" builtin_spec = BuiltinParameterSpecs.builtin_tuple_spec class ExpressionBuiltinList( ExpressionListShapeExactMixin, ExpressionBuiltinContainerBase ): kind = "EXPRESSION_BUILTIN_LIST" builtin_spec = BuiltinParameterSpecs.builtin_list_spec class ExpressionBuiltinSet( ExpressionSetShapeExactMixin, ExpressionBuiltinContainerBase ): kind = "EXPRESSION_BUILTIN_SET" builtin_spec = BuiltinParameterSpecs.builtin_set_spec class ExpressionBuiltinFrozenset( ExpressionFrozensetShapeExactMixin, ExpressionBuiltinContainerBase ): kind = "EXPRESSION_BUILTIN_FROZENSET" builtin_spec = BuiltinParameterSpecs.builtin_frozenset_spec class ExpressionBuiltinFloat(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_FLOAT" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) @staticmethod def getTypeShape(): # TODO: Depending on input type shape, we should improve this. return tshape_float_derived def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionFloat( float_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseExceptionFloat(exception_type) class ExpressionBuiltinBool(ExpressionBoolShapeExactMixin, ExpressionBuiltinTypeBase): kind = "EXPRESSION_BUILTIN_BOOL" builtin_spec = BuiltinParameterSpecs.builtin_bool_spec def computeExpression(self, trace_collection): value = self.subnode_value truth_value = value.getTruthValue() if truth_value is not None: result = wrapExpressionWithNodeSideEffects( new_node=makeConstantReplacementNode( constant=truth_value, node=self, user_provided=False ), old_node=value, ) return ( result, "new_constant", "Predicted truth value of built-in bool argument", ) return ExpressionBuiltinTypeBase.computeExpression(self, trace_collection) class ExpressionBuiltinUnicodeBase( ExpressionSpecBasedComputationMixin, ExpressionChildrenHavingBase ): named_children = ("value", "encoding", "errors") def __init__(self, value, encoding, errors, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"value": value, "encoding": encoding, "errors": errors}, source_ref=source_ref, ) def computeExpression(self, trace_collection): args = [self.subnode_value, self.subnode_encoding, self.subnode_errors] while args and args[-1] is None: del args[-1] # The value of that node escapes and could change its contents. if self.subnode_value is not None: trace_collection.onValueEscapeStr(self.subnode_value) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=tuple(args) ) class ExpressionBuiltinStrP2(ExpressionBuiltinTypeBase): """Python2 built-in str call.""" kind = "EXPRESSION_BUILTIN_STR_P2" builtin_spec = BuiltinParameterSpecs.builtin_str_spec def computeExpression(self, trace_collection): ( new_node, change_tags, change_desc, ) = ExpressionBuiltinTypeBase.computeExpression(self, trace_collection) if new_node is self: str_value = self.subnode_value.getStrValue() if str_value is not None: new_node = wrapExpressionWithNodeSideEffects( new_node=str_value, old_node=self.subnode_value ) change_tags = "new_expression" change_desc = "Predicted 'str' built-in result" return new_node, change_tags, change_desc @staticmethod def getTypeShape(): return tshape_str_derived class ExpressionBuiltinUnicodeP2(ExpressionBuiltinUnicodeBase): """Python2 built-in unicode call.""" kind = "EXPRESSION_BUILTIN_UNICODE_P2" builtin_spec = BuiltinParameterSpecs.builtin_unicode_p2_spec @staticmethod def getTypeShape(): return tshape_unicode_derived class ExpressionBuiltinStrP3(ExpressionBuiltinUnicodeBase): """Python3 built-in str call.""" kind = "EXPRESSION_BUILTIN_STR_P3" builtin_spec = BuiltinParameterSpecs.builtin_str_spec @staticmethod def getTypeShape(): return tshape_str_derived class ExpressionBuiltinBytes3( ExpressionBytesShapeExactMixin, ExpressionBuiltinUnicodeBase ): kind = "EXPRESSION_BUILTIN_BYTES3" builtin_spec = BuiltinParameterSpecs.builtin_bytes_p3_spec class ExpressionBuiltinBytes1(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_BYTES1" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) @staticmethod def getTypeShape(): # TODO: Depending on input type shape, we should improve this. return tshape_bytes_derived def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionBytes( bytes_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseExceptionBytes(exception_type) class ExpressionBuiltinBytearray1( ExpressionBytearrayShapeExactMixin, ExpressionBuiltinTypeBase ): kind = "EXPRESSION_BUILTIN_BYTEARRAY1" builtin_spec = BuiltinParameterSpecs.builtin_bytearray_spec def __init__(self, value, source_ref): ExpressionBuiltinTypeBase.__init__(self, value=value, source_ref=source_ref) class ExpressionBuiltinBytearray3( ExpressionBytearrayShapeExactMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_BYTEARRAY3" named_children = ("string", "encoding", "errors") builtin_spec = BuiltinParameterSpecs.builtin_bytearray_spec def __init__(self, string, encoding, errors, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"string": string, "encoding": encoding, "errors": errors}, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionConstantGenericAlias(CompileTimeConstantExpressionBase): kind = "EXPRESSION_CONSTANT_GENERIC_ALIAS" __slots__ = ("generic_alias",) def __init__(self, generic_alias, source_ref): CompileTimeConstantExpressionBase.__init__(self, source_ref=source_ref) self.generic_alias = generic_alias def finalize(self): del self.parent def getDetails(self): return {"generic_alias": self.generic_alias} def getCompileTimeConstant(self): return self.generic_alias def getStrValue(self): return makeConstantRefNode( constant=str(self.getCompileTimeConstant()), user_provided=True, source_ref=self.source_ref, ) def computeExpressionRaw(self, trace_collection): # Nothing much to do. return self, None, None class ExpressionConstantUnionType(CompileTimeConstantExpressionBase): kind = "EXPRESSION_CONSTANT_UNION_TYPE" __slots__ = ("union_type",) def __init__(self, union_type, source_ref): CompileTimeConstantExpressionBase.__init__(self, source_ref=source_ref) self.union_type = union_type def finalize(self): del self.parent def getDetails(self): return {"union_type": self.union_type} def getCompileTimeConstant(self): return self.union_type def getStrValue(self): return makeConstantRefNode( constant=str(self.getCompileTimeConstant()), user_provided=True, source_ref=self.source_ref, ) def computeExpressionRaw(self, trace_collection): # Nothing much to do. return self, None, None Nuitka-0.6.19.1/nuitka/nodes/BuiltinDecoratorNodes.py0000600000372100037210000000546314166627112027516 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in staticmethod/classmethod nodes These are good for optimizations, as they give a very well known result, changing only the way a class member is being called. Being able to avoid going through a C call to the built-ins resulting wrapper, will speed up things. """ from .ExpressionBases import ExpressionChildHavingBase from .NodeMakingHelpers import makeStatementOnlyNodesFromExpressions from .shapes.BuiltinTypeShapes import tshape_classmethod, tshape_staticmethod class ExpressionBuiltinStaticmethodClassmethodBase(ExpressionChildHavingBase): named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) def computeExpression(self, trace_collection): return self, None, None @staticmethod def isKnownToBeIterable(count): return False @staticmethod def isKnownToBeHashable(): return True # TODO: Side effect from child mixin should do these, there is one for multiple children. def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseException(exception_type) def mayHaveSideEffect(self): return self.subnode_value.mayHaveSideEffect() def extractSideEffects(self): return self.subnode_value.extractSideEffects() def computeExpressionDrop(self, statement, trace_collection): result = makeStatementOnlyNodesFromExpressions( self.subnode_value.extractSideEffects() ) return ( result, "new_statements", "Removed unused %r call." % self.getTypeShape().getTypeName(), ) class ExpressionBuiltinStaticmethod(ExpressionBuiltinStaticmethodClassmethodBase): kind = "EXPRESSION_BUILTIN_STATICMETHOD" @staticmethod def getTypeShape(): return tshape_staticmethod class ExpressionBuiltinClassmethod(ExpressionBuiltinStaticmethodClassmethodBase): kind = "EXPRESSION_BUILTIN_CLASSMETHOD" @staticmethod def getTypeShape(): return tshape_classmethod Nuitka-0.6.19.1/nuitka/nodes/NodeMakingHelpers.py0000600000372100037210000003530714166627112026613 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ These are just helpers to create nodes, often to replace existing nodes These are for use in optimizations and computations, and therefore cover mostly exceptions and constants. Often cyclic dependencies kicks in, which is why this module is mostly only imported locally. Note: It's intended to be reversed, this module will make the local imports instead, as these local imports look ugly everywhere else, making it more difficult to use. """ from nuitka import Options from nuitka.__past__ import GenericAlias, UnionType from nuitka.Builtins import builtin_names from nuitka.Constants import isConstant from nuitka.PythonVersions import python_version from nuitka.Tracing import my_print, unusual_logger def makeConstantReplacementNode(constant, node, user_provided): from .ConstantRefNodes import makeConstantRefNode return makeConstantRefNode( constant=constant, source_ref=node.source_ref, user_provided=user_provided ) def makeRaiseExceptionReplacementExpression( expression, exception_type, exception_value ): from .BuiltinRefNodes import ExpressionBuiltinExceptionRef from .ExceptionNodes import ExpressionRaiseException source_ref = expression.source_ref assert type(exception_type) is str if Options.shallWarnImplicitRaises(): unusual_logger.warning( '%s: Will always raise exception: "%s(%s)"' % ( source_ref.getAsString(), exception_type, exception_value, ) ) result = ExpressionRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name=exception_type, source_ref=source_ref ), exception_value=makeConstantReplacementNode( constant=exception_value, node=expression, user_provided=False ), source_ref=source_ref, ) return result def makeRaiseExceptionReplacementStatement(statement, exception_type, exception_value): from .BuiltinRefNodes import ExpressionBuiltinExceptionRef from .ExceptionNodes import StatementRaiseExceptionImplicit source_ref = statement.getSourceReference() assert type(exception_type) is str if Options.shallWarnImplicitRaises(): unusual_logger.warning( '%s: Will always raise exception: "%s(%s)"' % ( source_ref.getAsString(), exception_type, exception_value, ) ) result = StatementRaiseExceptionImplicit( exception_type=ExpressionBuiltinExceptionRef( exception_name=exception_type, source_ref=source_ref ), exception_value=makeConstantReplacementNode( constant=exception_value, node=statement, user_provided=False ), exception_cause=None, exception_trace=None, source_ref=source_ref, ) return result def makeRaiseExceptionReplacementExpressionFromInstance(expression, exception): assert isinstance(exception, Exception) args = exception.args if type(args) is tuple and len(args) == 1: value = args[0] else: assert type(args) is tuple value = args return makeRaiseExceptionReplacementExpression( expression=expression, exception_type=exception.__class__.__name__, exception_value=value, ) def makeRaiseExceptionStatementFromInstance(exception, source_ref): assert isinstance(exception, Exception) args = exception.args if type(args) is tuple and len(args) == 1: value = args[0] else: assert type(args) is tuple value = args from .BuiltinRefNodes import ExpressionBuiltinExceptionRef from .ConstantRefNodes import makeConstantRefNode from .ExceptionNodes import StatementRaiseExceptionImplicit return StatementRaiseExceptionImplicit( exception_type=ExpressionBuiltinExceptionRef( exception_name=exception.__class__.__name__, source_ref=source_ref ), exception_value=makeConstantRefNode( constant=value, source_ref=source_ref, user_provided=False ), exception_cause=None, exception_trace=None, source_ref=source_ref, ) def makeRaiseExceptionExpressionFromTemplate( exception_type, template, template_args, source_ref ): from .BuiltinRefNodes import ExpressionBuiltinExceptionRef from .ConstantRefNodes import makeConstantRefNode from .ContainerMakingNodes import makeExpressionMakeTupleOrConstant from .ExceptionNodes import ExpressionRaiseException from .OperatorNodes import makeBinaryOperationNode if type(template_args) is tuple: template_args = makeExpressionMakeTupleOrConstant( elements=template_args, user_provided=False, source_ref=source_ref ) return ExpressionRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name=exception_type, source_ref=source_ref ), exception_value=makeBinaryOperationNode( operator="Mod", left=makeConstantRefNode( constant=template, source_ref=source_ref, user_provided=True ), right=template_args, source_ref=source_ref, ), source_ref=source_ref, ) def makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template, operation, original_node, value_node ): shape = value_node.getTypeShape() type_name = shape.getTypeName() if type_name is not None: result = makeRaiseExceptionReplacementExpressionFromInstance( expression=original_node, exception=TypeError(template % type_name if "%" in template else template), ) result = wrapExpressionWithNodeSideEffects(new_node=result, old_node=value_node) else: from .AttributeNodes import makeExpressionAttributeLookup from .TypeNodes import ExpressionBuiltinType1 source_ref = original_node.getSourceReference() result = makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template=template, template_args=makeExpressionAttributeLookup( expression=ExpressionBuiltinType1( value=value_node.makeClone(), source_ref=source_ref ), attribute_name="__name__", source_ref=source_ref, ), source_ref=source_ref, ) type_name = shape.__name__ return ( result, "new_raise", "Raising for use of '%s' on %s '%s'." % (operation, "type" if type_name is not None else "shape", type_name), ) def makeCompileTimeConstantReplacementNode(value, node, user_provided): # This needs to match code in isCompileTimeConstantValue if isConstant(value): return makeConstantReplacementNode( constant=value, node=node, user_provided=user_provided ) elif type(value) is type: if value.__name__ in builtin_names: from .BuiltinRefNodes import makeExpressionBuiltinRef # Need not provide locals_scope, not used for these kinds of built-in refs that # refer to types. return makeExpressionBuiltinRef( builtin_name=value.__name__, locals_scope=None, source_ref=node.getSourceReference(), ) else: return node elif GenericAlias is not None and isinstance(value, GenericAlias): from .BuiltinTypeNodes import ExpressionConstantGenericAlias return ExpressionConstantGenericAlias( generic_alias=value, source_ref=node.getSourceReference(), ) elif UnionType is not None and isinstance(value, UnionType): from .BuiltinTypeNodes import ExpressionConstantUnionType return ExpressionConstantUnionType( union_type=value, source_ref=node.getSourceReference(), ) else: return node def getComputationResult(node, computation, description, user_provided): """With a computation function, execute it and return constant result or exception node. """ # Try and turn raised exceptions into static raises. pylint: disable=broad-except try: result = computation() except Exception as e: new_node = makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=e ) change_tags = "new_raise" change_desc = description + " Predicted to raise an exception." else: new_node = makeCompileTimeConstantReplacementNode( value=result, node=node, user_provided=user_provided ) if Options.is_debug: assert new_node is not node, (node, result) if new_node is not node: change_tags = "new_constant" change_desc = description + " Predicted constant result." else: change_tags = None change_desc = None return new_node, change_tags, change_desc def makeStatementExpressionOnlyReplacementNode(expression, node): from .StatementNodes import StatementExpressionOnly return StatementExpressionOnly( expression=expression, source_ref=node.getSourceReference() ) def mergeStatements(statements, allow_none=False): """Helper function that merges nested statement sequences.""" merged_statements = [] for statement in statements: if statement is None and allow_none: pass elif type(statement) in (tuple, list): merged_statements += mergeStatements(statement, allow_none) elif statement.isStatement() or statement.isStatementsFrame(): merged_statements.append(statement) elif statement.isStatementsSequence(): merged_statements.extend(mergeStatements(statement.subnode_statements)) else: assert False, statement return merged_statements def makeStatementsSequenceReplacementNode(statements, node): from .StatementNodes import StatementsSequence return StatementsSequence( statements=mergeStatements(statements), source_ref=node.getSourceReference() ) def convertNoneConstantToNone(node): if node is None: return None elif node.isExpressionConstantNoneRef(): return None else: return node def wrapExpressionWithSideEffects(side_effects, old_node, new_node): assert new_node.isExpression() from .SideEffectNodes import ExpressionSideEffects if side_effects: try: side_effects = sum( ( side_effect.extractSideEffects() for side_effect in side_effects if side_effect.mayHaveSideEffects() ), (), ) except AttributeError: my_print("Problem with side effects:", side_effects) raise if side_effects: new_node = ExpressionSideEffects( expression=new_node, side_effects=side_effects, source_ref=old_node.getSourceReference(), ) return new_node def wrapExpressionWithNodeSideEffects(new_node, old_node): return wrapExpressionWithSideEffects( side_effects=old_node.extractSideEffects(), old_node=old_node, new_node=new_node ) def wrapStatementWithSideEffects(new_node, old_node, allow_none=False): assert new_node is not None or allow_none side_effects = old_node.extractSideEffects() if side_effects: from .StatementNodes import StatementExpressionOnly side_effects = tuple( StatementExpressionOnly( expression=side_effect, source_ref=side_effect.getSourceReference() ) for side_effect in side_effects ) if new_node is not None: new_node = makeStatementsSequenceReplacementNode( statements=side_effects + (new_node,), node=old_node ) else: new_node = makeStatementsSequenceReplacementNode( statements=side_effects, node=old_node ) return new_node def makeStatementOnlyNodesFromExpressions(expressions): from .StatementNodes import StatementExpressionOnly, StatementsSequence statements = tuple( StatementExpressionOnly( expression=expression, source_ref=expression.getSourceReference() ) for expression in expressions ) if not statements: return None elif len(statements) == 1: return statements[0] else: return StatementsSequence( statements=statements, source_ref=statements[0].getSourceReference() ) def makeVariableRefNode(variable, source_ref): if variable.isTempVariable(): from .VariableRefNodes import ExpressionTempVariableRef return ExpressionTempVariableRef(variable=variable, source_ref=source_ref) else: from .VariableRefNodes import ExpressionVariableRef return ExpressionVariableRef(variable=variable, source_ref=source_ref) def makeExpressionBuiltinLocals(locals_scope, source_ref): if locals_scope.isModuleScope(): from .GlobalsLocalsNodes import ExpressionBuiltinGlobals return ExpressionBuiltinGlobals(source_ref=source_ref) else: from .GlobalsLocalsNodes import ( ExpressionBuiltinLocalsCopy, ExpressionBuiltinLocalsRef, ExpressionBuiltinLocalsUpdated, ) if locals_scope.isClassScope(): return ExpressionBuiltinLocalsRef( locals_scope=locals_scope, source_ref=source_ref ) elif python_version >= 0x300 or locals_scope.isUnoptimizedFunctionScope(): assert locals_scope.isFunctionScope(), locals_scope return ExpressionBuiltinLocalsUpdated( locals_scope=locals_scope, source_ref=source_ref ) else: return ExpressionBuiltinLocalsCopy( locals_scope=locals_scope, source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinSumNodes.py0000600000372100037210000000624514166627112026337 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node the calls to the 'sum' built-in. This is a rather challenging case for optimization, as it has C code behind it that could be in-lined sometimes for more static analysis. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) class ExpressionBuiltinSumMixin(object): # Mixins are required to slots __slots__ = () builtin_spec = BuiltinParameterSpecs.builtin_sum_spec def computeBuiltinSpec(self, trace_collection, given_values): assert self.builtin_spec is not None, self if not self.builtin_spec.isCompileTimeComputable(given_values): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Raise exception known step 0. return self, None, None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin_spec.simulateCall(given_values), description="Built-in call to '%s' computed." % (self.builtin_spec.getName()), ) class ExpressionBuiltinSum1(ExpressionBuiltinSumMixin, ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_SUM1" named_child = "sequence" def __init__(self, sequence, source_ref): assert sequence is not None ExpressionChildHavingBase.__init__(self, value=sequence, source_ref=source_ref) def computeExpression(self, trace_collection): sequence = self.subnode_sequence # TODO: Protect against large xrange constants return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(sequence,) ) class ExpressionBuiltinSum2(ExpressionBuiltinSumMixin, ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_SUM2" named_children = ("sequence", "start") def __init__(self, sequence, start, source_ref): assert sequence is not None assert start is not None ExpressionChildrenHavingBase.__init__( self, values={"sequence": sequence, "start": start}, source_ref=source_ref ) def computeExpression(self, trace_collection): sequence = self.subnode_sequence start = self.subnode_start # TODO: Protect against large xrange constants return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(sequence, start) ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinRefNodes.py0000600000372100037210000002046314166627112026305 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tree nodes for built-in references. There is 2 major types of built-in references. One is the values from built-ins, the other is built-in exceptions. They work differently and mean different things, but they have similar origin, that is, access to variables only ever read. """ from nuitka.Builtins import ( builtin_anon_names, builtin_exception_names, builtin_exception_values, builtin_names, builtin_type_names, ) from nuitka.Options import hasPythonFlagNoAsserts from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from .ConstantRefNodes import makeConstantRefNode from .ExceptionNodes import ( ExpressionBuiltinMakeException, ExpressionBuiltinMakeExceptionImportError, ) from .ExpressionBases import CompileTimeConstantExpressionBase from .shapes.BuiltinTypeShapes import tshape_exception_class class ExpressionBuiltinRefBase(CompileTimeConstantExpressionBase): # Base classes can be abstract, pylint: disable=abstract-method __slots__ = ("builtin_name",) def __init__(self, builtin_name, source_ref): CompileTimeConstantExpressionBase.__init__(self, source_ref=source_ref) self.builtin_name = builtin_name def finalize(self): del self.parent def getDetails(self): return {"builtin_name": self.builtin_name} def getBuiltinName(self): return self.builtin_name @staticmethod def isKnownToBeHashable(): return True def getStrValue(self): return makeConstantRefNode( constant=str(self.getCompileTimeConstant()), user_provided=True, source_ref=self.source_ref, ) def makeExpressionBuiltinTypeRef(builtin_name, source_ref): return makeConstantRefNode( constant=__builtins__[builtin_name], source_ref=source_ref ) quick_names = {"None": None, "True": True, "False": False, "Ellipsis": Ellipsis} def makeExpressionBuiltinRef(builtin_name, locals_scope, source_ref): assert builtin_name in builtin_names, builtin_name if builtin_name in quick_names: return makeConstantRefNode( constant=quick_names[builtin_name], source_ref=source_ref ) elif builtin_name == "__debug__": return makeConstantRefNode( constant=not hasPythonFlagNoAsserts(), source_ref=source_ref ) elif builtin_name in builtin_type_names: return makeExpressionBuiltinTypeRef( builtin_name=builtin_name, source_ref=source_ref ) elif builtin_name in ("dir", "eval", "exec", "execfile", "locals", "vars"): return ExpressionBuiltinWithContextRef( builtin_name=builtin_name, locals_scope=locals_scope, source_ref=source_ref ) else: return ExpressionBuiltinRef(builtin_name=builtin_name, source_ref=source_ref) class ExpressionBuiltinRef(ExpressionBuiltinRefBase): kind = "EXPRESSION_BUILTIN_REF" __slots__ = () # For overload locals_scope = None @staticmethod def isExpressionBuiltinRef(): return True def __init__(self, builtin_name, source_ref): ExpressionBuiltinRefBase.__init__( self, builtin_name=builtin_name, source_ref=source_ref ) def getCompileTimeConstant(self): return __builtins__[self.builtin_name] def computeExpressionRaw(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): from nuitka.optimizations.OptimizeBuiltinCalls import ( computeBuiltinCall, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) new_node, tags, message = computeBuiltinCall( builtin_name=self.builtin_name, call_node=call_node ) if self.builtin_name in ("dir", "eval", "exec", "execfile", "locals", "vars"): # Just inform the collection that all has escaped. trace_collection.onLocalsUsage(locals_scope=self.getLocalsScope()) return new_node, tags, message @staticmethod def isKnownToBeIterable(count): # TODO: Why yes, some may be, could be told here. return None class ExpressionBuiltinWithContextRef(ExpressionBuiltinRef): """Same as ExpressionBuiltinRef, but with a context it refers to.""" kind = "EXPRESSION_BUILTIN_WITH_CONTEXT_REF" __slots__ = ("locals_scope",) def __init__(self, builtin_name, locals_scope, source_ref): ExpressionBuiltinRef.__init__( self, builtin_name=builtin_name, source_ref=source_ref ) self.locals_scope = locals_scope def getDetails(self): return {"builtin_name": self.builtin_name, "locals_scope": self.locals_scope} def getLocalsScope(self): return self.locals_scope class ExpressionBuiltinAnonymousRef(ExpressionBuiltinRefBase): kind = "EXPRESSION_BUILTIN_ANONYMOUS_REF" __slots__ = () def __init__(self, builtin_name, source_ref): assert builtin_name in builtin_anon_names, (builtin_name, source_ref) ExpressionBuiltinRefBase.__init__( self, builtin_name=builtin_name, source_ref=source_ref ) def getCompileTimeConstant(self): return builtin_anon_names[self.builtin_name] def computeExpressionRaw(self, trace_collection): return self, None, None class ExpressionBuiltinExceptionRef(ExpressionBuiltinRefBase): kind = "EXPRESSION_BUILTIN_EXCEPTION_REF" __slots__ = () def __init__(self, exception_name, source_ref): assert exception_name in builtin_exception_names, exception_name ExpressionBuiltinRefBase.__init__( self, builtin_name=exception_name, source_ref=source_ref ) def getDetails(self): return {"exception_name": self.builtin_name} getExceptionName = ExpressionBuiltinRefBase.getBuiltinName @staticmethod def getTypeShape(): return tshape_exception_class @staticmethod def mayRaiseException(exception_type): return False def getCompileTimeConstant(self): return builtin_exception_values[self.builtin_name] def computeExpressionRaw(self, trace_collection): # Not much that can be done here. return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): exception_name = self.getExceptionName() def createBuiltinMakeException(args, name=None, path=None, source_ref=None): if exception_name == "ImportError" and python_version >= 0x300: return ExpressionBuiltinMakeExceptionImportError( exception_name=exception_name, args=args, name=name, path=path, source_ref=source_ref, ) else: # We expect to only get the star arguments for these. assert name is None assert path is None return ExpressionBuiltinMakeException( exception_name=exception_name, args=args, source_ref=source_ref ) new_node = BuiltinParameterSpecs.extractBuiltinArgs( node=call_node, builtin_class=createBuiltinMakeException, builtin_spec=BuiltinParameterSpecs.makeBuiltinExceptionParameterSpec( exception_name=exception_name ), ) assert new_node is not None return new_node, "new_expression", "Detected built-in exception making." Nuitka-0.6.19.1/nuitka/nodes/AttributeNodesGenerated.py0000600000372100037210000047417514166627112030041 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Specialized attribute nodes WARNING, this code is GENERATED. Modify the template AttributeNodeFixed.py.j2 instead! """ from nuitka.specs.BuiltinParameterSpecs import extractBuiltinArgs from .AttributeLookupNodes import ExpressionAttributeLookupFixedBase from .NodeBases import SideEffectsFromChildrenMixin attribute_classes = {} attribute_typed_classes = set() class ExpressionAttributeLookupFixedCapitalize(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'capitalize' of an object. Typically code like: source.capitalize """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_CAPITALIZE" attribute_name = "capitalize" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrCapitalize( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'capitalize' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="capitalize", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="capitalize" ) attribute_classes["capitalize"] = ExpressionAttributeLookupFixedCapitalize from nuitka.specs.BuiltinStrOperationSpecs import str_capitalize_spec class ExpressionAttributeLookupStrCapitalize( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedCapitalize ): """Attribute Capitalize lookup on a str. Typically code like: some_str.capitalize """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_CAPITALIZE" attribute_name = "capitalize" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationCapitalize(source_ref): from .StrNodes import ExpressionStrOperationCapitalize return ExpressionStrOperationCapitalize( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationCapitalize, builtin_spec=str_capitalize_spec, ) return result, "new_expression", "Call to 'capitalize' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrCapitalize) class ExpressionAttributeLookupFixedCasefold(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'casefold' of an object. Typically code like: source.casefold """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_CASEFOLD" attribute_name = "casefold" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrCasefold( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'casefold' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="casefold", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="casefold" ) attribute_classes["casefold"] = ExpressionAttributeLookupFixedCasefold class ExpressionAttributeLookupStrCasefold( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedCasefold ): """Attribute Casefold lookup on a str. Typically code like: some_str.casefold """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_CASEFOLD" attribute_name = "casefold" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationCasefold is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrCasefold) class ExpressionAttributeLookupFixedCenter(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'center' of an object. Typically code like: source.center """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_CENTER" attribute_name = "center" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrCenter( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'center' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="center", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="center" ) attribute_classes["center"] = ExpressionAttributeLookupFixedCenter class ExpressionAttributeLookupStrCenter( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedCenter ): """Attribute Center lookup on a str. Typically code like: some_str.center """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_CENTER" attribute_name = "center" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationCenter is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrCenter) class ExpressionAttributeLookupFixedClear(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'clear' of an object. Typically code like: source.clear """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_CLEAR" attribute_name = "clear" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictClear( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'clear' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="clear", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="clear" ) attribute_classes["clear"] = ExpressionAttributeLookupFixedClear from nuitka.specs.BuiltinDictOperationSpecs import dict_clear_spec class ExpressionAttributeLookupDictClear( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedClear ): """Attribute Clear lookup on a dict. Typically code like: some_dict.clear """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_CLEAR" attribute_name = "clear" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationClear(source_ref): from .DictionaryNodes import ExpressionDictOperationClear return ExpressionDictOperationClear( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationClear, builtin_spec=dict_clear_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'clear' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictClear) class ExpressionAttributeLookupFixedCopy(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'copy' of an object. Typically code like: source.copy """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_COPY" attribute_name = "copy" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictCopy( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'copy' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="copy", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="copy" ) attribute_classes["copy"] = ExpressionAttributeLookupFixedCopy from nuitka.specs.BuiltinDictOperationSpecs import dict_copy_spec class ExpressionAttributeLookupDictCopy( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedCopy ): """Attribute Copy lookup on a dict. Typically code like: some_dict.copy """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_COPY" attribute_name = "copy" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationCopy(source_ref): from .DictionaryNodes import ExpressionDictOperationCopy return ExpressionDictOperationCopy( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationCopy, builtin_spec=dict_copy_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'copy' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictCopy) class ExpressionAttributeLookupFixedCount(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'count' of an object. Typically code like: source.count """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_COUNT" attribute_name = "count" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrCount( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'count' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="count", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="count" ) attribute_classes["count"] = ExpressionAttributeLookupFixedCount class ExpressionAttributeLookupStrCount( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedCount ): """Attribute Count lookup on a str. Typically code like: some_str.count """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_COUNT" attribute_name = "count" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationCount is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrCount) class ExpressionAttributeLookupFixedDecode(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'decode' of an object. Typically code like: source.decode """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_DECODE" attribute_name = "decode" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrDecode( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'decode' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="decode", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="decode" ) attribute_classes["decode"] = ExpressionAttributeLookupFixedDecode from nuitka.specs.BuiltinStrOperationSpecs import str_decode_spec class ExpressionAttributeLookupStrDecode( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedDecode ): """Attribute Decode lookup on a str. Typically code like: some_str.decode """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_DECODE" attribute_name = "decode" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationDecode(encoding, errors, source_ref): if errors is not None: from .StrNodes import ExpressionStrOperationDecode3 return ExpressionStrOperationDecode3( str_arg=self.subnode_expression, encoding=encoding, errors=errors, source_ref=source_ref, ) elif encoding is not None: from .StrNodes import ExpressionStrOperationDecode2 return ExpressionStrOperationDecode2( str_arg=self.subnode_expression, encoding=encoding, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationDecode1 return ExpressionStrOperationDecode1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationDecode, builtin_spec=str_decode_spec, ) return result, "new_expression", "Call to 'decode' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrDecode) class ExpressionAttributeLookupFixedEncode(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'encode' of an object. Typically code like: source.encode """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ENCODE" attribute_name = "encode" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrEncode( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'encode' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="encode", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="encode" ) attribute_classes["encode"] = ExpressionAttributeLookupFixedEncode from nuitka.specs.BuiltinStrOperationSpecs import str_encode_spec class ExpressionAttributeLookupStrEncode( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedEncode ): """Attribute Encode lookup on a str. Typically code like: some_str.encode """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ENCODE" attribute_name = "encode" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationEncode(encoding, errors, source_ref): if errors is not None: from .StrNodes import ExpressionStrOperationEncode3 return ExpressionStrOperationEncode3( str_arg=self.subnode_expression, encoding=encoding, errors=errors, source_ref=source_ref, ) elif encoding is not None: from .StrNodes import ExpressionStrOperationEncode2 return ExpressionStrOperationEncode2( str_arg=self.subnode_expression, encoding=encoding, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationEncode1 return ExpressionStrOperationEncode1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationEncode, builtin_spec=str_encode_spec, ) return result, "new_expression", "Call to 'encode' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrEncode) class ExpressionAttributeLookupFixedEndswith(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'endswith' of an object. Typically code like: source.endswith """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ENDSWITH" attribute_name = "endswith" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrEndswith( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'endswith' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="endswith", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="endswith" ) attribute_classes["endswith"] = ExpressionAttributeLookupFixedEndswith from nuitka.specs.BuiltinStrOperationSpecs import str_endswith_spec class ExpressionAttributeLookupStrEndswith( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedEndswith ): """Attribute Endswith lookup on a str. Typically code like: some_str.endswith """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ENDSWITH" attribute_name = "endswith" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationEndswith(suffix, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationEndswith4 return ExpressionStrOperationEndswith4( str_arg=self.subnode_expression, suffix=suffix, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationEndswith3 return ExpressionStrOperationEndswith3( str_arg=self.subnode_expression, suffix=suffix, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationEndswith2 return ExpressionStrOperationEndswith2( str_arg=self.subnode_expression, suffix=suffix, source_ref=source_ref, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationEndswith, builtin_spec=str_endswith_spec, ) return result, "new_expression", "Call to 'endswith' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrEndswith) class ExpressionAttributeLookupFixedExpandtabs(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'expandtabs' of an object. Typically code like: source.expandtabs """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_EXPANDTABS" attribute_name = "expandtabs" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrExpandtabs( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'expandtabs' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="expandtabs", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="expandtabs" ) attribute_classes["expandtabs"] = ExpressionAttributeLookupFixedExpandtabs class ExpressionAttributeLookupStrExpandtabs( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedExpandtabs ): """Attribute Expandtabs lookup on a str. Typically code like: some_str.expandtabs """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_EXPANDTABS" attribute_name = "expandtabs" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationExpandtabs is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrExpandtabs) class ExpressionAttributeLookupFixedFind(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'find' of an object. Typically code like: source.find """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_FIND" attribute_name = "find" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrFind( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'find' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="find", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="find" ) attribute_classes["find"] = ExpressionAttributeLookupFixedFind from nuitka.specs.BuiltinStrOperationSpecs import str_find_spec class ExpressionAttributeLookupStrFind( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedFind ): """Attribute Find lookup on a str. Typically code like: some_str.find """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_FIND" attribute_name = "find" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationFind(sub, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationFind4 return ExpressionStrOperationFind4( str_arg=self.subnode_expression, sub=sub, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationFind3 return ExpressionStrOperationFind3( str_arg=self.subnode_expression, sub=sub, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationFind2 return ExpressionStrOperationFind2( str_arg=self.subnode_expression, sub=sub, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationFind, builtin_spec=str_find_spec, ) return result, "new_expression", "Call to 'find' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrFind) class ExpressionAttributeLookupFixedFormat(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'format' of an object. Typically code like: source.format """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_FORMAT" attribute_name = "format" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrFormat( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'format' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="format", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="format" ) attribute_classes["format"] = ExpressionAttributeLookupFixedFormat class ExpressionAttributeLookupStrFormat( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedFormat ): """Attribute Format lookup on a str. Typically code like: some_str.format """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_FORMAT" attribute_name = "format" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationFormat is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrFormat) class ExpressionAttributeLookupFixedFormatmap(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'format_map' of an object. Typically code like: source.format_map """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_FORMATMAP" attribute_name = "format_map" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrFormatmap( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'format_map' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="format_map", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="format_map" ) attribute_classes["format_map"] = ExpressionAttributeLookupFixedFormatmap class ExpressionAttributeLookupStrFormatmap( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedFormatmap ): """Attribute Formatmap lookup on a str. Typically code like: some_str.format_map """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_FORMATMAP" attribute_name = "format_map" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationFormatmap is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrFormatmap) class ExpressionAttributeLookupFixedFromkeys(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'fromkeys' of an object. Typically code like: source.fromkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_FROMKEYS" attribute_name = "fromkeys" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictFromkeys( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'fromkeys' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="fromkeys", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="fromkeys" ) attribute_classes["fromkeys"] = ExpressionAttributeLookupFixedFromkeys class ExpressionAttributeLookupDictFromkeys( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedFromkeys ): """Attribute Fromkeys lookup on a dict. Typically code like: some_dict.fromkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_FROMKEYS" attribute_name = "fromkeys" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as dict operation ExpressionDictOperationFromkeys is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupDictFromkeys) class ExpressionAttributeLookupFixedGet(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'get' of an object. Typically code like: source.get """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_GET" attribute_name = "get" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictGet( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'get' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="get", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="get" ) attribute_classes["get"] = ExpressionAttributeLookupFixedGet from nuitka.specs.BuiltinDictOperationSpecs import dict_get_spec class ExpressionAttributeLookupDictGet( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedGet ): """Attribute Get lookup on a dict. Typically code like: some_dict.get """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_GET" attribute_name = "get" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationGet(key, default, source_ref): if default is not None: from .DictionaryNodes import ExpressionDictOperationGet3 return ExpressionDictOperationGet3( dict_arg=self.subnode_expression, key=key, default=default, source_ref=source_ref, ) else: from .DictionaryNodes import ExpressionDictOperationGet2 return ExpressionDictOperationGet2( dict_arg=self.subnode_expression, key=key, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationGet, builtin_spec=dict_get_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'get' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictGet) class ExpressionAttributeLookupFixedHaskey(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'has_key' of an object. Typically code like: source.has_key """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_HASKEY" attribute_name = "has_key" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictHaskey( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'has_key' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="has_key", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="has_key" ) attribute_classes["has_key"] = ExpressionAttributeLookupFixedHaskey from nuitka.specs.BuiltinDictOperationSpecs import dict_has_key_spec class ExpressionAttributeLookupDictHaskey( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedHaskey ): """Attribute Haskey lookup on a dict. Typically code like: some_dict.has_key """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_HASKEY" attribute_name = "has_key" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationHaskey(key, source_ref): from .DictionaryNodes import ExpressionDictOperationHaskey return ExpressionDictOperationHaskey( dict_arg=self.subnode_expression, key=key, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationHaskey, builtin_spec=dict_has_key_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'has_key' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictHaskey) class ExpressionAttributeLookupFixedIndex(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'index' of an object. Typically code like: source.index """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_INDEX" attribute_name = "index" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIndex( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'index' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="index", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="index" ) attribute_classes["index"] = ExpressionAttributeLookupFixedIndex from nuitka.specs.BuiltinStrOperationSpecs import str_index_spec class ExpressionAttributeLookupStrIndex( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIndex ): """Attribute Index lookup on a str. Typically code like: some_str.index """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_INDEX" attribute_name = "index" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIndex(sub, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationIndex4 return ExpressionStrOperationIndex4( str_arg=self.subnode_expression, sub=sub, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationIndex3 return ExpressionStrOperationIndex3( str_arg=self.subnode_expression, sub=sub, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationIndex2 return ExpressionStrOperationIndex2( str_arg=self.subnode_expression, sub=sub, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIndex, builtin_spec=str_index_spec, ) return result, "new_expression", "Call to 'index' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIndex) class ExpressionAttributeLookupFixedIsalnum(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isalnum' of an object. Typically code like: source.isalnum """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISALNUM" attribute_name = "isalnum" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsalnum( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isalnum' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isalnum", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isalnum" ) attribute_classes["isalnum"] = ExpressionAttributeLookupFixedIsalnum from nuitka.specs.BuiltinStrOperationSpecs import str_isalnum_spec class ExpressionAttributeLookupStrIsalnum( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsalnum ): """Attribute Isalnum lookup on a str. Typically code like: some_str.isalnum """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISALNUM" attribute_name = "isalnum" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIsalnum(source_ref): from .StrNodes import ExpressionStrOperationIsalnum return ExpressionStrOperationIsalnum( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIsalnum, builtin_spec=str_isalnum_spec, ) return result, "new_expression", "Call to 'isalnum' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIsalnum) class ExpressionAttributeLookupFixedIsalpha(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isalpha' of an object. Typically code like: source.isalpha """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISALPHA" attribute_name = "isalpha" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsalpha( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isalpha' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isalpha", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isalpha" ) attribute_classes["isalpha"] = ExpressionAttributeLookupFixedIsalpha from nuitka.specs.BuiltinStrOperationSpecs import str_isalpha_spec class ExpressionAttributeLookupStrIsalpha( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsalpha ): """Attribute Isalpha lookup on a str. Typically code like: some_str.isalpha """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISALPHA" attribute_name = "isalpha" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIsalpha(source_ref): from .StrNodes import ExpressionStrOperationIsalpha return ExpressionStrOperationIsalpha( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIsalpha, builtin_spec=str_isalpha_spec, ) return result, "new_expression", "Call to 'isalpha' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIsalpha) class ExpressionAttributeLookupFixedIsascii(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isascii' of an object. Typically code like: source.isascii """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISASCII" attribute_name = "isascii" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsascii( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isascii' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isascii", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isascii" ) attribute_classes["isascii"] = ExpressionAttributeLookupFixedIsascii class ExpressionAttributeLookupStrIsascii( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsascii ): """Attribute Isascii lookup on a str. Typically code like: some_str.isascii """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISASCII" attribute_name = "isascii" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationIsascii is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrIsascii) class ExpressionAttributeLookupFixedIsdecimal(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isdecimal' of an object. Typically code like: source.isdecimal """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISDECIMAL" attribute_name = "isdecimal" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsdecimal( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isdecimal' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isdecimal", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isdecimal" ) attribute_classes["isdecimal"] = ExpressionAttributeLookupFixedIsdecimal class ExpressionAttributeLookupStrIsdecimal( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsdecimal ): """Attribute Isdecimal lookup on a str. Typically code like: some_str.isdecimal """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISDECIMAL" attribute_name = "isdecimal" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationIsdecimal is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrIsdecimal) class ExpressionAttributeLookupFixedIsdigit(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isdigit' of an object. Typically code like: source.isdigit """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISDIGIT" attribute_name = "isdigit" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsdigit( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isdigit' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isdigit", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isdigit" ) attribute_classes["isdigit"] = ExpressionAttributeLookupFixedIsdigit from nuitka.specs.BuiltinStrOperationSpecs import str_isdigit_spec class ExpressionAttributeLookupStrIsdigit( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsdigit ): """Attribute Isdigit lookup on a str. Typically code like: some_str.isdigit """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISDIGIT" attribute_name = "isdigit" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIsdigit(source_ref): from .StrNodes import ExpressionStrOperationIsdigit return ExpressionStrOperationIsdigit( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIsdigit, builtin_spec=str_isdigit_spec, ) return result, "new_expression", "Call to 'isdigit' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIsdigit) class ExpressionAttributeLookupFixedIsidentifier(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isidentifier' of an object. Typically code like: source.isidentifier """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISIDENTIFIER" attribute_name = "isidentifier" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsidentifier( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isidentifier' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isidentifier", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isidentifier" ) attribute_classes["isidentifier"] = ExpressionAttributeLookupFixedIsidentifier class ExpressionAttributeLookupStrIsidentifier( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsidentifier ): """Attribute Isidentifier lookup on a str. Typically code like: some_str.isidentifier """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISIDENTIFIER" attribute_name = "isidentifier" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationIsidentifier is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrIsidentifier) class ExpressionAttributeLookupFixedIslower(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'islower' of an object. Typically code like: source.islower """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISLOWER" attribute_name = "islower" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIslower( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'islower' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="islower", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="islower" ) attribute_classes["islower"] = ExpressionAttributeLookupFixedIslower from nuitka.specs.BuiltinStrOperationSpecs import str_islower_spec class ExpressionAttributeLookupStrIslower( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIslower ): """Attribute Islower lookup on a str. Typically code like: some_str.islower """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISLOWER" attribute_name = "islower" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIslower(source_ref): from .StrNodes import ExpressionStrOperationIslower return ExpressionStrOperationIslower( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIslower, builtin_spec=str_islower_spec, ) return result, "new_expression", "Call to 'islower' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIslower) class ExpressionAttributeLookupFixedIsnumeric(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isnumeric' of an object. Typically code like: source.isnumeric """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISNUMERIC" attribute_name = "isnumeric" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsnumeric( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isnumeric' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isnumeric", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isnumeric" ) attribute_classes["isnumeric"] = ExpressionAttributeLookupFixedIsnumeric class ExpressionAttributeLookupStrIsnumeric( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsnumeric ): """Attribute Isnumeric lookup on a str. Typically code like: some_str.isnumeric """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISNUMERIC" attribute_name = "isnumeric" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationIsnumeric is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrIsnumeric) class ExpressionAttributeLookupFixedIsprintable(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isprintable' of an object. Typically code like: source.isprintable """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISPRINTABLE" attribute_name = "isprintable" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsprintable( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isprintable' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isprintable", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isprintable" ) attribute_classes["isprintable"] = ExpressionAttributeLookupFixedIsprintable class ExpressionAttributeLookupStrIsprintable( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsprintable ): """Attribute Isprintable lookup on a str. Typically code like: some_str.isprintable """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISPRINTABLE" attribute_name = "isprintable" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationIsprintable is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrIsprintable) class ExpressionAttributeLookupFixedIsspace(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isspace' of an object. Typically code like: source.isspace """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISSPACE" attribute_name = "isspace" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsspace( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isspace' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isspace", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isspace" ) attribute_classes["isspace"] = ExpressionAttributeLookupFixedIsspace from nuitka.specs.BuiltinStrOperationSpecs import str_isspace_spec class ExpressionAttributeLookupStrIsspace( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsspace ): """Attribute Isspace lookup on a str. Typically code like: some_str.isspace """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISSPACE" attribute_name = "isspace" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIsspace(source_ref): from .StrNodes import ExpressionStrOperationIsspace return ExpressionStrOperationIsspace( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIsspace, builtin_spec=str_isspace_spec, ) return result, "new_expression", "Call to 'isspace' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIsspace) class ExpressionAttributeLookupFixedIstitle(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'istitle' of an object. Typically code like: source.istitle """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISTITLE" attribute_name = "istitle" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIstitle( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'istitle' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="istitle", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="istitle" ) attribute_classes["istitle"] = ExpressionAttributeLookupFixedIstitle from nuitka.specs.BuiltinStrOperationSpecs import str_istitle_spec class ExpressionAttributeLookupStrIstitle( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIstitle ): """Attribute Istitle lookup on a str. Typically code like: some_str.istitle """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISTITLE" attribute_name = "istitle" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIstitle(source_ref): from .StrNodes import ExpressionStrOperationIstitle return ExpressionStrOperationIstitle( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIstitle, builtin_spec=str_istitle_spec, ) return result, "new_expression", "Call to 'istitle' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIstitle) class ExpressionAttributeLookupFixedIsupper(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'isupper' of an object. Typically code like: source.isupper """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ISUPPER" attribute_name = "isupper" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrIsupper( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'isupper' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="isupper", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="isupper" ) attribute_classes["isupper"] = ExpressionAttributeLookupFixedIsupper from nuitka.specs.BuiltinStrOperationSpecs import str_isupper_spec class ExpressionAttributeLookupStrIsupper( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIsupper ): """Attribute Isupper lookup on a str. Typically code like: some_str.isupper """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ISUPPER" attribute_name = "isupper" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationIsupper(source_ref): from .StrNodes import ExpressionStrOperationIsupper return ExpressionStrOperationIsupper( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationIsupper, builtin_spec=str_isupper_spec, ) return result, "new_expression", "Call to 'isupper' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrIsupper) class ExpressionAttributeLookupFixedItems(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'items' of an object. Typically code like: source.items """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ITEMS" attribute_name = "items" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictItems( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'items' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="items", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="items" ) attribute_classes["items"] = ExpressionAttributeLookupFixedItems from nuitka.specs.BuiltinDictOperationSpecs import dict_items_spec class ExpressionAttributeLookupDictItems( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedItems ): """Attribute Items lookup on a dict. Typically code like: some_dict.items """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_ITEMS" attribute_name = "items" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationItems(source_ref): if str is bytes: from .DictionaryNodes import ExpressionDictOperationItems return ExpressionDictOperationItems( dict_arg=self.subnode_expression, source_ref=source_ref ) else: from .DictionaryNodes import ExpressionDictOperationIteritems return ExpressionDictOperationIteritems( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationItems, builtin_spec=dict_items_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'items' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictItems) class ExpressionAttributeLookupFixedIteritems(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'iteritems' of an object. Typically code like: source.iteritems """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ITERITEMS" attribute_name = "iteritems" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictIteritems( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'iteritems' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="iteritems", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="iteritems" ) attribute_classes["iteritems"] = ExpressionAttributeLookupFixedIteritems from nuitka.specs.BuiltinDictOperationSpecs import dict_iteritems_spec class ExpressionAttributeLookupDictIteritems( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIteritems ): """Attribute Iteritems lookup on a dict. Typically code like: some_dict.iteritems """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_ITERITEMS" attribute_name = "iteritems" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationIteritems(source_ref): from .DictionaryNodes import ExpressionDictOperationIteritems return ExpressionDictOperationIteritems( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationIteritems, builtin_spec=dict_iteritems_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'iteritems' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictIteritems) class ExpressionAttributeLookupFixedIterkeys(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'iterkeys' of an object. Typically code like: source.iterkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ITERKEYS" attribute_name = "iterkeys" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictIterkeys( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'iterkeys' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="iterkeys", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="iterkeys" ) attribute_classes["iterkeys"] = ExpressionAttributeLookupFixedIterkeys from nuitka.specs.BuiltinDictOperationSpecs import dict_iterkeys_spec class ExpressionAttributeLookupDictIterkeys( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedIterkeys ): """Attribute Iterkeys lookup on a dict. Typically code like: some_dict.iterkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_ITERKEYS" attribute_name = "iterkeys" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationIterkeys(source_ref): from .DictionaryNodes import ExpressionDictOperationIterkeys return ExpressionDictOperationIterkeys( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationIterkeys, builtin_spec=dict_iterkeys_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'iterkeys' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictIterkeys) class ExpressionAttributeLookupFixedItervalues(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'itervalues' of an object. Typically code like: source.itervalues """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ITERVALUES" attribute_name = "itervalues" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictItervalues( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'itervalues' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="itervalues", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="itervalues" ) attribute_classes["itervalues"] = ExpressionAttributeLookupFixedItervalues from nuitka.specs.BuiltinDictOperationSpecs import dict_itervalues_spec class ExpressionAttributeLookupDictItervalues( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedItervalues ): """Attribute Itervalues lookup on a dict. Typically code like: some_dict.itervalues """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_ITERVALUES" attribute_name = "itervalues" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationItervalues(source_ref): from .DictionaryNodes import ExpressionDictOperationItervalues return ExpressionDictOperationItervalues( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationItervalues, builtin_spec=dict_itervalues_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'itervalues' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictItervalues) class ExpressionAttributeLookupFixedJoin(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'join' of an object. Typically code like: source.join """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_JOIN" attribute_name = "join" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrJoin( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'join' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="join", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="join" ) attribute_classes["join"] = ExpressionAttributeLookupFixedJoin from nuitka.specs.BuiltinStrOperationSpecs import str_join_spec class ExpressionAttributeLookupStrJoin( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedJoin ): """Attribute Join lookup on a str. Typically code like: some_str.join """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_JOIN" attribute_name = "join" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationJoin(iterable, source_ref): from .StrNodes import ExpressionStrOperationJoin return ExpressionStrOperationJoin( str_arg=self.subnode_expression, iterable=iterable, source_ref=source_ref, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationJoin, builtin_spec=str_join_spec, ) return result, "new_expression", "Call to 'join' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrJoin) class ExpressionAttributeLookupFixedKeys(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'keys' of an object. Typically code like: source.keys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_KEYS" attribute_name = "keys" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictKeys( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'keys' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="keys", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="keys" ) attribute_classes["keys"] = ExpressionAttributeLookupFixedKeys from nuitka.specs.BuiltinDictOperationSpecs import dict_keys_spec class ExpressionAttributeLookupDictKeys( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedKeys ): """Attribute Keys lookup on a dict. Typically code like: some_dict.keys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_KEYS" attribute_name = "keys" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationKeys(source_ref): if str is bytes: from .DictionaryNodes import ExpressionDictOperationKeys return ExpressionDictOperationKeys( dict_arg=self.subnode_expression, source_ref=source_ref ) else: from .DictionaryNodes import ExpressionDictOperationIterkeys return ExpressionDictOperationIterkeys( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationKeys, builtin_spec=dict_keys_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'keys' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictKeys) class ExpressionAttributeLookupFixedLjust(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'ljust' of an object. Typically code like: source.ljust """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_LJUST" attribute_name = "ljust" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrLjust( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'ljust' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="ljust", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="ljust" ) attribute_classes["ljust"] = ExpressionAttributeLookupFixedLjust class ExpressionAttributeLookupStrLjust( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedLjust ): """Attribute Ljust lookup on a str. Typically code like: some_str.ljust """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_LJUST" attribute_name = "ljust" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationLjust is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrLjust) class ExpressionAttributeLookupFixedLower(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'lower' of an object. Typically code like: source.lower """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_LOWER" attribute_name = "lower" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrLower( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'lower' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="lower", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="lower" ) attribute_classes["lower"] = ExpressionAttributeLookupFixedLower from nuitka.specs.BuiltinStrOperationSpecs import str_lower_spec class ExpressionAttributeLookupStrLower( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedLower ): """Attribute Lower lookup on a str. Typically code like: some_str.lower """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_LOWER" attribute_name = "lower" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationLower(source_ref): from .StrNodes import ExpressionStrOperationLower return ExpressionStrOperationLower( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationLower, builtin_spec=str_lower_spec, ) return result, "new_expression", "Call to 'lower' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrLower) class ExpressionAttributeLookupFixedLstrip(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'lstrip' of an object. Typically code like: source.lstrip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_LSTRIP" attribute_name = "lstrip" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrLstrip( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'lstrip' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="lstrip", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="lstrip" ) attribute_classes["lstrip"] = ExpressionAttributeLookupFixedLstrip from nuitka.specs.BuiltinStrOperationSpecs import str_lstrip_spec class ExpressionAttributeLookupStrLstrip( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedLstrip ): """Attribute Lstrip lookup on a str. Typically code like: some_str.lstrip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_LSTRIP" attribute_name = "lstrip" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationLstrip(chars, source_ref): if chars is not None: from .StrNodes import ExpressionStrOperationLstrip2 return ExpressionStrOperationLstrip2( str_arg=self.subnode_expression, chars=chars, source_ref=source_ref ) else: from .StrNodes import ExpressionStrOperationLstrip1 return ExpressionStrOperationLstrip1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationLstrip, builtin_spec=str_lstrip_spec, ) return result, "new_expression", "Call to 'lstrip' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrLstrip) class ExpressionAttributeLookupFixedMaketrans(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'maketrans' of an object. Typically code like: source.maketrans """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_MAKETRANS" attribute_name = "maketrans" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is not bytes and subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrMaketrans( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'maketrans' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="maketrans", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="maketrans" ) attribute_classes["maketrans"] = ExpressionAttributeLookupFixedMaketrans class ExpressionAttributeLookupStrMaketrans( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedMaketrans ): """Attribute Maketrans lookup on a str. Typically code like: some_str.maketrans """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_MAKETRANS" attribute_name = "maketrans" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationMaketrans is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrMaketrans) class ExpressionAttributeLookupFixedPartition(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'partition' of an object. Typically code like: source.partition """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_PARTITION" attribute_name = "partition" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrPartition( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'partition' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="partition", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="partition" ) attribute_classes["partition"] = ExpressionAttributeLookupFixedPartition from nuitka.specs.BuiltinStrOperationSpecs import str_partition_spec class ExpressionAttributeLookupStrPartition( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedPartition ): """Attribute Partition lookup on a str. Typically code like: some_str.partition """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_PARTITION" attribute_name = "partition" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationPartition(sep, source_ref): from .StrNodes import ExpressionStrOperationPartition return ExpressionStrOperationPartition( str_arg=self.subnode_expression, sep=sep, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationPartition, builtin_spec=str_partition_spec, ) return result, "new_expression", "Call to 'partition' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrPartition) class ExpressionAttributeLookupFixedPop(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'pop' of an object. Typically code like: source.pop """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_POP" attribute_name = "pop" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictPop( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'pop' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="pop", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="pop" ) attribute_classes["pop"] = ExpressionAttributeLookupFixedPop from nuitka.specs.BuiltinDictOperationSpecs import dict_pop_spec class ExpressionAttributeLookupDictPop( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedPop ): """Attribute Pop lookup on a dict. Typically code like: some_dict.pop """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_POP" attribute_name = "pop" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationPop(key, default, source_ref): if default is not None: from .DictionaryNodes import ExpressionDictOperationPop3 return ExpressionDictOperationPop3( dict_arg=self.subnode_expression, key=key, default=default, source_ref=source_ref, ) else: from .DictionaryNodes import ExpressionDictOperationPop2 return ExpressionDictOperationPop2( dict_arg=self.subnode_expression, key=key, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationPop, builtin_spec=dict_pop_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'pop' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictPop) class ExpressionAttributeLookupFixedPopitem(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'popitem' of an object. Typically code like: source.popitem """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_POPITEM" attribute_name = "popitem" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictPopitem( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'popitem' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="popitem", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="popitem" ) attribute_classes["popitem"] = ExpressionAttributeLookupFixedPopitem class ExpressionAttributeLookupDictPopitem( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedPopitem ): """Attribute Popitem lookup on a dict. Typically code like: some_dict.popitem """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_POPITEM" attribute_name = "popitem" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as dict operation ExpressionDictOperationPopitem is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupDictPopitem) class ExpressionAttributeLookupFixedReplace(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'replace' of an object. Typically code like: source.replace """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_REPLACE" attribute_name = "replace" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrReplace( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'replace' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="replace", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="replace" ) attribute_classes["replace"] = ExpressionAttributeLookupFixedReplace from nuitka.specs.BuiltinStrOperationSpecs import str_replace_spec class ExpressionAttributeLookupStrReplace( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedReplace ): """Attribute Replace lookup on a str. Typically code like: some_str.replace """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_REPLACE" attribute_name = "replace" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationReplace(old, new, count, source_ref): if count is not None: from .StrNodes import ExpressionStrOperationReplace4 return ExpressionStrOperationReplace4( str_arg=self.subnode_expression, old=old, new=new, count=count, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationReplace3 return ExpressionStrOperationReplace3( str_arg=self.subnode_expression, old=old, new=new, source_ref=source_ref, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationReplace, builtin_spec=str_replace_spec, ) return result, "new_expression", "Call to 'replace' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrReplace) class ExpressionAttributeLookupFixedRfind(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rfind' of an object. Typically code like: source.rfind """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RFIND" attribute_name = "rfind" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRfind( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rfind' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rfind", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rfind" ) attribute_classes["rfind"] = ExpressionAttributeLookupFixedRfind from nuitka.specs.BuiltinStrOperationSpecs import str_rfind_spec class ExpressionAttributeLookupStrRfind( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRfind ): """Attribute Rfind lookup on a str. Typically code like: some_str.rfind """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RFIND" attribute_name = "rfind" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationRfind(sub, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationRfind4 return ExpressionStrOperationRfind4( str_arg=self.subnode_expression, sub=sub, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationRfind3 return ExpressionStrOperationRfind3( str_arg=self.subnode_expression, sub=sub, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationRfind2 return ExpressionStrOperationRfind2( str_arg=self.subnode_expression, sub=sub, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationRfind, builtin_spec=str_rfind_spec, ) return result, "new_expression", "Call to 'rfind' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrRfind) class ExpressionAttributeLookupFixedRindex(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rindex' of an object. Typically code like: source.rindex """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RINDEX" attribute_name = "rindex" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRindex( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rindex' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rindex", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rindex" ) attribute_classes["rindex"] = ExpressionAttributeLookupFixedRindex from nuitka.specs.BuiltinStrOperationSpecs import str_rindex_spec class ExpressionAttributeLookupStrRindex( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRindex ): """Attribute Rindex lookup on a str. Typically code like: some_str.rindex """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RINDEX" attribute_name = "rindex" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationRindex(sub, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationRindex4 return ExpressionStrOperationRindex4( str_arg=self.subnode_expression, sub=sub, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationRindex3 return ExpressionStrOperationRindex3( str_arg=self.subnode_expression, sub=sub, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationRindex2 return ExpressionStrOperationRindex2( str_arg=self.subnode_expression, sub=sub, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationRindex, builtin_spec=str_rindex_spec, ) return result, "new_expression", "Call to 'rindex' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrRindex) class ExpressionAttributeLookupFixedRjust(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rjust' of an object. Typically code like: source.rjust """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RJUST" attribute_name = "rjust" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRjust( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rjust' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rjust", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rjust" ) attribute_classes["rjust"] = ExpressionAttributeLookupFixedRjust class ExpressionAttributeLookupStrRjust( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRjust ): """Attribute Rjust lookup on a str. Typically code like: some_str.rjust """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RJUST" attribute_name = "rjust" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationRjust is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrRjust) class ExpressionAttributeLookupFixedRpartition(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rpartition' of an object. Typically code like: source.rpartition """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RPARTITION" attribute_name = "rpartition" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRpartition( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rpartition' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rpartition", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rpartition" ) attribute_classes["rpartition"] = ExpressionAttributeLookupFixedRpartition from nuitka.specs.BuiltinStrOperationSpecs import str_rpartition_spec class ExpressionAttributeLookupStrRpartition( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRpartition ): """Attribute Rpartition lookup on a str. Typically code like: some_str.rpartition """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RPARTITION" attribute_name = "rpartition" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationRpartition(sep, source_ref): from .StrNodes import ExpressionStrOperationRpartition return ExpressionStrOperationRpartition( str_arg=self.subnode_expression, sep=sep, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationRpartition, builtin_spec=str_rpartition_spec, ) return result, "new_expression", "Call to 'rpartition' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrRpartition) class ExpressionAttributeLookupFixedRsplit(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rsplit' of an object. Typically code like: source.rsplit """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RSPLIT" attribute_name = "rsplit" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRsplit( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rsplit' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rsplit", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rsplit" ) attribute_classes["rsplit"] = ExpressionAttributeLookupFixedRsplit from nuitka.specs.BuiltinStrOperationSpecs import str_rsplit_spec class ExpressionAttributeLookupStrRsplit( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRsplit ): """Attribute Rsplit lookup on a str. Typically code like: some_str.rsplit """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RSPLIT" attribute_name = "rsplit" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationRsplit(sep, maxsplit, source_ref): if maxsplit is not None: from .StrNodes import ExpressionStrOperationRsplit3 return ExpressionStrOperationRsplit3( str_arg=self.subnode_expression, sep=sep, maxsplit=maxsplit, source_ref=source_ref, ) elif sep is not None: from .StrNodes import ExpressionStrOperationRsplit2 return ExpressionStrOperationRsplit2( str_arg=self.subnode_expression, sep=sep, source_ref=source_ref ) else: from .StrNodes import ExpressionStrOperationRsplit1 return ExpressionStrOperationRsplit1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationRsplit, builtin_spec=str_rsplit_spec, ) return result, "new_expression", "Call to 'rsplit' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrRsplit) class ExpressionAttributeLookupFixedRstrip(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'rstrip' of an object. Typically code like: source.rstrip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_RSTRIP" attribute_name = "rstrip" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrRstrip( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'rstrip' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="rstrip", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="rstrip" ) attribute_classes["rstrip"] = ExpressionAttributeLookupFixedRstrip from nuitka.specs.BuiltinStrOperationSpecs import str_rstrip_spec class ExpressionAttributeLookupStrRstrip( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedRstrip ): """Attribute Rstrip lookup on a str. Typically code like: some_str.rstrip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_RSTRIP" attribute_name = "rstrip" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationRstrip(chars, source_ref): if chars is not None: from .StrNodes import ExpressionStrOperationRstrip2 return ExpressionStrOperationRstrip2( str_arg=self.subnode_expression, chars=chars, source_ref=source_ref ) else: from .StrNodes import ExpressionStrOperationRstrip1 return ExpressionStrOperationRstrip1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationRstrip, builtin_spec=str_rstrip_spec, ) return result, "new_expression", "Call to 'rstrip' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrRstrip) class ExpressionAttributeLookupFixedSetdefault(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'setdefault' of an object. Typically code like: source.setdefault """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_SETDEFAULT" attribute_name = "setdefault" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictSetdefault( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'setdefault' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="setdefault", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="setdefault" ) attribute_classes["setdefault"] = ExpressionAttributeLookupFixedSetdefault from nuitka.specs.BuiltinDictOperationSpecs import dict_setdefault_spec class ExpressionAttributeLookupDictSetdefault( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedSetdefault ): """Attribute Setdefault lookup on a dict. Typically code like: some_dict.setdefault """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_SETDEFAULT" attribute_name = "setdefault" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationSetdefault(key, default, source_ref): if default is not None: from .DictionaryNodes import ExpressionDictOperationSetdefault3 return ExpressionDictOperationSetdefault3( dict_arg=self.subnode_expression, key=key, default=default, source_ref=source_ref, ) else: from .DictionaryNodes import ExpressionDictOperationSetdefault2 return ExpressionDictOperationSetdefault2( dict_arg=self.subnode_expression, key=key, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationSetdefault, builtin_spec=dict_setdefault_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'setdefault' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictSetdefault) class ExpressionAttributeLookupFixedSplit(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'split' of an object. Typically code like: source.split """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_SPLIT" attribute_name = "split" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrSplit( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'split' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="split", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="split" ) attribute_classes["split"] = ExpressionAttributeLookupFixedSplit from nuitka.specs.BuiltinStrOperationSpecs import str_split_spec class ExpressionAttributeLookupStrSplit( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedSplit ): """Attribute Split lookup on a str. Typically code like: some_str.split """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_SPLIT" attribute_name = "split" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationSplit(sep, maxsplit, source_ref): if maxsplit is not None: from .StrNodes import ExpressionStrOperationSplit3 return ExpressionStrOperationSplit3( str_arg=self.subnode_expression, sep=sep, maxsplit=maxsplit, source_ref=source_ref, ) elif sep is not None: from .StrNodes import ExpressionStrOperationSplit2 return ExpressionStrOperationSplit2( str_arg=self.subnode_expression, sep=sep, source_ref=source_ref ) else: from .StrNodes import ExpressionStrOperationSplit1 return ExpressionStrOperationSplit1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationSplit, builtin_spec=str_split_spec, ) return result, "new_expression", "Call to 'split' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrSplit) class ExpressionAttributeLookupFixedSplitlines(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'splitlines' of an object. Typically code like: source.splitlines """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_SPLITLINES" attribute_name = "splitlines" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrSplitlines( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'splitlines' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="splitlines", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="splitlines" ) attribute_classes["splitlines"] = ExpressionAttributeLookupFixedSplitlines class ExpressionAttributeLookupStrSplitlines( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedSplitlines ): """Attribute Splitlines lookup on a str. Typically code like: some_str.splitlines """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_SPLITLINES" attribute_name = "splitlines" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationSplitlines is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrSplitlines) class ExpressionAttributeLookupFixedStartswith(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'startswith' of an object. Typically code like: source.startswith """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_STARTSWITH" attribute_name = "startswith" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrStartswith( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'startswith' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="startswith", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="startswith" ) attribute_classes["startswith"] = ExpressionAttributeLookupFixedStartswith from nuitka.specs.BuiltinStrOperationSpecs import str_startswith_spec class ExpressionAttributeLookupStrStartswith( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedStartswith ): """Attribute Startswith lookup on a str. Typically code like: some_str.startswith """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_STARTSWITH" attribute_name = "startswith" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationStartswith(prefix, start, end, source_ref): if end is not None: from .StrNodes import ExpressionStrOperationStartswith4 return ExpressionStrOperationStartswith4( str_arg=self.subnode_expression, prefix=prefix, start=start, end=end, source_ref=source_ref, ) elif start is not None: from .StrNodes import ExpressionStrOperationStartswith3 return ExpressionStrOperationStartswith3( str_arg=self.subnode_expression, prefix=prefix, start=start, source_ref=source_ref, ) else: from .StrNodes import ExpressionStrOperationStartswith2 return ExpressionStrOperationStartswith2( str_arg=self.subnode_expression, prefix=prefix, source_ref=source_ref, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationStartswith, builtin_spec=str_startswith_spec, ) return result, "new_expression", "Call to 'startswith' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrStartswith) class ExpressionAttributeLookupFixedStrip(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'strip' of an object. Typically code like: source.strip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_STRIP" attribute_name = "strip" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrStrip( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'strip' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="strip", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="strip" ) attribute_classes["strip"] = ExpressionAttributeLookupFixedStrip from nuitka.specs.BuiltinStrOperationSpecs import str_strip_spec class ExpressionAttributeLookupStrStrip( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedStrip ): """Attribute Strip lookup on a str. Typically code like: some_str.strip """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_STRIP" attribute_name = "strip" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationStrip(chars, source_ref): if chars is not None: from .StrNodes import ExpressionStrOperationStrip2 return ExpressionStrOperationStrip2( str_arg=self.subnode_expression, chars=chars, source_ref=source_ref ) else: from .StrNodes import ExpressionStrOperationStrip1 return ExpressionStrOperationStrip1( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationStrip, builtin_spec=str_strip_spec, ) return result, "new_expression", "Call to 'strip' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrStrip) class ExpressionAttributeLookupFixedSwapcase(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'swapcase' of an object. Typically code like: source.swapcase """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_SWAPCASE" attribute_name = "swapcase" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrSwapcase( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'swapcase' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="swapcase", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="swapcase" ) attribute_classes["swapcase"] = ExpressionAttributeLookupFixedSwapcase from nuitka.specs.BuiltinStrOperationSpecs import str_swapcase_spec class ExpressionAttributeLookupStrSwapcase( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedSwapcase ): """Attribute Swapcase lookup on a str. Typically code like: some_str.swapcase """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_SWAPCASE" attribute_name = "swapcase" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationSwapcase(source_ref): from .StrNodes import ExpressionStrOperationSwapcase return ExpressionStrOperationSwapcase( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationSwapcase, builtin_spec=str_swapcase_spec, ) return result, "new_expression", "Call to 'swapcase' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrSwapcase) class ExpressionAttributeLookupFixedTitle(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'title' of an object. Typically code like: source.title """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_TITLE" attribute_name = "title" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrTitle( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'title' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="title", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="title" ) attribute_classes["title"] = ExpressionAttributeLookupFixedTitle from nuitka.specs.BuiltinStrOperationSpecs import str_title_spec class ExpressionAttributeLookupStrTitle( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedTitle ): """Attribute Title lookup on a str. Typically code like: some_str.title """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_TITLE" attribute_name = "title" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationTitle(source_ref): from .StrNodes import ExpressionStrOperationTitle return ExpressionStrOperationTitle( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationTitle, builtin_spec=str_title_spec, ) return result, "new_expression", "Call to 'title' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrTitle) class ExpressionAttributeLookupFixedTranslate(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'translate' of an object. Typically code like: source.translate """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_TRANSLATE" attribute_name = "translate" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrTranslate( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'translate' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="translate", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="translate" ) attribute_classes["translate"] = ExpressionAttributeLookupFixedTranslate class ExpressionAttributeLookupStrTranslate( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedTranslate ): """Attribute Translate lookup on a str. Typically code like: some_str.translate """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_TRANSLATE" attribute_name = "translate" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationTranslate is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrTranslate) class ExpressionAttributeLookupFixedUpdate(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'update' of an object. Typically code like: source.update """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_UPDATE" attribute_name = "update" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictUpdate( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'update' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="update", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="update" ) attribute_classes["update"] = ExpressionAttributeLookupFixedUpdate from nuitka.specs.BuiltinDictOperationSpecs import dict_update_spec class ExpressionAttributeLookupDictUpdate( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedUpdate ): """Attribute Update lookup on a dict. Typically code like: some_dict.update """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_UPDATE" attribute_name = "update" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationUpdate(list_args, kw_args, source_ref): if kw_args is not None: from .DictionaryNodes import ExpressionDictOperationUpdate3 return ExpressionDictOperationUpdate3( dict_arg=self.subnode_expression, iterable=list_args, pairs=kw_args, source_ref=source_ref, ) else: from .DictionaryNodes import ExpressionDictOperationUpdate2 return ExpressionDictOperationUpdate2( dict_arg=self.subnode_expression, iterable=list_args, source_ref=source_ref, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationUpdate, builtin_spec=dict_update_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'update' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictUpdate) class ExpressionAttributeLookupFixedUpper(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'upper' of an object. Typically code like: source.upper """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_UPPER" attribute_name = "upper" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrUpper( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'upper' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="upper", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="upper" ) attribute_classes["upper"] = ExpressionAttributeLookupFixedUpper from nuitka.specs.BuiltinStrOperationSpecs import str_upper_spec class ExpressionAttributeLookupStrUpper( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedUpper ): """Attribute Upper lookup on a str. Typically code like: some_str.upper """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_UPPER" attribute_name = "upper" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionStrOperationUpper(source_ref): from .StrNodes import ExpressionStrOperationUpper return ExpressionStrOperationUpper( str_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionStrOperationUpper, builtin_spec=str_upper_spec, ) return result, "new_expression", "Call to 'upper' of str recognized." attribute_typed_classes.add(ExpressionAttributeLookupStrUpper) class ExpressionAttributeLookupFixedValues(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'values' of an object. Typically code like: source.values """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_VALUES" attribute_name = "values" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictValues( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'values' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="values", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="values" ) attribute_classes["values"] = ExpressionAttributeLookupFixedValues from nuitka.specs.BuiltinDictOperationSpecs import dict_values_spec class ExpressionAttributeLookupDictValues( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedValues ): """Attribute Values lookup on a dict. Typically code like: some_dict.values """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_VALUES" attribute_name = "values" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationValues(source_ref): if str is bytes: from .DictionaryNodes import ExpressionDictOperationValues return ExpressionDictOperationValues( dict_arg=self.subnode_expression, source_ref=source_ref ) else: from .DictionaryNodes import ExpressionDictOperationItervalues return ExpressionDictOperationItervalues( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationValues, builtin_spec=dict_values_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'values' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictValues) class ExpressionAttributeLookupFixedViewitems(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'viewitems' of an object. Typically code like: source.viewitems """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_VIEWITEMS" attribute_name = "viewitems" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictViewitems( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'viewitems' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="viewitems", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="viewitems" ) attribute_classes["viewitems"] = ExpressionAttributeLookupFixedViewitems from nuitka.specs.BuiltinDictOperationSpecs import dict_viewitems_spec class ExpressionAttributeLookupDictViewitems( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedViewitems ): """Attribute Viewitems lookup on a dict. Typically code like: some_dict.viewitems """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_VIEWITEMS" attribute_name = "viewitems" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationViewitems(source_ref): from .DictionaryNodes import ExpressionDictOperationViewitems return ExpressionDictOperationViewitems( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationViewitems, builtin_spec=dict_viewitems_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'viewitems' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictViewitems) class ExpressionAttributeLookupFixedViewkeys(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'viewkeys' of an object. Typically code like: source.viewkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_VIEWKEYS" attribute_name = "viewkeys" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictViewkeys( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'viewkeys' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="viewkeys", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="viewkeys" ) attribute_classes["viewkeys"] = ExpressionAttributeLookupFixedViewkeys from nuitka.specs.BuiltinDictOperationSpecs import dict_viewkeys_spec class ExpressionAttributeLookupDictViewkeys( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedViewkeys ): """Attribute Viewkeys lookup on a dict. Typically code like: some_dict.viewkeys """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_VIEWKEYS" attribute_name = "viewkeys" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationViewkeys(source_ref): from .DictionaryNodes import ExpressionDictOperationViewkeys return ExpressionDictOperationViewkeys( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationViewkeys, builtin_spec=dict_viewkeys_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'viewkeys' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictViewkeys) class ExpressionAttributeLookupFixedViewvalues(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'viewvalues' of an object. Typically code like: source.viewvalues """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_VIEWVALUES" attribute_name = "viewvalues" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if str is bytes and subnode_expression.hasShapeDictionaryExact(): return trace_collection.computedExpressionResult( expression=ExpressionAttributeLookupDictViewvalues( expression=subnode_expression, source_ref=self.source_ref ), change_tags="new_expression", change_desc="Attribute lookup 'viewvalues' on dict shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="viewvalues", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="viewvalues" ) attribute_classes["viewvalues"] = ExpressionAttributeLookupFixedViewvalues from nuitka.specs.BuiltinDictOperationSpecs import dict_viewvalues_spec class ExpressionAttributeLookupDictViewvalues( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedViewvalues ): """Attribute Viewvalues lookup on a dict. Typically code like: some_dict.viewvalues """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_DICT_VIEWVALUES" attribute_name = "viewvalues" def computeExpression(self, trace_collection): return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): def wrapExpressionDictOperationViewvalues(source_ref): from .DictionaryNodes import ExpressionDictOperationViewvalues return ExpressionDictOperationViewvalues( dict_arg=self.subnode_expression, source_ref=source_ref ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=wrapExpressionDictOperationViewvalues, builtin_spec=dict_viewvalues_spec, ) return trace_collection.computedExpressionResult( expression=result, change_tags="new_expression", change_desc="Call to 'viewvalues' of dictionary recognized.", ) attribute_typed_classes.add(ExpressionAttributeLookupDictViewvalues) class ExpressionAttributeLookupFixedZfill(ExpressionAttributeLookupFixedBase): """Looking up an attribute value 'zfill' of an object. Typically code like: source.zfill """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_FIXED_ZFILL" attribute_name = "zfill" def computeExpression(self, trace_collection): subnode_expression = self.subnode_expression if subnode_expression.hasShapeStrExact(): result = ExpressionAttributeLookupStrZfill( expression=subnode_expression, source_ref=self.source_ref ) return ( result, "new_expression", "Attribute lookup 'zfill' on str shape resolved.", ) return subnode_expression.computeExpressionAttribute( lookup_node=self, attribute_name="zfill", trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseExceptionAttributeLookup( exception_type=exception_type, attribute_name="zfill" ) attribute_classes["zfill"] = ExpressionAttributeLookupFixedZfill class ExpressionAttributeLookupStrZfill( SideEffectsFromChildrenMixin, ExpressionAttributeLookupFixedZfill ): """Attribute Zfill lookup on a str. Typically code like: some_str.zfill """ kind = "EXPRESSION_ATTRIBUTE_LOOKUP_STR_ZFILL" attribute_name = "zfill" def computeExpression(self, trace_collection): return self, None, None # No computeExpressionCall as str operation ExpressionStrOperationZfill is not yet implemented attribute_typed_classes.add(ExpressionAttributeLookupStrZfill) Nuitka-0.6.19.1/nuitka/nodes/BuiltinVarsNodes.py0000600000372100037210000000271214166627112026501 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Builtin vars node. Not used much, esp. not in the form with arguments. Maybe used in some meta programming, and hopefully can be predicted, because at run time, it is hard to support. """ from .ExpressionBases import ExpressionChildHavingBase class ExpressionBuiltinVars(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_VARS" named_child = "source" def __init__(self, source, source_ref): ExpressionChildHavingBase.__init__(self, value=source, source_ref=source_ref) def computeExpression(self, trace_collection): # TODO: Should be possible to predict this. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/BuiltinAnyNodes.py0000600000372100037210000001011114166627112026305 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Batakrishna Sahu, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'any' built-in. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ExpressionBuiltinSingleArgBase from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, wrapExpressionWithNodeSideEffects, ) class ExpressionBuiltinAny( ExpressionBoolShapeExactMixin, ExpressionBuiltinSingleArgBase ): """Builtin Any Node class. Args: ExpressionBase: 'any - expression' Returns: Node that represents built-in 'any' call. """ kind = "EXPRESSION_BUILTIN_ANY" builtin_spec = BuiltinParameterSpecs.builtin_any_spec def computeExpression(self, trace_collection): value = self.subnode_value shape = value.getTypeShape() if shape.hasShapeSlotIter() is False: # An exception is raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="any", original_node=value, value_node=value, ) iteration_handle = value.getIterationHandle() if iteration_handle is not None: all_false = True count = 0 while True: truth_value = iteration_handle.getNextValueTruth() if truth_value is StopIteration: break if count > 256: all_false = False break if truth_value is True: result = wrapExpressionWithNodeSideEffects( new_node=makeConstantReplacementNode( constant=True, node=self, user_provided=False ), old_node=value, ) return ( result, "new_constant", "Predicted truth value of built-in any argument", ) elif truth_value is None: all_false = False count += 1 if all_false is True: result = wrapExpressionWithNodeSideEffects( new_node=makeConstantReplacementNode( constant=False, node=self, user_provided=False ), old_node=value, ) return ( result, "new_constant", "Predicted truth value of built-in any argument", ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): """returns boolean True if exception is raised else False""" value = self.subnode_value if value.mayRaiseException(exception_type): return True return not value.getTypeShape().hasShapeSlotIter() Nuitka-0.6.19.1/nuitka/nodes/StrNodes.py0000600000372100037210000012632314166627112025014 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes that build and operate on str. """ from abc import abstractmethod from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .ExpressionShapeMixins import ( ExpressionBoolShapeExactMixin, ExpressionBytesShapeExactMixin, ExpressionIntShapeExactMixin, ExpressionListShapeExactMixin, ExpressionStrOrUnicodeExactMixin, ExpressionStrShapeExactMixin, ExpressionTupleShapeExactMixin, ) from .NodeBases import SideEffectsFromChildrenMixin from .NodeMetaClasses import NodeCheckMetaClass def getStrOperationClasses(): """Return all str operation nodes, for use by code generation.""" return ( cls for kind, cls in NodeCheckMetaClass.kinds.items() if kind.startswith("EXPRESSION_STR_OPERATION") ) class ExpressionStrOperationJoin( ExpressionStrShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents s.join(iterable).""" kind = "EXPRESSION_STR_OPERATION_JOIN" named_children = ("str_arg", "iterable") def __init__(self, str_arg, iterable, source_ref): assert str_arg is not None assert iterable is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "iterable": iterable}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg iterable = self.subnode_iterable if str_arg.isCompileTimeConstant() and iterable.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: str_arg.getCompileTimeConstant().join( iterable.getCompileTimeConstant() ), description="Built-in 'str.join' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the iterables contains a non-string. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationPartition( ExpressionTupleShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents s.partition(sep).""" kind = "EXPRESSION_STR_OPERATION_PARTITION" named_children = ("str_arg", "sep") def __init__(self, str_arg, sep, source_ref): assert str_arg is not None assert sep is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sep": sep}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sep = self.subnode_sep if str_arg.isCompileTimeConstant() and sep.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: str_arg.getCompileTimeConstant().partition( sep.getCompileTimeConstant() ), description="Built-in 'str.partition' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sep is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getIterationLength(): return 3 class ExpressionStrOperationRpartition( ExpressionTupleShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents s.rpartition(sep).""" kind = "EXPRESSION_STR_OPERATION_RPARTITION" named_children = ("str_arg", "sep") def __init__(self, str_arg, sep, source_ref): assert str_arg is not None assert sep is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sep": sep}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sep = self.subnode_sep if str_arg.isCompileTimeConstant() and sep.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: str_arg.getCompileTimeConstant().rpartition( sep.getCompileTimeConstant() ), description="Built-in 'str.rpartition' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sep is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getIterationLength(): return 3 class ExpressionStrOperationStrip2Base( ExpressionStrShapeExactMixin, ExpressionChildrenHavingBase ): named_children = ("str_arg", "chars") @abstractmethod def getSimulator(self): """Compile time simulation""" def __init__(self, str_arg, chars, source_ref): assert str_arg is not None assert chars is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "chars": chars}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg chars = self.subnode_chars if str_arg.isCompileTimeConstant() and chars.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), chars.getCompileTimeConstant(), ), description="Built-in 'str.strip' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sep is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): # TODO: Only if chars is not correct shape return True class ExpressionStrOperationStrip2(ExpressionStrOperationStrip2Base): """This operation represents s.strip(chars).""" kind = "EXPRESSION_STR_OPERATION_STRIP2" @staticmethod def getSimulator(): """Compile time simulation""" return str.strip class ExpressionStrOperationLstrip2(ExpressionStrOperationStrip2Base): """This operation represents s.lstrip(chars).""" kind = "EXPRESSION_STR_OPERATION_LSTRIP2" @staticmethod def getSimulator(): """Compile time simulation""" return str.lstrip class ExpressionStrOperationRstrip2(ExpressionStrOperationStrip2Base): """This operation represents s.rstrip(chars).""" kind = "EXPRESSION_STR_OPERATION_RSTRIP2" @staticmethod def getSimulator(): """Compile time simulation""" return str.rstrip class ExpressionStrOperationSingleArgBase( SideEffectsFromChildrenMixin, ExpressionChildHavingBase ): named_child = "str_arg" @abstractmethod def getSimulator(self): """Compile time simulation.""" def __init__(self, str_arg, source_ref): assert str_arg is not None ExpressionChildHavingBase.__init__( self, value=str_arg, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg if str_arg.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), ), description="Built-in 'str.%s' on constant value." % simulator.__name__, user_provided=str_arg.user_provided, ) return self, None, None def mayRaiseException(self, exception_type): return self.subnode_str_arg.mayRaiseException(exception_type) class ExpressionStrOperationStrip1Base( # Base classes can be abstract, pylint: disable=abstract-method ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase, ): """Base class for use by str.strip(), str.lstrip() and str.rstrip()""" class ExpressionStrOperationStrip1(ExpressionStrOperationStrip1Base): """This operation represents s.strip().""" kind = "EXPRESSION_STR_OPERATION_STRIP1" @staticmethod def getSimulator(): """Compile time simulation.""" return str.strip class ExpressionStrOperationLstrip1(ExpressionStrOperationStrip1Base): """This operation represents s.lstrip(chars).""" kind = "EXPRESSION_STR_OPERATION_LSTRIP1" @staticmethod def getSimulator(): """Compile time simulation.""" return str.lstrip class ExpressionStrOperationRstrip1(ExpressionStrOperationStrip1Base): """This operation represents s.rstrip().""" kind = "EXPRESSION_STR_OPERATION_RSTRIP1" @staticmethod def getSimulator(): """Compile time simulation.""" return str.rstrip class ExpressionStrOperationFind2Base( ExpressionIntShapeExactMixin, ExpressionChildrenHavingBase ): named_children = ("str_arg", "sub") def __init__(self, str_arg, sub, source_ref): assert str_arg is not None assert sub is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sub": sub}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sub = self.subnode_sub if str_arg.isCompileTimeConstant() and sub.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), sub.getCompileTimeConstant() ), description="Built-in 'str.find' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sub is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrFindMixin(object): __slots__ = () @staticmethod def getSimulator(): """Compile time simulation""" return str.find class ExpressionStrRfindMixin(object): __slots__ = () @staticmethod def getSimulator(): """Compile time simulation""" return str.rfind class ExpressionStrOperationFind2( ExpressionStrFindMixin, ExpressionStrOperationFind2Base ): """This operation represents s.find(sub).""" kind = "EXPRESSION_STR_OPERATION_FIND2" class ExpressionStrOperationRfind2( ExpressionStrRfindMixin, ExpressionStrOperationFind2Base ): """This operation represents s.rfind(sub).""" kind = "EXPRESSION_STR_OPERATION_RFIND2" class ExpressionStrOperationFind3Base( ExpressionIntShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents s.find(sub).""" kind = "EXPRESSION_STR_OPERATION_FIND3" named_children = ("str_arg", "sub", "start") def __init__(self, str_arg, sub, start, source_ref): assert str_arg is not None assert sub is not None assert start is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sub": sub, "start": start}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sub = self.subnode_sub start = self.subnode_start if ( str_arg.isCompileTimeConstant() and sub.isCompileTimeConstant() and start.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), sub.getCompileTimeConstant(), start.getCompileTimeConstant(), ), description="Built-in 'str.find' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sub is not a string or start is not an int trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationFind3( ExpressionStrFindMixin, ExpressionStrOperationFind3Base ): """This operation represents s.find(sub, start).""" kind = "EXPRESSION_STR_OPERATION_FIND3" class ExpressionStrOperationRfind3( ExpressionStrRfindMixin, ExpressionStrOperationFind3Base ): """This operation represents s.rfind(sub, start).""" kind = "EXPRESSION_STR_OPERATION_RFIND3" class ExpressionStrOperationFind4Base( ExpressionIntShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents s.find(sub).""" kind = "EXPRESSION_STR_OPERATION_FIND4" named_children = ("str_arg", "sub", "start", "end") def __init__(self, str_arg, sub, start, end, source_ref): assert str_arg is not None assert sub is not None assert start is not None assert end is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sub": sub, "start": start, "end": end}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sub = self.subnode_sub start = self.subnode_start end = self.subnode_end if ( str_arg.isCompileTimeConstant() and sub.isCompileTimeConstant() and start.isCompileTimeConstant() and end.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), sub.getCompileTimeConstant(), start.getCompileTimeConstant(), end.getCompileTimeConstant(), ), description="Built-in 'str.find' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sub is not a string or start and end are not int trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationFind4( ExpressionStrFindMixin, ExpressionStrOperationFind4Base ): """This operation represents s.find(sub, start, end).""" kind = "EXPRESSION_STR_OPERATION_FIND4" class ExpressionStrOperationRfind4( ExpressionStrRfindMixin, ExpressionStrOperationFind4Base ): """This operation represents s.rfind(sub, start, end).""" kind = "EXPRESSION_STR_OPERATION_RFIND4" class ExpressionStrOperationIndexMixin(object): __slots__ = () @staticmethod def mayRaiseException(exception_type): # It will return ValueError if not finding it, pylint: disable=unused-argument return True @staticmethod def getSimulator(): """Compile time simulation""" return str.index class ExpressionStrOperationRindexMixin(ExpressionStrOperationIndexMixin): __slots__ = () @staticmethod def getSimulator(): """Compile time simulation""" return str.rindex class ExpressionStrOperationIndex2( ExpressionStrOperationIndexMixin, ExpressionStrOperationFind2Base ): """This operation represents s.index(sub).""" kind = "EXPRESSION_STR_OPERATION_INDEX2" class ExpressionStrOperationIndex3( ExpressionStrOperationIndexMixin, ExpressionStrOperationFind3Base ): """This operation represents s.index(sub, start).""" kind = "EXPRESSION_STR_OPERATION_INDEX3" class ExpressionStrOperationIndex4( ExpressionStrOperationIndexMixin, ExpressionStrOperationFind4Base ): """This operation represents s.index(sub, start, end).""" kind = "EXPRESSION_STR_OPERATION_INDEX4" class ExpressionStrOperationRindex2( ExpressionStrOperationRindexMixin, ExpressionStrOperationFind2Base ): """This operation represents s.rindex(sub).""" kind = "EXPRESSION_STR_OPERATION_RINDEX2" class ExpressionStrOperationRindex3( ExpressionStrOperationRindexMixin, ExpressionStrOperationFind3Base ): """This operation represents s.rindex(sub, start).""" kind = "EXPRESSION_STR_OPERATION_RINDEX3" class ExpressionStrOperationRindex4( ExpressionStrOperationRindexMixin, ExpressionStrOperationFind4Base ): """This operation represents s.rindex(sub, start, end).""" kind = "EXPRESSION_STR_OPERATION_RINDEX4" class ExpressionStrOperationCapitalize( ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.capitalize().""" kind = "EXPRESSION_STR_OPERATION_CAPITALIZE" @staticmethod def getSimulator(): """Compile time simulation.""" return str.capitalize class ExpressionStrOperationUpper( ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.upper().""" kind = "EXPRESSION_STR_OPERATION_UPPER" @staticmethod def getSimulator(): """Compile time simulation.""" return str.upper class ExpressionStrOperationLower( ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.lower().""" kind = "EXPRESSION_STR_OPERATION_LOWER" @staticmethod def getSimulator(): """Compile time simulation.""" return str.lower class ExpressionStrOperationSwapcase( ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.swapcase().""" kind = "EXPRESSION_STR_OPERATION_SWAPCASE" @staticmethod def getSimulator(): """Compile time simulation.""" return str.swapcase class ExpressionStrOperationTitle( ExpressionStrShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.title().""" kind = "EXPRESSION_STR_OPERATION_TITLE" @staticmethod def getSimulator(): """Compile time simulation.""" return str.title class ExpressionStrOperationIsalnum( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.isalnum().""" kind = "EXPRESSION_STR_OPERATION_ISALNUM" @staticmethod def getSimulator(): """Compile time simulation.""" return str.isalnum class ExpressionStrOperationIsalpha( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.isalpha().""" kind = "EXPRESSION_STR_OPERATION_ISALPHA" @staticmethod def getSimulator(): """Compile time simulation.""" return str.isalpha class ExpressionStrOperationIsdigit( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.isdigit().""" kind = "EXPRESSION_STR_OPERATION_ISDIGIT" @staticmethod def getSimulator(): """Compile time simulation.""" return str.isdigit class ExpressionStrOperationIslower( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.islower().""" kind = "EXPRESSION_STR_OPERATION_ISLOWER" @staticmethod def getSimulator(): """Compile time simulation.""" return str.islower class ExpressionStrOperationIsupper( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.isupper().""" kind = "EXPRESSION_STR_OPERATION_ISUPPER" @staticmethod def getSimulator(): """Compile time simulation.""" return str.isupper class ExpressionStrOperationIsspace( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.isspace().""" kind = "EXPRESSION_STR_OPERATION_ISSPACE" @staticmethod def getSimulator(): """Compile time simulation.""" return str.isspace class ExpressionStrOperationIstitle( ExpressionBoolShapeExactMixin, ExpressionStrOperationSingleArgBase ): """This operation represents s.istitle().""" kind = "EXPRESSION_STR_OPERATION_ISTITLE" @staticmethod def getSimulator(): """Compile time simulation.""" return str.istitle class ExpressionStrSplitMixin(object): __slots__ = () @staticmethod def getSimulator(): """Compile time simulation.""" return str.split class ExpressionStrRsplitMixin(object): __slots__ = () @staticmethod def getSimulator(): """Compile time simulation.""" return str.rsplit class ExpressionStrOperationSplit1Base( # Base classes can be abstract, pylint: disable=abstract-method ExpressionListShapeExactMixin, ExpressionStrOperationSingleArgBase, ): """Base class for use by str.split(), str.lsplit() and str.rsplit()""" class ExpressionStrOperationSplit1( ExpressionStrSplitMixin, ExpressionStrOperationSplit1Base ): """This operation represents s.split().""" kind = "EXPRESSION_STR_OPERATION_SPLIT1" # TODO: This one could be eliminated in factor of simpleExpressionStrOperationSplit1 # since without an argument, there is no difference. class ExpressionStrOperationRsplit1( ExpressionStrRsplitMixin, ExpressionStrOperationSplit1Base ): """This operation represents s.rsplit().""" kind = "EXPRESSION_STR_OPERATION_RSPLIT1" class ExpressionStrOperationSplit2Base( ExpressionListShapeExactMixin, ExpressionChildrenHavingBase ): named_children = ("str_arg", "sep") def __init__(self, str_arg, sep, source_ref): assert str_arg is not None assert sep is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sep": sep}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sep = self.subnode_sep if str_arg.isCompileTimeConstant() and sep.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), sep.getCompileTimeConstant() ), description="Built-in 'str.split' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the sep is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationSplit2( ExpressionStrSplitMixin, ExpressionStrOperationSplit2Base ): """This operation represents s.split(sep).""" kind = "EXPRESSION_STR_OPERATION_SPLIT2" class ExpressionStrOperationRsplit2( ExpressionStrRsplitMixin, ExpressionStrOperationSplit2Base ): """This operation represents s.rsplit(sep).""" kind = "EXPRESSION_STR_OPERATION_RSPLIT2" class ExpressionStrOperationSplit3Base( ExpressionListShapeExactMixin, ExpressionChildrenHavingBase ): named_children = ("str_arg", "sep", "maxsplit") def __init__(self, str_arg, sep, maxsplit, source_ref): assert str_arg is not None assert sep is not None assert maxsplit is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "sep": sep, "maxsplit": maxsplit}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg sep = self.subnode_sep maxsplit = self.subnode_maxsplit if ( str_arg.isCompileTimeConstant() and sep.isCompileTimeConstant() and maxsplit.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), sep.getCompileTimeConstant(), maxsplit.getCompileTimeConstant(), ), description="Built-in 'str.split' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the seo is not a string or maxsplit not a number trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationSplit3( ExpressionStrSplitMixin, ExpressionStrOperationSplit3Base ): """This operation represents s.split(sep, maxsplit).""" kind = "EXPRESSION_STR_OPERATION_SPLIT3" class ExpressionStrOperationRsplit3( ExpressionStrRsplitMixin, ExpressionStrOperationSplit3Base ): """This operation represents s.rsplit(sep, maxsplit).""" kind = "EXPRESSION_STR_OPERATION_RSPLIT3" class ExpressionStrOperationEndswithBase( ExpressionBoolShapeExactMixin, ExpressionChildrenHavingBase ): @staticmethod def getSimulator(): """Compile time simulation""" return str.endswith class ExpressionStrOperationEndswith2(ExpressionStrOperationEndswithBase): kind = "EXPRESSION_STR_OPERATION_ENDSWITH2" named_children = ("str_arg", "suffix") def __init__(self, str_arg, suffix, source_ref): assert str_arg is not None assert suffix is not None ExpressionStrOperationEndswithBase.__init__( self, values={"str_arg": str_arg, "suffix": suffix}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg suffix = self.subnode_suffix if str_arg.isCompileTimeConstant() and suffix.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), suffix.getCompileTimeConstant() ), description="Built-in 'str.endswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the suffix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationEndswith3(ExpressionStrOperationEndswithBase): kind = "EXPRESSION_STR_OPERATION_ENDSWITH3" named_children = ("str_arg", "suffix", "start") def __init__(self, str_arg, suffix, start, source_ref): assert str_arg is not None assert suffix is not None assert start is not None ExpressionStrOperationEndswithBase.__init__( self, values={"str_arg": str_arg, "suffix": suffix, "start": start}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg suffix = self.subnode_suffix start = self.subnode_start if ( str_arg.isCompileTimeConstant() and suffix.isCompileTimeConstant() and start.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), suffix.getCompileTimeConstant(), start.getCompileTimeConstant(), ), description="Built-in 'str.endswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the suffix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationEndswith4(ExpressionStrOperationEndswithBase): kind = "EXPRESSION_STR_OPERATION_ENDSWITH4" named_children = ("str_arg", "suffix", "start", "end") def __init__(self, str_arg, suffix, start, end, source_ref): assert str_arg is not None assert suffix is not None assert start is not None assert end is not None ExpressionStrOperationEndswithBase.__init__( self, values={"str_arg": str_arg, "suffix": suffix, "start": start, "end": end}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg suffix = self.subnode_suffix start = self.subnode_start end = self.subnode_end if ( str_arg.isCompileTimeConstant() and suffix.isCompileTimeConstant() and start.isCompileTimeConstant() and end.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), suffix.getCompileTimeConstant(), start.getCompileTimeConstant(), end.getCompileTimeConstant(), ), description="Built-in 'str.endswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the suffix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationStartswithBase( ExpressionBoolShapeExactMixin, ExpressionChildrenHavingBase ): @staticmethod def getSimulator(): """Compile time simulation""" return str.startswith class ExpressionStrOperationStartswith2(ExpressionStrOperationStartswithBase): kind = "EXPRESSION_STR_OPERATION_STARTSWITH2" named_children = ("str_arg", "prefix") def __init__(self, str_arg, prefix, source_ref): assert str_arg is not None assert prefix is not None ExpressionStrOperationStartswithBase.__init__( self, values={"str_arg": str_arg, "prefix": prefix}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg prefix = self.subnode_prefix if str_arg.isCompileTimeConstant() and prefix.isCompileTimeConstant(): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), prefix.getCompileTimeConstant() ), description="Built-in 'str.startswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the prefix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationStartswith3(ExpressionStrOperationStartswithBase): kind = "EXPRESSION_STR_OPERATION_STARTSWITH3" named_children = ("str_arg", "prefix", "start") def __init__(self, str_arg, prefix, start, source_ref): assert str_arg is not None assert prefix is not None assert start is not None ExpressionStrOperationStartswithBase.__init__( self, values={"str_arg": str_arg, "prefix": prefix, "start": start}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg prefix = self.subnode_prefix start = self.subnode_start if ( str_arg.isCompileTimeConstant() and prefix.isCompileTimeConstant() and start.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), prefix.getCompileTimeConstant(), start.getCompileTimeConstant(), ), description="Built-in 'str.startswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the prefix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationStartswith4(ExpressionStrOperationStartswithBase): kind = "EXPRESSION_STR_OPERATION_STARTSWITH4" named_children = ("str_arg", "prefix", "start", "end") def __init__(self, str_arg, prefix, start, end, source_ref): assert str_arg is not None assert prefix is not None assert start is not None assert end is not None ExpressionStrOperationStartswithBase.__init__( self, values={"str_arg": str_arg, "prefix": prefix, "start": start, "end": end}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg prefix = self.subnode_prefix start = self.subnode_start end = self.subnode_end if ( str_arg.isCompileTimeConstant() and prefix.isCompileTimeConstant() and start.isCompileTimeConstant() and end.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), prefix.getCompileTimeConstant(), start.getCompileTimeConstant(), end.getCompileTimeConstant(), ), description="Built-in 'str.startswith' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the prefix is not a string trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationReplaceBase( ExpressionStrOrUnicodeExactMixin, ExpressionChildrenHavingBase ): @staticmethod def getSimulator(): """Compile time simulation""" return str.replace class ExpressionStrOperationReplace3(ExpressionStrOperationReplaceBase): kind = "EXPRESSION_STR_OPERATION_REPLACE3" named_children = ("str_arg", "old", "new") def __init__(self, str_arg, old, new, source_ref): assert str_arg is not None assert old is not None assert new is not None ExpressionStrOperationReplaceBase.__init__( self, values={"str_arg": str_arg, "old": old, "new": new}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg old = self.subnode_old new = self.subnode_new if ( str_arg.isCompileTimeConstant() and old.isCompileTimeConstant() and new.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), old.getCompileTimeConstant(), new.getCompileTimeConstant(), ), description="Built-in 'str.replace' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the old/new are not strings trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationReplace4(ExpressionStrOperationReplaceBase): kind = "EXPRESSION_STR_OPERATION_REPLACE4" named_children = ("str_arg", "old", "new", "count") def __init__(self, str_arg, old, new, count, source_ref): assert str_arg is not None assert old is not None assert new is not None assert count is not None ExpressionStrOperationReplaceBase.__init__( self, values={"str_arg": str_arg, "old": old, "new": new, "count": count}, source_ref=source_ref, ) def computeExpression(self, trace_collection): str_arg = self.subnode_str_arg old = self.subnode_old new = self.subnode_new count = self.subnode_count if ( str_arg.isCompileTimeConstant() and old.isCompileTimeConstant() and new.isCompileTimeConstant() and count.isCompileTimeConstant() ): simulator = self.getSimulator() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: simulator( str_arg.getCompileTimeConstant(), old.getCompileTimeConstant(), new.getCompileTimeConstant(), count.getCompileTimeConstant(), ), description="Built-in 'str.replace' with constant values.", user_provided=str_arg.user_provided, ) # TODO: Only if the old/new are not strings trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationEncodeMixin( ExpressionBytesShapeExactMixin if str is not bytes else ExpressionStrShapeExactMixin ): __slots__ = () # TODO: Encodings might be registered and influence things at runtime, disabled # until we researched that. @staticmethod def getSimulator(): """Compile time simulation""" return str.encode class ExpressionStrOperationEncode1( ExpressionStrOperationEncodeMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_STR_OPERATION_ENCODE1" named_child = "str_arg" def __init__(self, str_arg, source_ref): assert str_arg is not None ExpressionChildHavingBase.__init__( self, value=str_arg, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be encoded. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationEncode2( ExpressionStrOperationEncodeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_STR_OPERATION_ENCODE2" named_children = "str_arg", "encoding" def __init__(self, str_arg, encoding, source_ref): assert str_arg is not None assert encoding is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "encoding": encoding}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be encoded to the given encoding trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationEncode3( ExpressionStrOperationEncodeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_STR_OPERATION_ENCODE3" named_children = "str_arg", "encoding", "errors" def __init__(self, str_arg, encoding, errors, source_ref): assert str_arg is not None assert encoding is not None assert errors is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "encoding": encoding, "errors": errors}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be encoded to the given encoding, and errors # is not ignore. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationDecodeMixin(ExpressionStrOrUnicodeExactMixin): __slots__ = () # TODO: Encodings might be registered and influence things at runtime, disabled # until we researched that. @staticmethod def getSimulator(): """Compile time simulation""" return str.decode class ExpressionStrOperationDecode1( ExpressionStrOperationDecodeMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_STR_OPERATION_DECODE1" named_child = "str_arg" def __init__(self, str_arg, source_ref): assert str_arg is not None ExpressionChildHavingBase.__init__( self, value=str_arg, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be decoded. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationDecode2( ExpressionStrOperationDecodeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_STR_OPERATION_DECODE2" named_children = "str_arg", "encoding" def __init__(self, str_arg, encoding, source_ref): assert str_arg is not None assert encoding is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "encoding": encoding}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be decoded to the given encoding trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionStrOperationDecode3( ExpressionStrOperationDecodeMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_STR_OPERATION_DECODE3" named_children = "str_arg", "encoding", "errors" def __init__(self, str_arg, encoding, errors, source_ref): assert str_arg is not None assert encoding is not None assert errors is not None ExpressionChildrenHavingBase.__init__( self, values={"str_arg": str_arg, "encoding": encoding, "errors": errors}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Only if the string cannot be decoded to the given encoding, and errors # is not ignore. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/OperatorNodesUnary.py0000600000372100037210000002151714166627112027055 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for unary operations. Some of these come from built-ins, e.g. abs, some from syntax, and repr from both. """ from nuitka import PythonOperators from .ConstantRefNodes import makeConstantRefNode from .ExpressionBases import ExpressionChildHavingBase from .ExpressionShapeMixins import ( ExpressionBoolShapeExactMixin, ExpressionStrOrUnicodeDerivedShapeMixin, ) class ExpressionOperationUnaryBase(ExpressionChildHavingBase): named_child = "operand" __slots__ = ("operator", "simulator") def __init__(self, operand, source_ref): ExpressionChildHavingBase.__init__(self, value=operand, source_ref=source_ref) def getOperator(self): return self.operator def computeExpression(self, trace_collection): operator = self.getOperator() operand = self.subnode_operand if operand.isCompileTimeConstant(): operand_value = operand.getCompileTimeConstant() return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.simulator(operand_value), description="Operator '%s' with constant argument." % operator, ) else: # TODO: May go down to MemoryError for compile time constant overflow # ones. trace_collection.onExceptionRaiseExit(BaseException) # The value of that node escapes and could change its contents. # TODO: The unary operations don't do much to an operator, add # methods, that don't do stuff on common types though. # trace_collection.onValueEscapeSomeUnaryOperator(operand) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self, None, None @staticmethod def isExpressionOperationUnary(): return True class ExpressionOperationUnaryRepr( # TODO: Not exact ExpressionStrOrUnicodeDerivedShapeMixin, ExpressionOperationUnaryBase ): """Python unary operator `x` and repr built-in.""" kind = "EXPRESSION_OPERATION_UNARY_REPR" operator = "Repr" __slots__ = ("escape_desc",) def __init__(self, operand, source_ref): assert operand.isExpression(), operand ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) self.escape_desc = None def computeExpression(self, trace_collection): result, self.escape_desc = self.subnode_operand.computeExpressionOperationRepr( repr_node=self, trace_collection=trace_collection ) return result def mayRaiseException(self, exception_type): # TODO: Match getExceptionExit() more precisely against exception type given return ( self.escape_desc is None or self.escape_desc.getExceptionExit() is not None or self.subnode_operand.mayRaiseException(exception_type) ) def mayHaveSideEffects(self): operand = self.subnode_operand if operand.mayHaveSideEffects(): return True return self.escape_desc is None or self.escape_desc.isControlFlowEscape() class ExpressionOperationUnarySub(ExpressionOperationUnaryBase): """Python unary operator -""" kind = "EXPRESSION_OPERATION_UNARY_SUB" operator = "USub" simulator = PythonOperators.unary_operator_functions[operator] def __init__(self, operand, source_ref): assert operand.isExpression(), operand ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) class ExpressionOperationUnaryAdd(ExpressionOperationUnaryBase): """Python unary operator +""" kind = "EXPRESSION_OPERATION_UNARY_ADD" operator = "UAdd" simulator = PythonOperators.unary_operator_functions[operator] def __init__(self, operand, source_ref): assert operand.isExpression(), operand ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) class ExpressionOperationUnaryInvert(ExpressionOperationUnaryBase): """Python unary operator ~""" kind = "EXPRESSION_OPERATION_UNARY_INVERT" operator = "Invert" simulator = PythonOperators.unary_operator_functions[operator] def __init__(self, operand, source_ref): assert operand.isExpression(), operand ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) class ExpressionOperationNot( ExpressionBoolShapeExactMixin, ExpressionOperationUnaryBase ): kind = "EXPRESSION_OPERATION_NOT" operator = "Not" simulator = PythonOperators.unary_operator_functions[operator] def __init__(self, operand, source_ref): ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) def computeExpression(self, trace_collection): return self.subnode_operand.computeExpressionOperationNot( not_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): return self.subnode_operand.mayRaiseException( exception_type ) or self.subnode_operand.mayRaiseExceptionBool(exception_type) def getTruthValue(self): result = self.subnode_operand.getTruthValue() # Need to invert the truth value of operand of course here. return None if result is None else not result def mayHaveSideEffects(self): operand = self.subnode_operand if operand.mayHaveSideEffects(): return True return operand.mayHaveSideEffectsBool() def mayHaveSideEffectsBool(self): return self.subnode_operand.mayHaveSideEffectsBool() def extractSideEffects(self): operand = self.subnode_operand # TODO: Find the common ground of these, and make it an expression # method. if operand.isExpressionMakeSequence(): return operand.extractSideEffects() if operand.isExpressionMakeDict(): return operand.extractSideEffects() return (self,) class ExpressionOperationUnaryAbs(ExpressionOperationUnaryBase): kind = "EXPRESSION_OPERATION_UNARY_ABS" operator = "Abs" simulator = PythonOperators.unary_operator_functions[operator] def __init__(self, operand, source_ref): ExpressionOperationUnaryBase.__init__( self, operand=operand, source_ref=source_ref ) def computeExpression(self, trace_collection): return self.subnode_operand.computeExpressionAbs( abs_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): operand = self.subnode_operand if operand.mayRaiseException(exception_type): return True return operand.mayRaiseExceptionAbs(exception_type) def mayHaveSideEffects(self): operand = self.subnode_operand if operand.mayHaveSideEffects(): return True return operand.mayHaveSideEffectsAbs() def makeExpressionOperationUnary(operator, operand, source_ref): if operator == "Repr": unary_class = ExpressionOperationUnaryRepr elif operator == "USub": unary_class = ExpressionOperationUnarySub elif operator == "UAdd": unary_class = ExpressionOperationUnaryAdd elif operator == "Invert": unary_class = ExpressionOperationUnaryInvert else: assert False, operand # Shortcut these unary operations, avoiding "-1", etc. to ever become one. if operand.isCompileTimeConstant(): try: constant = unary_class.simulator(operand.getCompileTimeConstant()) except Exception: # Catch all the things, pylint: disable=broad-except # Compile time detectable error, postpone these, so they get traced. pass else: return makeConstantRefNode( constant=constant, source_ref=source_ref, user_provided=getattr(operand, "user_provided", False), ) return unary_class(operand=operand, source_ref=source_ref) Nuitka-0.6.19.1/nuitka/nodes/shapes/0000700000372100037210000000000014167275622024161 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/nodes/shapes/StandardShapes.py0000600000372100037210000012166114166627112027442 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard shapes that commonly appear. """ from abc import abstractmethod from nuitka.__past__ import getMetaClassBase from nuitka.codegen.c_types.CTypePyObjectPtrs import CTypePyObjectPtr from nuitka.codegen.Reports import onMissingOperation from .ControlFlowDescriptions import ControlFlowDescriptionFullEscape from .ShapeMixins import ShapeIteratorMixin class ShapeBase(getMetaClassBase("Shape")): def __repr__(self): return "<%s %s %s>" % ( self.__class__.__name__, self.getTypeName(), self.helper_code, ) @staticmethod def getTypeName(): return None helper_code = "OBJECT" @staticmethod def getCType(): return CTypePyObjectPtr @staticmethod def getShapeIter(): return tshape_unknown @staticmethod def hasShapeModule(): return None @staticmethod def hasShapeSlotBytes(): return None @staticmethod def hasShapeSlotComplex(): return None @staticmethod def hasShapeSlotBool(): return None @staticmethod def hasShapeSlotAbs(): return None @staticmethod def hasShapeSlotLen(): return None @staticmethod def hasShapeSlotInt(): return None @staticmethod def hasShapeSlotLong(): return None @staticmethod def hasShapeSlotFloat(): return None @staticmethod def hasShapeSlotIter(): return None @staticmethod def hasShapeSlotNext(): return None @staticmethod def hasShapeSlotContains(): return None @staticmethod def hasShapeSlotHash(): return None @staticmethod def hasShapeTrustedAttributes(): return None add_shapes = {} def getOperationBinaryAddShape(self, right_shape): result = self.add_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryAddLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Add", self, right_shape) return operation_result_unknown # TODO: Change defaults to be "None" for easier catching of # non-overloaders iadd_shapes = {} def getOperationInplaceAddShape(self, right_shape): """Inplace add operation shape, for overload.""" if self.iadd_shapes: result = self.iadd_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryAddLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("IAdd", self, right_shape) return operation_result_unknown else: # By default, inplace add is the same as plain add, the # only exception known right now is list, which extend # from all iterables, but don't add with them. return self.getOperationBinaryAddShape(right_shape) sub_shapes = {} def getOperationBinarySubShape(self, right_shape): result = self.sub_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinarySubLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Sub", self, right_shape) return operation_result_unknown mult_shapes = {} def getOperationBinaryMultShape(self, right_shape): result = self.mult_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryMultLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Mult", self, right_shape) return operation_result_unknown floordiv_shapes = {} def getOperationBinaryFloorDivShape(self, right_shape): result = self.floordiv_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryFloorDivLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("FloorDiv", self, right_shape) return operation_result_unknown olddiv_shapes = {} def getOperationBinaryOldDivShape(self, right_shape): result = self.olddiv_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryOldDivLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("OldDiv", self, right_shape) return operation_result_unknown truediv_shapes = {} def getOperationBinaryTrueDivShape(self, right_shape): result = self.truediv_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryTrueDivLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("TrueDiv", self, right_shape) return operation_result_unknown mod_shapes = {} def getOperationBinaryModShape(self, right_shape): result = self.mod_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryModLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Mod", self, right_shape) return operation_result_unknown divmod_shapes = {} def getOperationBinaryDivmodShape(self, right_shape): result = self.divmod_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryDivmodLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Divmod", self, right_shape) return operation_result_unknown pow_shapes = {} def getOperationBinaryPowShape(self, right_shape): result = self.pow_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryPowLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Pow", self, right_shape) return operation_result_unknown lshift_shapes = {} def getOperationBinaryLShiftShape(self, right_shape): result = self.lshift_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryLShiftLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("LShift", self, right_shape) return operation_result_unknown rshift_shapes = {} def getOperationBinaryRShiftShape(self, right_shape): result = self.rshift_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryRShiftLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("RShift", self, right_shape) return operation_result_unknown bitor_shapes = {} def getOperationBinaryBitOrShape(self, right_shape): result = self.bitor_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryBitOrLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("BitOr", self, right_shape) return operation_result_unknown bitand_shapes = {} def getOperationBinaryBitAndShape(self, right_shape): result = self.bitand_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryBitAndLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("BitAnd", self, right_shape) return operation_result_unknown bitxor_shapes = {} def getOperationBinaryBitXorShape(self, right_shape): result = self.bitxor_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryBitXorLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("BitXor", self, right_shape) return operation_result_unknown ibitor_shapes = {} def getOperationInplaceBitOrShape(self, right_shape): """Inplace bitor operation shape, for overload.""" if self.ibitor_shapes: result = self.ibitor_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryBitOrLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("IBitOr", self, right_shape) return operation_result_unknown else: # By default, inplace add is the same as plain add, the # only exception known right now is list, which extend # from all iterables, but don't add with them. return self.getOperationBinaryBitOrShape(right_shape) matmult_shapes = {} def getOperationBinaryMatMultShape(self, right_shape): result = self.matmult_shapes.get(right_shape) if result is not None: return result else: right_shape_type = type(right_shape) if right_shape_type is ShapeLoopCompleteAlternative: return right_shape.getOperationBinaryBitMatMultLShape(self) if right_shape_type is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("MatMult", self, right_shape) return operation_result_unknown def getComparisonLtShape(self, right_shape): onMissingOperation("Lt", self, right_shape) return operation_result_unknown def getComparisonLteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGtShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonEqShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonNeqShape(self, right_shape): return self.getComparisonLtShape(right_shape) @abstractmethod def getOperationUnaryReprEscape(self): pass def emitAlternatives(self, emit): emit(self) class ShapeTypeUnknown(ShapeBase): @staticmethod def getOperationBinaryAddShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinarySubShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryMultShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryFloorDivShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryOldDivShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryTrueDivShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryModShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryDivmodShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryPowShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryLShiftShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryRShiftShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryBitOrShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryBitAndShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryBitXorShape(right_shape): return operation_result_unknown @staticmethod def getOperationBinaryMatMultShape(right_shape): return operation_result_unknown @staticmethod def getComparisonLtShape(right_shape): return operation_result_unknown @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionFullEscape tshape_unknown = ShapeTypeUnknown() class ShapeTypeUninit(ShapeTypeUnknown): pass tshape_uninit = ShapeTypeUninit() class ValueShapeBase(object): __slots__ = () def hasShapeSlotLen(self): return self.getTypeShape().hasShapeSlotLen() class ValueShapeUnknown(ValueShapeBase): __slots__ = () @staticmethod def getTypeShape(): return tshape_unknown @staticmethod def isConstant(): """Can't say if it's constant, we don't know anything.""" return None # Singleton value for sharing. vshape_unknown = ValueShapeUnknown() class ShapeLargeConstantValue(object): __slots__ = "shape", "size" def __init__(self, size, shape): self.size = size self.shape = shape def getTypeShape(self): return self.shape @staticmethod def isConstant(): return True def hasShapeSlotLen(self): return self.shape.hasShapeSlotLen() class ShapeLargeConstantValuePredictable(ShapeLargeConstantValue): __slots__ = ("predictor",) def __init__(self, size, predictor, shape): ShapeLargeConstantValue.__init__(self, size, shape) self.predictor = predictor class ShapeIterator(ShapeBase, ShapeIteratorMixin): """Iterator created by iter with 2 arguments, TODO: could be way more specific.""" @staticmethod def hasShapeSlotBool(): return None @staticmethod def hasShapeSlotLen(): return None @staticmethod def hasShapeSlotInt(): return None @staticmethod def hasShapeSlotLong(): return None @staticmethod def hasShapeSlotFloat(): return None @staticmethod def getShapeIter(): return tshape_iterator @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionFullEscape tshape_iterator = ShapeIterator() class ShapeLoopInitialAlternative(ShapeBase): """Merge of loop wrap around with loop start value. Happens at the start of loop blocks. This is for loop closed SSA, to make it clear, that the entered value, can be anything really, and will only later be clarified. They will start out with just one previous, and later be updated with all of the variable versions at loop continue times. """ __slots__ = ("type_shapes",) def __init__(self, shapes): self.type_shapes = shapes def emitAlternatives(self, emit): for type_shape in self.type_shapes: type_shape.emitAlternatives(emit) def _collectInitialShape(self, operation): result = set() for type_shape in self.type_shapes: try: entry, _description = operation(type_shape) except TypeError: assert False, type_shape if entry is tshape_unknown: return tshape_unknown result.add(entry) return ShapeLoopInitialAlternative(result) def getOperationBinaryAddShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryAddShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationInplaceAddShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationInplaceAddShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinarySubShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinarySubShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryMultShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryMultShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryFloorDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryFloorDivShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryOldDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryOldDivShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryTrueDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryTrueDivShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryModShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryModShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryDivmodShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryDivmodShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryPowShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryPowShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryLShiftShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryLShiftShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryRShiftShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryRShiftShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryBitOrShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryBitOrShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryBitAndShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryBitAndShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryBitXorShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryBitXorShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getOperationBinaryMatMultShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getOperationBinaryMatMultShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown else: return ( self._collectInitialShape( operation=lambda left_shape: left_shape.getComparisonLtShape( right_shape ) ), ControlFlowDescriptionFullEscape, ) def getComparisonLteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGtShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonEqShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonNeqShape(self, right_shape): return self.getComparisonLtShape(right_shape) @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionFullEscape class ShapeLoopCompleteAlternative(ShapeBase): """Merge of loop wrap around with loop start value. Happens at the start of loop blocks. This is for loop closed SSA, to make it clear, that the entered value, can be one of multiple types, but only those. They will start out with just one previous, and later be updated with all of the variable versions at loop continue times. """ __slots__ = ("type_shapes",) def __init__(self, shapes): self.type_shapes = shapes def __hash__(self): # We are unhashable set, and need deep comparison. return 27 def __eq__(self, other): if self.__class__ is not other.__class__: return False return self.type_shapes == other.type_shapes def emitAlternatives(self, emit): for type_shape in self.type_shapes: type_shape.emitAlternatives(emit) def _collectShapeOperation(self, operation): result = None escape_description = None single = True for type_shape in self.type_shapes: entry, description = operation(type_shape) if entry is tshape_unknown: return operation_result_unknown if single: if result is None: # First entry, fine. result = entry escape_description = description else: # Second entry, not the same, convert to set. if result is not entry: single = False result = set((result, entry)) escape_description = set((escape_description, description)) else: result.add(entry) escape_description.add(description) if single: assert result is not None return result, escape_description else: if len(escape_description) > 1: if ControlFlowDescriptionFullEscape in escape_description: escape_description = ControlFlowDescriptionFullEscape else: assert False else: (escape_description,) = escape_description return ShapeLoopCompleteAlternative(result), escape_description def getOperationBinaryAddShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryAddShape( right_shape ) ) def getOperationInplaceAddShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationInplaceAddShape( right_shape ) ) def getOperationBinarySubShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinarySubShape( right_shape ) ) def getOperationBinaryMultShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryMultShape( right_shape ) ) def getOperationBinaryFloorDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryFloorDivShape( right_shape ) ) def getOperationBinaryOldDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryOldDivShape( right_shape ) ) def getOperationBinaryTrueDivShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryTrueDivShape( right_shape ) ) def getOperationBinaryModShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryModShape( right_shape ) ) def getOperationBinaryDivmodShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryDivmodShape( right_shape ) ) def getOperationBinaryPowShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryPowShape( right_shape ) ) def getOperationBinaryLShiftShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryLShiftShape( right_shape ) ) def getOperationBinaryRShiftShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryRShiftShape( right_shape ) ) def getOperationBinaryBitOrShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryBitOrShape( right_shape ) ) def getOperationBinaryBitAndShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryBitAndShape( right_shape ) ) def getOperationBinaryBitXorShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryBitXorShape( right_shape ) ) def getOperationBinaryMatMultShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getOperationBinaryMatMultShape( right_shape ) ) # Special method to be called by other shapes encountering this type on # the right side. def getOperationBinaryAddLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryAddShape ) # Special method to be called by other shapes encountering this type on # the right side. def getOperationBinarySubLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinarySubShape ) def getOperationBinaryMultLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryMultShape ) def getOperationBinaryFloorDivLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryFloorDivShape ) def getOperationBinaryOldDivLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryOldDivShape ) def getOperationBinaryTrueDivLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryTrueDivShape ) def getOperationBinaryModLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryModShape ) def getOperationBinaryDivmodLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryDivmodShape ) def getOperationBinaryPowLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryPowShape ) def getOperationBinaryLShiftLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryLShiftShape ) def getOperationBinaryRShiftLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryRShiftShape ) def getOperationBinaryBitOrLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryBitOrShape ) def getOperationBinaryBitAndLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryBitAndShape ) def getOperationBinaryBitXorLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryBitXorShape ) def getOperationBinaryMatMultLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation( operation=left_shape.getOperationBinaryMatMultShape ) def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown return self._collectShapeOperation( operation=lambda left_shape: left_shape.getComparisonLtShape(right_shape) ) # Special method to be called by other shapes encountering this type on # the right side. def getComparisonLtLShape(self, left_shape): assert left_shape is not tshape_unknown return self._collectShapeOperation(operation=left_shape.getComparisonLtShape) def getComparisonLteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGtShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonGteShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonEqShape(self, right_shape): return self.getComparisonLtShape(right_shape) def getComparisonNeqShape(self, right_shape): return self.getComparisonLtShape(right_shape) @staticmethod def getOperationUnaryReprEscape(): # TODO: We could collect information. return ControlFlowDescriptionFullEscape def _delegatedCheck(self, check): result = None for type_shape in self.type_shapes: r = check(type_shape) if r is None: return None elif r is True: if result is False: return None elif result is None: result = True elif r is False: if result is True: return None elif result is None: result = False return result def hasShapeSlotBool(self): return self._delegatedCheck(lambda x: x.hasShapeSlotBool()) def hasShapeSlotLen(self): return self._delegatedCheck(lambda x: x.hasShapeSlotLen()) def hasShapeSlotIter(self): return self._delegatedCheck(lambda x: x.hasShapeSlotIter()) def hasShapeSlotNext(self): return self._delegatedCheck(lambda x: x.hasShapeSlotNext()) def hasShapeSlotContains(self): return self._delegatedCheck(lambda x: x.hasShapeSlotContains()) def hasShapeSlotInt(self): return self._delegatedCheck(lambda x: x.hasShapeSlotInt()) def hasShapeSlotLong(self): return self._delegatedCheck(lambda x: x.hasShapeSlotLong()) def hasShapeSlotFloat(self): return self._delegatedCheck(lambda x: x.hasShapeSlotFloat()) def hasShapeSlotComplex(self): return self._delegatedCheck(lambda x: x.hasShapeSlotComplex()) def hasShapeSlotBytes(self): return self._delegatedCheck(lambda x: x.hasShapeSlotBytes()) def hasShapeModule(self): return self._delegatedCheck(lambda x: x.hasShapeModule()) tshape_unknown_loop = ShapeLoopCompleteAlternative(shapes=(tshape_unknown,)) operation_result_unknown = tshape_unknown, ControlFlowDescriptionFullEscape Nuitka-0.6.19.1/nuitka/nodes/shapes/BuiltinTypeShapes.py0000600000372100037210000045122514166627112030154 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Shapes for Python built-in types. """ from nuitka.codegen.c_types.CTypeNuitkaBools import CTypeNuitkaBoolEnum from nuitka.codegen.c_types.CTypeNuitkaInts import CTypeNuitkaIntOrLongStruct from nuitka.codegen.Reports import onMissingOperation from nuitka.Options import isExperimental from nuitka.PythonVersions import python_version from .ControlFlowDescriptions import ( ControlFlowDescriptionAddUnsupported, ControlFlowDescriptionBitandUnsupported, ControlFlowDescriptionBitorUnsupported, ControlFlowDescriptionBitxorUnsupported, ControlFlowDescriptionComparisonUnorderable, ControlFlowDescriptionDivmodUnsupported, ControlFlowDescriptionElementBasedEscape, ControlFlowDescriptionFloorDivUnsupported, ControlFlowDescriptionFormatError, ControlFlowDescriptionLshiftUnsupported, ControlFlowDescriptionMatmultUnsupported, ControlFlowDescriptionModUnsupported, ControlFlowDescriptionMulUnsupported, ControlFlowDescriptionNoEscape, ControlFlowDescriptionOldDivUnsupported, ControlFlowDescriptionPowUnsupported, ControlFlowDescriptionRshiftUnsupported, ControlFlowDescriptionSubUnsupported, ControlFlowDescriptionTrueDivUnsupported, ControlFlowDescriptionValueErrorNoEscape, ControlFlowDescriptionZeroDivisionNoEscape, ) from .ShapeMixins import ( ShapeContainerImmutableMixin, ShapeContainerMixin, ShapeContainerMutableMixin, ShapeIteratorMixin, ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeNumberMixin, ) from .StandardShapes import ( ShapeBase, ShapeLoopCompleteAlternative, ShapeLoopInitialAlternative, ShapeTypeUnknown, operation_result_unknown, tshape_unknown, ) # Updated later only, due to cyclic dependencies, make the dictionary # available for reference use in class definition. add_shapes_none = {} sub_shapes_none = {} mult_shapes_none = {} floordiv_shapes_none = {} truediv_shapes_none = {} olddiv_shapes_none = {} mod_shapes_none = {} divmod_shapes_none = {} pow_shapes_none = {} bitor_shapes_none = {} bitand_shapes_none = {} bitxor_shapes_none = {} lshift_shapes_none = {} rshift_shapes_none = {} matmult_shapes_none = {} add_shapes_bool = {} sub_shapes_bool = {} mult_shapes_bool = {} floordiv_shapes_bool = {} truediv_shapes_bool = {} olddiv_shapes_bool = {} mod_shapes_bool = {} divmod_shapes_bool = {} pow_shapes_bool = {} bitor_shapes_bool = {} bitand_shapes_bool = {} bitxor_shapes_bool = {} lshift_shapes_bool = {} rshift_shapes_bool = {} matmult_shapes_bool = matmult_shapes_none add_shapes_int = {} sub_shapes_int = {} mult_shapes_int = {} floordiv_shapes_int = {} truediv_shapes_int = {} olddiv_shapes_int = {} mod_shapes_int = {} divmod_shapes_int = divmod_shapes_bool pow_shapes_int = {} bitor_shapes_int = {} bitand_shapes_int = {} bitxor_shapes_int = {} lshift_shapes_int = {} rshift_shapes_int = {} matmult_shapes_int = matmult_shapes_none add_shapes_long = {} sub_shapes_long = {} mult_shapes_long = {} floordiv_shapes_long = {} truediv_shapes_long = truediv_shapes_int olddiv_shapes_long = {} mod_shapes_long = {} divmod_shapes_long = divmod_shapes_bool pow_shapes_long = {} bitor_shapes_long = {} bitand_shapes_long = {} bitxor_shapes_long = {} lshift_shapes_long = {} rshift_shapes_long = {} matmult_shapes_long = matmult_shapes_none add_shapes_intorlong = {} sub_shapes_intorlong = {} mult_shapes_intorlong = {} floordiv_shapes_intorlong = {} truediv_shapes_intorlong = {} olddiv_shapes_intorlong = {} mod_shapes_intorlong = {} divmod_shapes_intorlong = {} pow_shapes_intorlong = {} bitor_shapes_intorlong = {} bitand_shapes_intorlong = {} bitxor_shapes_intorlong = {} lshift_shapes_intorlong = {} rshift_shapes_intorlong = {} matmult_shapes_intorlong = matmult_shapes_none add_shapes_float = {} sub_shapes_float = {} mult_shapes_float = {} floordiv_shapes_float = {} truediv_shapes_float = {} olddiv_shapes_float = {} mod_shapes_float = {} divmod_shapes_float = divmod_shapes_bool pow_shapes_float = {} bitor_shapes_float = bitor_shapes_none bitand_shapes_float = bitand_shapes_none bitxor_shapes_float = bitxor_shapes_none lshift_shapes_float = lshift_shapes_none rshift_shapes_float = rshift_shapes_none matmult_shapes_float = matmult_shapes_none add_shapes_complex = {} sub_shapes_complex = {} mult_shapes_complex = {} if python_version < 0x300: floordiv_shapes_complex = {} else: floordiv_shapes_complex = floordiv_shapes_none truediv_shapes_complex = {} olddiv_shapes_complex = {} mod_shapes_complex = {} divmod_shapes_complex = divmod_shapes_bool pow_shapes_complex = {} bitor_shapes_complex = bitor_shapes_none bitand_shapes_complex = bitand_shapes_none bitxor_shapes_complex = bitxor_shapes_none lshift_shapes_complex = lshift_shapes_none rshift_shapes_complex = rshift_shapes_none matmult_shapes_complex = matmult_shapes_none add_shapes_tuple = {} sub_shapes_tuple = sub_shapes_none mult_shapes_tuple = {} floordiv_shapes_tuple = floordiv_shapes_none truediv_shapes_tuple = truediv_shapes_none olddiv_shapes_tuple = olddiv_shapes_none mod_shapes_tuple = mod_shapes_none divmod_shapes_tuple = divmod_shapes_none pow_shapes_tuple = pow_shapes_none bitor_shapes_tuple = bitor_shapes_none bitand_shapes_tuple = bitand_shapes_none bitxor_shapes_tuple = bitxor_shapes_none lshift_shapes_tuple = lshift_shapes_none rshift_shapes_tuple = rshift_shapes_none matmult_shapes_tuple = matmult_shapes_none add_shapes_list = {} iadd_shapes_list = {} sub_shapes_list = sub_shapes_none mult_shapes_list = {} floordiv_shapes_list = floordiv_shapes_none truediv_shapes_list = truediv_shapes_none olddiv_shapes_list = olddiv_shapes_none mod_shapes_list = mod_shapes_none divmod_shapes_list = divmod_shapes_none pow_shapes_list = pow_shapes_none bitor_shapes_list = bitor_shapes_none bitand_shapes_list = bitand_shapes_none bitxor_shapes_list = bitxor_shapes_none lshift_shapes_list = lshift_shapes_none rshift_shapes_list = rshift_shapes_none matmult_shapes_list = matmult_shapes_none add_shapes_set = {} sub_shapes_set = {} mult_shapes_set = mult_shapes_none floordiv_shapes_set = floordiv_shapes_none truediv_shapes_set = truediv_shapes_none olddiv_shapes_set = olddiv_shapes_none mod_shapes_set = mod_shapes_none divmod_shapes_set = divmod_shapes_none pow_shapes_set = pow_shapes_none bitor_shapes_set = {} bitand_shapes_set = {} bitxor_shapes_set = {} lshift_shapes_set = lshift_shapes_none rshift_shapes_set = rshift_shapes_none matmult_shapes_set = matmult_shapes_none add_shapes_frozenset = {} sub_shapes_frozenset = {} mult_shapes_frozenset = mult_shapes_none floordiv_shapes_frozenset = floordiv_shapes_none truediv_shapes_frozenset = truediv_shapes_none olddiv_shapes_frozenset = olddiv_shapes_none mod_shapes_frozenset = mod_shapes_none divmod_shapes_frozenset = divmod_shapes_none pow_shapes_frozenset = pow_shapes_none bitor_shapes_frozenset = {} bitand_shapes_frozenset = {} bitxor_shapes_frozenset = {} lshift_shapes_frozenset = lshift_shapes_none rshift_shapes_frozenset = rshift_shapes_none matmult_shapes_frozenset = matmult_shapes_none add_shapes_dict = {} sub_shapes_dict = sub_shapes_none mult_shapes_dict = mult_shapes_none floordiv_shapes_dict = floordiv_shapes_none truediv_shapes_dict = truediv_shapes_none olddiv_shapes_dict = olddiv_shapes_none mod_shapes_dict = mod_shapes_none divmod_shapes_dict = divmod_shapes_none pow_shapes_dict = pow_shapes_none bitor_shapes_dict = dict(bitor_shapes_none) ibitor_shapes_dict = dict(bitor_shapes_none) bitand_shapes_dict = bitand_shapes_none bitxor_shapes_dict = bitxor_shapes_none lshift_shapes_dict = lshift_shapes_none rshift_shapes_dict = rshift_shapes_none matmult_shapes_dict = matmult_shapes_none add_shapes_str = {} sub_shapes_str = sub_shapes_none mult_shapes_str = {} floordiv_shapes_str = floordiv_shapes_none truediv_shapes_str = truediv_shapes_none olddiv_shapes_str = olddiv_shapes_none mod_shapes_str = {} divmod_shapes_str = divmod_shapes_none pow_shapes_str = pow_shapes_none bitor_shapes_str = bitor_shapes_none bitand_shapes_str = bitand_shapes_none bitxor_shapes_str = bitxor_shapes_none lshift_shapes_str = lshift_shapes_none rshift_shapes_str = rshift_shapes_none matmult_shapes_str = matmult_shapes_none add_shapes_bytes = {} sub_shapes_bytes = sub_shapes_none mult_shapes_bytes = {} floordiv_shapes_bytes = floordiv_shapes_none truediv_shapes_bytes = truediv_shapes_none olddiv_shapes_bytes = olddiv_shapes_none mod_shapes_bytes = {} divmod_shapes_bytes = divmod_shapes_none pow_shapes_bytes = pow_shapes_none bitor_shapes_bytes = bitor_shapes_none bitand_shapes_bytes = bitand_shapes_none bitxor_shapes_bytes = bitxor_shapes_none lshift_shapes_bytes = lshift_shapes_none rshift_shapes_bytes = rshift_shapes_none matmult_shapes_bytes = matmult_shapes_none add_shapes_bytearray = {} sub_shapes_bytearray = sub_shapes_none mult_shapes_bytearray = {} floordiv_shapes_bytearray = floordiv_shapes_none truediv_shapes_bytearray = truediv_shapes_none olddiv_shapes_bytearray = olddiv_shapes_none mod_shapes_bytearray = {} divmod_shapes_bytearray = divmod_shapes_none pow_shapes_bytearray = pow_shapes_none bitor_shapes_bytearray = bitor_shapes_none bitand_shapes_bytearray = bitand_shapes_none bitxor_shapes_bytearray = bitxor_shapes_none lshift_shapes_bytearray = lshift_shapes_none rshift_shapes_bytearray = rshift_shapes_none matmult_shapes_bytearray = matmult_shapes_none add_shapes_unicode = {} sub_shapes_unicode = sub_shapes_none mult_shapes_unicode = {} floordiv_shapes_unicode = floordiv_shapes_none truediv_shapes_unicode = truediv_shapes_none olddiv_shapes_unicode = olddiv_shapes_none mod_shapes_unicode = {} divmod_shapes_unicode = divmod_shapes_none pow_shapes_unicode = pow_shapes_none bitor_shapes_unicode = bitor_shapes_none bitand_shapes_unicode = bitand_shapes_none bitxor_shapes_unicode = bitxor_shapes_none lshift_shapes_unicode = lshift_shapes_none rshift_shapes_unicode = rshift_shapes_none matmult_shapes_unicode = matmult_shapes_none add_shapes_strorunicode = {} sub_shapes_strorunicode = {} mult_shapes_strorunicode = {} floordiv_shapes_strorunicode = {} truediv_shapes_strorunicode = {} olddiv_shapes_strorunicode = {} mod_shapes_strorunicode = {} divmod_shapes_strorunicode = {} pow_shapes_strorunicode = {} bitor_shapes_strorunicode = {} bitand_shapes_strorunicode = {} bitxor_shapes_strorunicode = {} lshift_shapes_strorunicode = {} rshift_shapes_strorunicode = {} matmult_shapes_strorunicode = matmult_shapes_none def _getComparisonLtShapeGeneric(self, right_shape): if type(right_shape) is ShapeLoopCompleteAlternative: return right_shape.getComparisonLtLShape(self) if type(right_shape) is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Lt", self, right_shape) return operation_result_unknown def _getComparisonEqShapeGeneric(self, right_shape): if type(right_shape) is ShapeLoopCompleteAlternative: return right_shape.getComparisonEqLShape(self) if type(right_shape) is ShapeLoopInitialAlternative: return operation_result_unknown onMissingOperation("Eq", self, right_shape) return operation_result_unknown class ShapeTypeNoneType(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = None @staticmethod def getTypeName(): return "NoneType" @staticmethod def hasShapeSlotHash(): return True @staticmethod def hasShapeTrustedAttributes(): return True add_shapes = add_shapes_none sub_shapes = sub_shapes_none mult_shapes = mult_shapes_none floordiv_shapes = floordiv_shapes_none truediv_shapes = truediv_shapes_none olddiv_shapes = olddiv_shapes_none mod_shapes = mod_shapes_none divmod_shapes = divmod_shapes_none pow_shapes = pow_shapes_none bitor_shapes = bitor_shapes_none bitand_shapes = bitand_shapes_none bitxor_shapes = bitxor_shapes_none lshift_shapes = lshift_shapes_none rshift_shapes = rshift_shapes_none matmult_shapes = matmult_shapes_none if python_version < 0x300: def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape.getTypeName() is not None: return operation_result_bool_noescape if right_shape in (tshape_int_or_long, tshape_str_or_unicode): return operation_result_bool_noescape return _getComparisonLtShapeGeneric(self, right_shape) else: def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape.getTypeName() is not None: return operation_result_unorderable_comparison return _getComparisonLtShapeGeneric(self, right_shape) def getComparisonEqShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape.getTypeName() is not None: return operation_result_bool_noescape return _getComparisonEqShapeGeneric(self, right_shape) def getComparisonNeqShape(self, right_shape): return self.getComparisonEqShape(right_shape) @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionNoEscape tshape_none = ShapeTypeNoneType() class ShapeTypeBool(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): typical_value = True @staticmethod def getTypeName(): return "bool" @staticmethod def getCType(): return CTypeNuitkaBoolEnum add_shapes = add_shapes_bool sub_shapes = sub_shapes_bool mult_shapes = mult_shapes_bool floordiv_shapes = floordiv_shapes_bool truediv_shapes = truediv_shapes_bool olddiv_shapes = olddiv_shapes_bool mod_shapes = mod_shapes_bool divmod_shapes = divmod_shapes_bool pow_shapes = pow_shapes_bool bitor_shapes = bitor_shapes_bool bitand_shapes = bitand_shapes_bool bitxor_shapes = bitxor_shapes_bool lshift_shapes = lshift_shapes_bool rshift_shapes = rshift_shapes_bool matmult_shapes = matmult_shapes_bool def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in ( tshape_int, tshape_long, tshape_int_or_long, tshape_bool, tshape_float, ): return operation_result_bool_noescape if right_shape is tshape_int_or_long_derived: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_bool = ShapeTypeBool() class ShapeTypeInt(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): typical_value = 7 @staticmethod def getTypeName(): return "int" helper_code = "INT" if python_version < 0x300 else "LONG" add_shapes = add_shapes_int sub_shapes = sub_shapes_int mult_shapes = mult_shapes_int floordiv_shapes = floordiv_shapes_int truediv_shapes = truediv_shapes_int olddiv_shapes = olddiv_shapes_int mod_shapes = mod_shapes_int divmod_shapes = divmod_shapes_int pow_shapes = pow_shapes_int bitor_shapes = bitor_shapes_int bitand_shapes = bitand_shapes_int bitxor_shapes = bitxor_shapes_int lshift_shapes = lshift_shapes_int rshift_shapes = rshift_shapes_int matmult_shapes = matmult_shapes_int def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in ( tshape_int, tshape_long, tshape_int_or_long, tshape_bool, tshape_float, ): return operation_result_bool_noescape if right_shape in ( tshape_long_derived, tshape_int_or_long_derived, tshape_float_derived, ): return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_int = ShapeTypeInt() if python_version < 0x300: class ShapeTypeLong(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): typical_value = long(7) # pylint: disable=I0021,undefined-variable @staticmethod def getTypeName(): return "long" helper_code = "LONG" if python_version < 0x300 else "INVALID" add_shapes = add_shapes_long sub_shapes = sub_shapes_long mult_shapes = mult_shapes_long floordiv_shapes = floordiv_shapes_long truediv_shapes = truediv_shapes_long olddiv_shapes = olddiv_shapes_long mod_shapes = mod_shapes_long divmod_shapes = divmod_shapes_long pow_shapes = pow_shapes_long bitor_shapes = bitor_shapes_long bitand_shapes = bitand_shapes_long bitxor_shapes = bitxor_shapes_long lshift_shapes = lshift_shapes_long rshift_shapes = rshift_shapes_long matmult_shapes = matmult_shapes_long def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in ( tshape_int, tshape_long, tshape_int_or_long, tshape_bool, tshape_float, ): return operation_result_bool_noescape if right_shape in (tshape_long_derived, tshape_int_or_long_derived): return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_long = ShapeTypeLong() class ShapeTypeLongDerived(ShapeTypeUnknown): @staticmethod def getTypeName(): return None tshape_long_derived = ShapeTypeLongDerived() class ShapeTypeIntOrLong(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): if isExperimental("nuitka_ilong"): @staticmethod def getCType(): return CTypeNuitkaIntOrLongStruct @staticmethod def emitAlternatives(emit): emit(tshape_int) emit(tshape_long) add_shapes = add_shapes_intorlong sub_shapes = sub_shapes_intorlong mult_shapes = mult_shapes_intorlong floordiv_shapes = floordiv_shapes_intorlong truediv_shapes = truediv_shapes_intorlong olddiv_shapes = olddiv_shapes_intorlong mod_shapes = mod_shapes_intorlong divmod_shapes = divmod_shapes_intorlong pow_shapes = pow_shapes_intorlong bitor_shapes = bitor_shapes_intorlong bitand_shapes = bitand_shapes_intorlong bitxor_shapes = bitxor_shapes_intorlong lshift_shapes = lshift_shapes_intorlong rshift_shapes = rshift_shapes_intorlong matmult_shapes = matmult_shapes_intorlong def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in ( tshape_int, tshape_long, tshape_int_or_long, tshape_bool, tshape_float, ): return operation_result_bool_noescape if right_shape is tshape_int_or_long_derived: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_int_or_long = ShapeTypeIntOrLong() else: tshape_long = None tshape_long_derived = None tshape_int_or_long = tshape_int # TODO: Make this Python2 only, and use ShapeTypeIntDerived for Python3 class ShapeTypeIntOrLongDerived(ShapeTypeUnknown): pass tshape_int_or_long_derived = ShapeTypeIntOrLongDerived() class ShapeTypeFloat(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): typical_value = 0.1 @staticmethod def getTypeName(): return "float" helper_code = "FLOAT" add_shapes = add_shapes_float sub_shapes = sub_shapes_float mult_shapes = mult_shapes_float floordiv_shapes = floordiv_shapes_float truediv_shapes = truediv_shapes_float olddiv_shapes = olddiv_shapes_float mod_shapes = mod_shapes_float divmod_shapes = divmod_shapes_float pow_shapes = pow_shapes_float bitor_shapes = bitor_shapes_float bitand_shapes = bitand_shapes_float bitxor_shapes = bitxor_shapes_float lshift_shapes = lshift_shapes_float rshift_shapes = rshift_shapes_float matmult_shapes = matmult_shapes_float def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in ( tshape_float, tshape_long, tshape_int, tshape_int_or_long, tshape_bool, ): return operation_result_bool_noescape if right_shape is tshape_float_derived: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_float = ShapeTypeFloat() class ShapeTypeFloatDerived(ShapeTypeUnknown): pass tshape_float_derived = ShapeTypeFloatDerived() class ShapeTypeComplex(ShapeNotContainerMixin, ShapeNumberMixin, ShapeBase): typical_value = 0j @staticmethod def getTypeName(): return "complex" add_shapes = add_shapes_complex sub_shapes = sub_shapes_complex mult_shapes = mult_shapes_complex floordiv_shapes = floordiv_shapes_complex truediv_shapes = truediv_shapes_complex olddiv_shapes = olddiv_shapes_complex mod_shapes = mod_shapes_complex divmod_shapes = divmod_shapes_complex pow_shapes = pow_shapes_complex bitor_shapes = bitor_shapes_complex bitand_shapes = bitand_shapes_complex bitxor_shapes = bitxor_shapes_complex lshift_shapes = lshift_shapes_complex rshift_shapes = rshift_shapes_complex matmult_shapes = matmult_shapes_complex tshape_complex = ShapeTypeComplex() class ShapeTypeTuple(ShapeContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = () @staticmethod def getTypeName(): return "tuple" helper_code = "TUPLE" @staticmethod def getShapeIter(): return tshape_tuple_iterator add_shapes = add_shapes_tuple sub_shapes = sub_shapes_tuple mult_shapes = mult_shapes_tuple floordiv_shapes = floordiv_shapes_tuple truediv_shapes = truediv_shapes_tuple olddiv_shapes = olddiv_shapes_tuple mod_shapes = mod_shapes_tuple divmod_shapes = divmod_shapes_tuple pow_shapes = pow_shapes_tuple bitor_shapes = bitor_shapes_tuple bitand_shapes = bitand_shapes_tuple bitxor_shapes = bitxor_shapes_tuple lshift_shapes = lshift_shapes_tuple rshift_shapes = rshift_shapes_tuple matmult_shapes = matmult_shapes_tuple def getComparisonLtShape(self, right_shape): # Need to consider value shape for this. return operation_result_unknown tshape_tuple = ShapeTypeTuple() class ShapeTypeNamedTuple(ShapeContainerMixin, ShapeNotNumberMixin, ShapeBase): @staticmethod def getTypeName(): return "namedtuple" helper_code = "NAMEDTUPLE" @staticmethod def getShapeIter(): return tshape_tuple_iterator # TODO: Unsupported operation would be different, account for that. add_shapes = add_shapes_tuple sub_shapes = sub_shapes_tuple mult_shapes = mult_shapes_tuple floordiv_shapes = floordiv_shapes_tuple truediv_shapes = truediv_shapes_tuple olddiv_shapes = olddiv_shapes_tuple mod_shapes = mod_shapes_tuple divmod_shapes = divmod_shapes_tuple pow_shapes = pow_shapes_tuple bitor_shapes = bitor_shapes_tuple bitand_shapes = bitand_shapes_tuple bitxor_shapes = bitxor_shapes_tuple lshift_shapes = lshift_shapes_tuple rshift_shapes = rshift_shapes_tuple matmult_shapes = matmult_shapes_tuple def getComparisonLtShape(self, right_shape): # Need to consider value shape for this. return operation_result_unknown tshape_namedtuple = ShapeTypeNamedTuple() class TypeShapeTupleIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_tuple.typical_value) @staticmethod def getTypeName(): return "tupleiterator" if python_version < 0x300 else "tuple_iterator" tshape_tuple_iterator = TypeShapeTupleIterator() class ShapeTypeList(ShapeContainerMutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = [] @staticmethod def getTypeName(): return "list" helper_code = "LIST" @staticmethod def getShapeIter(): return tshape_list_iterator add_shapes = add_shapes_list sub_shapes = sub_shapes_list mult_shapes = mult_shapes_list floordiv_shapes = floordiv_shapes_list truediv_shapes = truediv_shapes_list olddiv_shapes = olddiv_shapes_list mod_shapes = mod_shapes_list divmod_shapes = divmod_shapes_list pow_shapes = pow_shapes_list bitor_shapes = bitor_shapes_list bitand_shapes = bitand_shapes_list bitxor_shapes = bitxor_shapes_list lshift_shapes = lshift_shapes_list rshift_shapes = rshift_shapes_list matmult_shapes = matmult_shapes_list iadd_shapes = iadd_shapes_list def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown # Need to consider value shape for this. if right_shape in (tshape_list, tshape_tuple): return operation_result_bool_elementbased if right_shape is tshape_xrange: if python_version < 0x300: return operation_result_bool_elementbased else: # TODO: Actually unorderable, but this requires making a # difference with "==" return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_list = ShapeTypeList() class ShapeTypeListIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_list.typical_value) @staticmethod def getTypeName(): return "listiterator" if python_version < 0x300 else "list_iterator" tshape_list_iterator = ShapeTypeListIterator() class ShapeTypeSet(ShapeContainerMutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = set() @staticmethod def getTypeName(): return "set" @staticmethod def getShapeIter(): return tshape_set_iterator add_shapes = add_shapes_set sub_shapes = sub_shapes_set mult_shapes = mult_shapes_set floordiv_shapes = floordiv_shapes_set truediv_shapes = truediv_shapes_set olddiv_shapes = olddiv_shapes_set mod_shapes = mod_shapes_set divmod_shapes = divmod_shapes_set pow_shapes = pow_shapes_set bitor_shapes = bitor_shapes_set bitand_shapes = bitand_shapes_set bitxor_shapes = bitxor_shapes_set lshift_shapes = lshift_shapes_set rshift_shapes = rshift_shapes_set matmult_shapes = matmult_shapes_set def getComparisonLtShape(self, right_shape): # Need to consider value shape for this. return operation_result_unknown tshape_set = ShapeTypeSet() class ShapeTypeSetIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_set.typical_value) @staticmethod def getTypeName(): return "setiterator" if python_version < 0x300 else "set_iterator" tshape_set_iterator = ShapeTypeSetIterator() class ShapeTypeFrozenset(ShapeContainerImmutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = frozenset() @staticmethod def getTypeName(): return "frozenset" @staticmethod def getShapeIter(): return tshape_set_iterator add_shapes = add_shapes_frozenset sub_shapes = sub_shapes_frozenset mult_shapes = mult_shapes_frozenset floordiv_shapes = floordiv_shapes_frozenset truediv_shapes = truediv_shapes_frozenset olddiv_shapes = olddiv_shapes_frozenset mod_shapes = mod_shapes_frozenset divmod_shapes = divmod_shapes_frozenset pow_shapes = pow_shapes_frozenset bitor_shapes = bitor_shapes_frozenset bitand_shapes = bitand_shapes_frozenset bitxor_shapes = bitxor_shapes_frozenset lshift_shapes = lshift_shapes_frozenset rshift_shapes = rshift_shapes_frozenset matmult_shapes = matmult_shapes_frozenset tshape_frozenset = ShapeTypeFrozenset() class ShapeTypeDict(ShapeContainerMutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = {} @staticmethod def getTypeName(): return "dict" @staticmethod def getShapeIter(): return tshape_dict_iterator add_shapes = add_shapes_dict sub_shapes = sub_shapes_dict mult_shapes = mult_shapes_dict floordiv_shapes = floordiv_shapes_dict truediv_shapes = truediv_shapes_dict olddiv_shapes = olddiv_shapes_dict mod_shapes = mod_shapes_dict divmod_shapes = divmod_shapes_dict pow_shapes = pow_shapes_dict bitor_shapes = bitor_shapes_dict bitand_shapes = bitand_shapes_dict bitxor_shapes = bitxor_shapes_dict lshift_shapes = lshift_shapes_dict rshift_shapes = rshift_shapes_dict matmult_shapes = matmult_shapes_dict ibitor_shapes = ibitor_shapes_dict def getComparisonLtShape(self, right_shape): # Need to consider value shape for this # TODO: Could return bool with annotation that exception is still # possible.. return operation_result_unknown tshape_dict = ShapeTypeDict() class ShapeTypeDictIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_dict.typical_value) @staticmethod def getTypeName(): return ( "dictionary-keyiterator" if python_version < 0x300 else "dictkey_iterator" ) tshape_dict_iterator = ShapeTypeDictIterator() class ShapeTypeStr(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = "a" @staticmethod def getTypeName(): return "str" helper_code = "STR" if python_version < 0x300 else "UNICODE" # Not a container, but has these. @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotLen(): return True @staticmethod def hasShapeSlotContains(): return True # Not a number, but has these. @staticmethod def hasShapeSlotInt(): return True @staticmethod def hasShapeSlotLong(): return True @staticmethod def hasShapeSlotFloat(): return True @staticmethod def hasShapeSlotComplex(): return True @staticmethod def hasShapeSlotHash(): return True @staticmethod def getShapeIter(): return tshape_str_iterator @staticmethod def hasShapeTrustedAttributes(): return True add_shapes = add_shapes_str sub_shapes = sub_shapes_str mult_shapes = mult_shapes_str floordiv_shapes = floordiv_shapes_str truediv_shapes = truediv_shapes_str olddiv_shapes = olddiv_shapes_str mod_shapes = mod_shapes_str divmod_shapes = divmod_shapes_str pow_shapes = pow_shapes_str bitor_shapes = bitor_shapes_str bitand_shapes = bitand_shapes_str bitxor_shapes = bitxor_shapes_str lshift_shapes = lshift_shapes_str rshift_shapes = rshift_shapes_str matmult_shapes = matmult_shapes_str def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape is tshape_str: return operation_result_bool_noescape if right_shape is tshape_str_derived: return operation_result_unknown if right_shape is tshape_bytearray: if python_version < 0x300: return operation_result_bool_noescape else: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_str = ShapeTypeStr() class TypeShapeStrDerived(ShapeTypeUnknown): pass tshape_str_derived = TypeShapeStrDerived() class ShapeTypeStrIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): tyical_value = iter(tshape_str.typical_value) @staticmethod def getTypeName(): return "iterator" if python_version < 0x300 else "str_iterator" tshape_str_iterator = ShapeTypeStrIterator() if python_version < 0x300: class ShapeTypeUnicode(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = u"a" @staticmethod def getTypeName(): return "unicode" helper_code = "UNICODE" # Not a container, but has these. @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotLen(): return True @staticmethod def hasShapeSlotContains(): return True # Not a number, but has these. @staticmethod def hasShapeSlotInt(): return True @staticmethod def hasShapeSlotLong(): return True @staticmethod def hasShapeSlotFloat(): return True @staticmethod def hasShapeSlotComplex(): return True @staticmethod def hasShapeSlotHash(): return True @staticmethod def getShapeIter(): return tshape_unicode_iterator @staticmethod def hasShapeTrustedAttributes(): return True add_shapes = add_shapes_unicode sub_shapes = sub_shapes_unicode mult_shapes = mult_shapes_unicode floordiv_shapes = floordiv_shapes_unicode truediv_shapes = truediv_shapes_unicode olddiv_shapes = olddiv_shapes_unicode mod_shapes = mod_shapes_unicode divmod_shapes = divmod_shapes_unicode pow_shapes = pow_shapes_unicode bitor_shapes = bitor_shapes_unicode bitand_shapes = bitand_shapes_unicode bitxor_shapes = bitxor_shapes_unicode lshift_shapes = lshift_shapes_unicode rshift_shapes = rshift_shapes_unicode matmult_shapes = matmult_shapes_unicode def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape is tshape_unicode: return operation_result_bool_noescape if right_shape is tshape_unicode_derived: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_unicode = ShapeTypeUnicode() class ShapeTypeUnicodeDerived(ShapeTypeUnknown): pass tshape_unicode_derived = ShapeTypeUnicodeDerived() class ShapeTypeUnicodeIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_unicode.typical_value) @staticmethod def getTypeName(): return "iterator" tshape_unicode_iterator = ShapeTypeUnicodeIterator() else: tshape_unicode = tshape_str tshape_unicode_iterator = tshape_str_iterator tshape_unicode_derived = tshape_str_derived if python_version < 0x300: class ShapeTypeStrOrUnicode(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): @staticmethod def emitAlternatives(emit): emit(tshape_str) emit(tshape_unicode) @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotLen(): return True @staticmethod def hasShapeSlotContains(): return True @staticmethod def hasShapeSlotInt(): return True @staticmethod def hasShapeSlotLong(): return True @staticmethod def hasShapeSlotFloat(): return True @staticmethod def hasShapeSlotComplex(): return True @staticmethod def hasShapeSlotHash(): return True @staticmethod def hasShapeTrustedAttributes(): return True # TODO: There seem to be missing a few here. add_shapes = add_shapes_strorunicode sub_shapes = sub_shapes_strorunicode mult_shapes = mult_shapes_strorunicode bitor_shapes = bitor_shapes_strorunicode bitand_shapes = bitand_shapes_strorunicode bitxor_shapes = bitxor_shapes_strorunicode lshift_shapes = lshift_shapes_strorunicode rshift_shapes = rshift_shapes_strorunicode matmult_shapes = matmult_shapes_strorunicode tshape_str_or_unicode = ShapeTypeStrOrUnicode() class ShapeTypeStrOrUnicodeDerived(ShapeTypeUnknown): pass tshape_str_or_unicode_derived = ShapeTypeStrOrUnicodeDerived() else: tshape_str_or_unicode = tshape_str tshape_str_or_unicode_derived = tshape_str_derived if python_version >= 0x300: class ShapeTypeBytes(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = b"b" @staticmethod def getTypeName(): return "bytes" helper_code = "BYTES" # Not a container, but has these. @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotLen(): return True @staticmethod def hasShapeSlotContains(): return True # Not a number, but has these. @staticmethod def hasShapeSlotInt(): return True @staticmethod def hasShapeSlotLong(): return True @staticmethod def hasShapeSlotFloat(): return True @staticmethod def hasShapeSlotHash(): return True @staticmethod def getShapeIter(): return tshape_bytes_iterator @staticmethod def hasShapeTrustedAttributes(): return True add_shapes = add_shapes_bytes sub_shapes = sub_shapes_bytes mult_shapes = mult_shapes_bytes floordiv_shapes = floordiv_shapes_bytes truediv_shapes = truediv_shapes_bytes olddiv_shapes = olddiv_shapes_bytes mod_shapes = mod_shapes_bytes divmod_shapes = divmod_shapes_bytes pow_shapes = pow_shapes_bytes bitor_shapes = bitor_shapes_bytes bitand_shapes = bitand_shapes_bytes bitxor_shapes = bitxor_shapes_bytes lshift_shapes = lshift_shapes_bytes rshift_shapes = rshift_shapes_bytes matmult_shapes = matmult_shapes_bytes def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape is tshape_bytes: return operation_result_bool_noescape if right_shape is tshape_bytes_derived: return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_bytes = ShapeTypeBytes() class TypeShapeBytesDerived(ShapeTypeUnknown): pass tshape_bytes_derived = TypeShapeBytesDerived() class TypeShapeBytesIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_bytes.typical_value) @staticmethod def getTypeName(): return "bytes_iterator" tshape_bytes_iterator = TypeShapeBytesIterator() else: # Shouldn't happen with Python2 tshape_bytes = None tshape_bytes_iterator = None tshape_bytes_derived = None class ShapeTypeBytearray(ShapeContainerMutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = bytearray(b"b") @staticmethod def getTypeName(): return "bytearray" @staticmethod def getShapeIter(): return tshape_bytearray_iterator add_shapes = add_shapes_bytearray sub_shapes = sub_shapes_bytearray mult_shapes = mult_shapes_bytearray floordiv_shapes = floordiv_shapes_bytearray truediv_shapes = truediv_shapes_bytearray olddiv_shapes = olddiv_shapes_bytearray mod_shapes = mod_shapes_bytearray divmod_shapes = divmod_shapes_bytearray pow_shapes = pow_shapes_bytearray bitor_shapes = bitor_shapes_bytearray bitand_shapes = bitand_shapes_bytearray bitxor_shapes = bitxor_shapes_bytearray lshift_shapes = lshift_shapes_bytearray rshift_shapes = rshift_shapes_bytearray matmult_shapes = matmult_shapes_bytearray def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape in (tshape_bytearray, tshape_bytes): return operation_result_bool_noescape if right_shape is tshape_str: if python_version < 0x300: return operation_result_bool_noescape else: # TODO: Exception actually for static optimization. return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_bytearray = ShapeTypeBytearray() class ShapeTypeBytearrayIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_bytearray.typical_value) @staticmethod def getTypeName(): return "bytearray_iterator" tshape_bytearray_iterator = ShapeTypeBytearrayIterator() class ShapeTypeEllipsis(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = Ellipsis @staticmethod def getTypeName(): return "ellipsis" @staticmethod def hasShapeSlotHash(): return True tshape_ellipsis = ShapeTypeEllipsis() class ShapeTypeSlice(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = slice(7) @staticmethod def getTypeName(): return "slice" @staticmethod def hasShapeSlotHash(): return False tshape_slice = ShapeTypeSlice() class ShapeTypeXrange(ShapeContainerImmutableMixin, ShapeNotNumberMixin, ShapeBase): typical_value = ( xrange(1) # pylint: disable=I0021,undefined-variable if python_version < 0x300 else range(1) ) @staticmethod def getTypeName(): return "xrange" if python_version < 0x300 else "range" @staticmethod def getShapeIter(): return tshape_xrange_iterator def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown # TODO: Maybe split in two shapes, they are quite different in the # end when it comes to operations. if python_version < 0x300: # Need to consider value shape for this. if right_shape in (tshape_list, tshape_tuple): return operation_result_bool_elementbased if right_shape is tshape_xrange: # TODO: This is value escaping, but that doesn't really apply return operation_result_bool_elementbased else: # TODO: Actually unorderable, but this requires making a # difference with "==" return operation_result_unknown return _getComparisonLtShapeGeneric(self, right_shape) tshape_xrange = ShapeTypeXrange() class ShapeTypeXrangeIterator(ShapeIteratorMixin, ShapeNotNumberMixin, ShapeBase): typical_value = iter(tshape_xrange.typical_value) @staticmethod def getTypeName(): return "rangeiterator" if python_version < 0x300 else "range_iterator" tshape_xrange_iterator = ShapeTypeXrangeIterator() class ShapeTypeType(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = int @staticmethod def getTypeName(): return "type" @staticmethod def hasShapeSlotHash(): return True def getComparisonLtShape(self, right_shape): if right_shape is tshape_unknown: return operation_result_unknown if right_shape is tshape_type: return tshape_unknown, ControlFlowDescriptionNoEscape return _getComparisonLtShapeGeneric(self, right_shape) tshape_type = ShapeTypeType() class ShapeTypeModule(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): typical_value = __import__("sys") @staticmethod def getTypeName(): return "module" @staticmethod def hasShapeModule(): return True @staticmethod def hasShapeSlotHash(): return True tshape_module = ShapeTypeModule() class ShapeTypeFunction(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): # TODO: Add typical value. @staticmethod def getTypeName(): return "function" @staticmethod def hasShapeSlotHash(): return True tshape_function = ShapeTypeFunction() class ShapeTypeBuiltinModule(ShapeTypeModule): typical_value = __import__("_ctypes") tshape_module_builtin = ShapeTypeBuiltinModule() class ShapeTypeFile(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): # TODO: That need not really be a file, find something better. typical_value = __import__("sys").stdout @staticmethod def getTypeName(): return "file" # Files are self-iterators. @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotNext(): return True @staticmethod def hasShapeSlotContains(): return True @staticmethod def hasShapeSlotHash(): return True tshape_file = ShapeTypeFile() class ShapeTypeStaticmethod(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): # TODO: Add typical value. @staticmethod def getTypeName(): return "staticmethod" # TODO: These probably reject all kinds of operations. tshape_staticmethod = ShapeTypeStaticmethod() class ShapeTypeClassmethod(ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase): # TODO: Add typical value. @staticmethod def getTypeName(): return "classmethod" # TODO: These probably reject all kinds of operations. tshape_classmethod = ShapeTypeClassmethod() # Precanned tuples to save creating return value tuples: operation_result_bool_noescape = tshape_bool, ControlFlowDescriptionNoEscape operation_result_float_noescape = tshape_float, ControlFlowDescriptionNoEscape operation_result_int_noescape = tshape_int, ControlFlowDescriptionNoEscape operation_result_long_noescape = tshape_long, ControlFlowDescriptionNoEscape operation_result_intorlong_noescape = tshape_int_or_long, ControlFlowDescriptionNoEscape operation_result_complex_noescape = tshape_complex, ControlFlowDescriptionNoEscape operation_result_tuple_noescape = tshape_tuple, ControlFlowDescriptionNoEscape operation_result_list_noescape = tshape_list, ControlFlowDescriptionNoEscape operation_result_set_noescape = tshape_set, ControlFlowDescriptionNoEscape operation_result_frozenset_noescape = tshape_frozenset, ControlFlowDescriptionNoEscape operation_result_str_noescape = tshape_str, ControlFlowDescriptionNoEscape operation_result_unicode_noescape = tshape_unicode, ControlFlowDescriptionNoEscape operation_result_strorunicode_noescape = ( tshape_str_or_unicode, ControlFlowDescriptionNoEscape, ) operation_result_bytes_noescape = tshape_bytes, ControlFlowDescriptionNoEscape operation_result_bytearray_noescape = tshape_bytearray, ControlFlowDescriptionNoEscape operation_result_dict_noescape = tshape_dict, ControlFlowDescriptionNoEscape operation_result_dict_valueerror = tshape_dict, ControlFlowDescriptionValueErrorNoEscape operation_result_bool_elementbased = ( tshape_bool, ControlFlowDescriptionElementBasedEscape, ) operation_result_unorderable_comparison = ( tshape_unknown, ControlFlowDescriptionComparisonUnorderable, ) operation_result_unsupported_add = tshape_unknown, ControlFlowDescriptionAddUnsupported operation_result_unsupported_sub = tshape_unknown, ControlFlowDescriptionSubUnsupported operation_result_unsupported_mul = tshape_unknown, ControlFlowDescriptionMulUnsupported operation_result_unsupported_floordiv = ( tshape_unknown, ControlFlowDescriptionFloorDivUnsupported, ) operation_result_unsupported_truediv = ( tshape_unknown, ControlFlowDescriptionTrueDivUnsupported, ) operation_result_unsupported_olddiv = ( tshape_unknown, ControlFlowDescriptionOldDivUnsupported, ) operation_result_unsupported_mod = tshape_unknown, ControlFlowDescriptionModUnsupported operation_result_unsupported_divmod = ( tshape_unknown, ControlFlowDescriptionDivmodUnsupported, ) operation_result_unsupported_pow = tshape_unknown, ControlFlowDescriptionPowUnsupported operation_result_unsupported_bitor = ( tshape_unknown, ControlFlowDescriptionBitorUnsupported, ) operation_result_unsupported_bitand = ( tshape_unknown, ControlFlowDescriptionBitandUnsupported, ) operation_result_unsupported_bitxor = ( tshape_unknown, ControlFlowDescriptionBitxorUnsupported, ) operation_result_unsupported_lshift = ( tshape_unknown, ControlFlowDescriptionLshiftUnsupported, ) operation_result_unsupported_rshift = ( tshape_unknown, ControlFlowDescriptionRshiftUnsupported, ) operation_result_unsupported_matmult = ( tshape_unknown, ControlFlowDescriptionMatmultUnsupported, ) # ZeroDivisionError can occur for some module and division operations, otherwise they # are fixed type. operation_result_zerodiv_int = tshape_int, ControlFlowDescriptionZeroDivisionNoEscape operation_result_zerodiv_long = ( tshape_long, ControlFlowDescriptionZeroDivisionNoEscape, ) operation_result_zerodiv_intorlong = ( tshape_int_or_long, ControlFlowDescriptionZeroDivisionNoEscape, ) operation_result_zerodiv_float = ( tshape_float, ControlFlowDescriptionZeroDivisionNoEscape, ) operation_result_zerodiv_complex = ( tshape_complex, ControlFlowDescriptionZeroDivisionNoEscape, ) operation_result_zerodiv_tuple = ( tshape_tuple, ControlFlowDescriptionZeroDivisionNoEscape, ) operation_result_valueerror_intorlong = ( tshape_int_or_long, ControlFlowDescriptionValueErrorNoEscape, ) operation_result_valueerror_long = ( tshape_long, ControlFlowDescriptionValueErrorNoEscape, ) # Format operations can do many things. operation_result_str_formaterror = (tshape_str, ControlFlowDescriptionFormatError) operation_result_unicode_formaterror = ( tshape_unicode, ControlFlowDescriptionFormatError, ) operation_result_bytes_formaterror = (tshape_bytes, ControlFlowDescriptionFormatError) operation_result_bytearray_formaterror = ( tshape_bytearray, ControlFlowDescriptionFormatError, ) # Precanned values, reject everything. def _rejectEverything(shapes, operation_unsupported): shapes.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # None really hates everything concrete for all operations. tshape_int: operation_unsupported, tshape_long: operation_unsupported, tshape_int_or_long: operation_unsupported, tshape_bool: operation_unsupported, tshape_long: operation_unsupported, tshape_float: operation_unsupported, tshape_complex: operation_unsupported, # Sequence repeat: tshape_str: operation_unsupported, tshape_bytes: operation_unsupported, tshape_bytearray: operation_unsupported, tshape_unicode: operation_unsupported, tshape_tuple: operation_unsupported, tshape_list: operation_unsupported, # Unsupported: tshape_set: operation_unsupported, tshape_frozenset: operation_unsupported, tshape_dict: operation_unsupported, tshape_type: operation_unsupported, tshape_none: operation_unsupported, } ) _rejectEverything(add_shapes_none, operation_result_unsupported_add) _rejectEverything(sub_shapes_none, operation_result_unsupported_sub) _rejectEverything(mult_shapes_none, operation_result_unsupported_mul) _rejectEverything(floordiv_shapes_none, operation_result_unsupported_floordiv) _rejectEverything(truediv_shapes_none, operation_result_unsupported_truediv) _rejectEverything(olddiv_shapes_none, operation_result_unsupported_olddiv) _rejectEverything(mod_shapes_none, operation_result_unsupported_mod) _rejectEverything(divmod_shapes_none, operation_result_unsupported_divmod) _rejectEverything(pow_shapes_none, operation_result_unsupported_pow) _rejectEverything(bitor_shapes_none, operation_result_unsupported_bitor) _rejectEverything(bitand_shapes_none, operation_result_unsupported_bitand) _rejectEverything(bitxor_shapes_none, operation_result_unsupported_bitxor) _rejectEverything(lshift_shapes_none, operation_result_unsupported_lshift) _rejectEverything(rshift_shapes_none, operation_result_unsupported_rshift) _rejectEverything(matmult_shapes_none, operation_result_unsupported_rshift) def cloneWithUnsupportedChange(op_shapes, operation_result_unsupported): r = {} for key, value in op_shapes.items(): if value[1].getExceptionExit() is TypeError: value = operation_result_unsupported r[key] = value return r add_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_intorlong_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_int_noescape, tshape_long: operation_result_long_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_bool.update( cloneWithUnsupportedChange(add_shapes_bool, operation_result_unsupported_sub) ) mult_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_int_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_int_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_str_noescape, tshape_bytes: operation_result_bytes_noescape, tshape_bytearray: operation_result_bytearray_noescape, tshape_unicode: operation_result_unicode_noescape, tshape_tuple: operation_result_tuple_noescape, tshape_list: operation_result_list_noescape, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) floordiv_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Ints do math tshape_int: operation_result_zerodiv_int, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_floordiv, tshape_bytes: operation_result_unsupported_floordiv, tshape_bytearray: operation_result_unsupported_floordiv, tshape_unicode: operation_result_unsupported_floordiv, tshape_tuple: operation_result_unsupported_floordiv, tshape_list: operation_result_unsupported_floordiv, tshape_set: operation_result_unsupported_floordiv, tshape_frozenset: operation_result_unsupported_floordiv, tshape_dict: operation_result_unsupported_floordiv, tshape_type: operation_result_unsupported_floordiv, tshape_none: operation_result_unsupported_floordiv, } ) truediv_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Bool act mostly like 0 or 1 int. tshape_int: operation_result_zerodiv_float, tshape_long: operation_result_zerodiv_float, tshape_int_or_long: operation_result_zerodiv_float, tshape_bool: operation_result_zerodiv_float, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_truediv, tshape_bytes: operation_result_unsupported_truediv, tshape_bytearray: operation_result_unsupported_truediv, tshape_unicode: operation_result_unsupported_truediv, tshape_tuple: operation_result_unsupported_truediv, tshape_list: operation_result_unsupported_truediv, tshape_set: operation_result_unsupported_truediv, tshape_frozenset: operation_result_unsupported_truediv, tshape_dict: operation_result_unsupported_truediv, tshape_type: operation_result_unsupported_truediv, tshape_none: operation_result_unsupported_truediv, } ) olddiv_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Bool act mostly like 0 or 1 int. tshape_int: operation_result_zerodiv_int, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_olddiv, tshape_bytes: operation_result_unsupported_olddiv, tshape_bytearray: operation_result_unsupported_olddiv, tshape_unicode: operation_result_unsupported_olddiv, tshape_tuple: operation_result_unsupported_olddiv, tshape_list: operation_result_unsupported_olddiv, tshape_set: operation_result_unsupported_olddiv, tshape_dict: operation_result_unsupported_olddiv, tshape_type: operation_result_unsupported_olddiv, tshape_none: operation_result_unsupported_olddiv, } ) mod_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_zerodiv_int, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex if python_version < 0x300 else operation_result_unsupported_mod, # Unsupported: tshape_str: operation_result_unsupported_mod, tshape_bytes: operation_result_unsupported_mod, tshape_bytearray: operation_result_unsupported_mod, tshape_unicode: operation_result_unsupported_mod, tshape_tuple: operation_result_unsupported_mod, tshape_list: operation_result_unsupported_mod, tshape_set: operation_result_unsupported_mod, tshape_frozenset: operation_result_unsupported_mod, tshape_dict: operation_result_unsupported_mod, tshape_type: operation_result_unsupported_mod, tshape_none: operation_result_unsupported_mod, } ) divmod_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Divmod makes tuples of 2 elements tshape_int: operation_result_zerodiv_tuple, tshape_long: operation_result_zerodiv_tuple, tshape_int_or_long: operation_result_zerodiv_tuple, tshape_bool: operation_result_zerodiv_tuple, tshape_float: operation_result_zerodiv_tuple, tshape_complex: operation_result_zerodiv_tuple, # Unsupported: tshape_str: operation_result_unsupported_divmod, tshape_bytes: operation_result_unsupported_divmod, tshape_bytearray: operation_result_unsupported_divmod, tshape_unicode: operation_result_unsupported_divmod, tshape_tuple: operation_result_unsupported_divmod, tshape_list: operation_result_unsupported_divmod, tshape_set: operation_result_unsupported_divmod, tshape_frozenset: operation_result_unsupported_divmod, tshape_dict: operation_result_unsupported_divmod, tshape_type: operation_result_unsupported_divmod, tshape_none: operation_result_unsupported_divmod, } ) pow_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_unknown, # TODO: operation_result_zerodiv_intorfloat, tshape_long: operation_result_unknown, # TODO: operation_result_zerodiv_longorfloat, tshape_int_or_long: operation_result_unknown, # TODO: operation_result_izerodiv_ntorlongorfloat, tshape_bool: operation_result_int_noescape, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_pow, tshape_bytes: operation_result_unsupported_pow, tshape_bytearray: operation_result_unsupported_pow, tshape_unicode: operation_result_unsupported_pow, tshape_tuple: operation_result_unsupported_pow, tshape_list: operation_result_unsupported_pow, tshape_set: operation_result_unsupported_pow, tshape_frozenset: operation_result_unsupported_pow, tshape_dict: operation_result_unsupported_pow, tshape_type: operation_result_unsupported_pow, tshape_none: operation_result_unsupported_pow, } ) bitor_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_int_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_bool_noescape, # Unsupported: tshape_float: operation_result_unsupported_bitor, tshape_complex: operation_result_unsupported_bitor, tshape_str: operation_result_unsupported_bitor, tshape_bytes: operation_result_unsupported_bitor, tshape_bytearray: operation_result_unsupported_bitor, tshape_unicode: operation_result_unsupported_bitor, tshape_tuple: operation_result_unsupported_bitor, tshape_list: operation_result_unsupported_bitor, tshape_set: operation_result_unsupported_bitor, tshape_frozenset: operation_result_unsupported_bitor, tshape_dict: operation_result_unsupported_bitor, tshape_type: operation_result_unsupported_bitor, tshape_none: operation_result_unsupported_bitor, } ) bitand_shapes_bool.update( cloneWithUnsupportedChange(bitor_shapes_bool, operation_result_unsupported_bitand) ) bitxor_shapes_bool.update( cloneWithUnsupportedChange(bitor_shapes_bool, operation_result_unsupported_bitand) ) lshift_shapes_bool.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_valueerror_intorlong, tshape_long: operation_result_valueerror_long, tshape_int_or_long: operation_result_valueerror_intorlong, tshape_bool: operation_result_valueerror_intorlong, # Unsupported: tshape_float: operation_result_unsupported_lshift, tshape_complex: operation_result_unsupported_lshift, tshape_str: operation_result_unsupported_lshift, tshape_bytes: operation_result_unsupported_lshift, tshape_bytearray: operation_result_unsupported_lshift, tshape_unicode: operation_result_unsupported_lshift, tshape_tuple: operation_result_unsupported_lshift, tshape_list: operation_result_unsupported_lshift, tshape_set: operation_result_unsupported_lshift, tshape_frozenset: operation_result_unsupported_lshift, tshape_dict: operation_result_unsupported_lshift, tshape_type: operation_result_unsupported_lshift, tshape_none: operation_result_unsupported_lshift, } ) rshift_shapes_bool.update( cloneWithUnsupportedChange(lshift_shapes_bool, operation_result_unsupported_rshift) ) add_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_intorlong_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_intorlong_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Unsupported: tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_int.update( cloneWithUnsupportedChange(add_shapes_int, operation_result_unsupported_sub) ) mult_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_intorlong_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_int_noescape, # cannot overflow tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_str_noescape, tshape_bytes: operation_result_bytes_noescape, tshape_bytearray: operation_result_bytearray_noescape, tshape_unicode: operation_result_unicode_noescape, tshape_tuple: operation_result_tuple_noescape, tshape_list: operation_result_list_noescape, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) floordiv_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math ops tshape_int: operation_result_zerodiv_intorlong, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_floordiv, tshape_bytes: operation_result_unsupported_floordiv, tshape_bytearray: operation_result_unsupported_floordiv, tshape_unicode: operation_result_unsupported_floordiv, tshape_tuple: operation_result_unsupported_floordiv, tshape_list: operation_result_unsupported_floordiv, tshape_set: operation_result_unsupported_floordiv, tshape_frozenset: operation_result_unsupported_floordiv, tshape_dict: operation_result_unsupported_floordiv, tshape_type: operation_result_unsupported_floordiv, tshape_none: operation_result_unsupported_floordiv, } ) truediv_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math ops tshape_int: operation_result_zerodiv_float, tshape_long: operation_result_zerodiv_float, tshape_int_or_long: operation_result_zerodiv_float, tshape_bool: operation_result_zerodiv_float, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_truediv, tshape_bytes: operation_result_unsupported_truediv, tshape_bytearray: operation_result_unsupported_truediv, tshape_unicode: operation_result_unsupported_truediv, tshape_tuple: operation_result_unsupported_truediv, tshape_list: operation_result_unsupported_truediv, tshape_set: operation_result_unsupported_truediv, tshape_frozenset: operation_result_unsupported_truediv, tshape_dict: operation_result_unsupported_truediv, tshape_type: operation_result_unsupported_truediv, tshape_none: operation_result_unsupported_truediv, } ) olddiv_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math tshape_int: operation_result_zerodiv_intorlong, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_olddiv, tshape_bytes: operation_result_unsupported_olddiv, tshape_bytearray: operation_result_unsupported_olddiv, tshape_unicode: operation_result_unsupported_olddiv, tshape_tuple: operation_result_unsupported_olddiv, tshape_list: operation_result_unsupported_olddiv, tshape_set: operation_result_unsupported_olddiv, tshape_dict: operation_result_unsupported_olddiv, tshape_type: operation_result_unsupported_olddiv, tshape_none: operation_result_unsupported_olddiv, } ) mod_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math tshape_int: operation_result_zerodiv_intorlong, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_intorlong, tshape_bool: operation_result_zerodiv_int, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex if python_version < 0x300 else operation_result_unsupported_mod, # Unsupported: tshape_str: operation_result_unsupported_mod, tshape_bytes: operation_result_unsupported_mod, tshape_bytearray: operation_result_unsupported_mod, tshape_unicode: operation_result_unsupported_mod, tshape_tuple: operation_result_unsupported_mod, tshape_list: operation_result_unsupported_mod, tshape_set: operation_result_unsupported_mod, tshape_frozenset: operation_result_unsupported_mod, tshape_dict: operation_result_unsupported_mod, tshape_type: operation_result_unsupported_mod, tshape_none: operation_result_unsupported_mod, } ) pow_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_unknown, # TODO: operation_result_intorlongorfloat, tshape_long: operation_result_unknown, # TODO: operation_result_longorfloat, tshape_int_or_long: operation_result_unknown, # TODO: operation_result_intorlongorfloat, tshape_bool: operation_result_int_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Unsupported: tshape_str: operation_result_unsupported_pow, tshape_bytes: operation_result_unsupported_pow, tshape_bytearray: operation_result_unsupported_pow, tshape_unicode: operation_result_unsupported_pow, tshape_tuple: operation_result_unsupported_pow, tshape_list: operation_result_unsupported_pow, tshape_set: operation_result_unsupported_pow, tshape_frozenset: operation_result_unsupported_pow, tshape_dict: operation_result_unsupported_pow, tshape_type: operation_result_unsupported_pow, tshape_none: operation_result_unsupported_pow, } ) bitor_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_int_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_intorlong_noescape, tshape_bool: operation_result_int_noescape, # Unsupported: tshape_float: operation_result_unsupported_bitor, tshape_complex: operation_result_unsupported_bitor, tshape_str: operation_result_unsupported_bitor, tshape_bytes: operation_result_unsupported_bitor, tshape_bytearray: operation_result_unsupported_bitor, tshape_unicode: operation_result_unsupported_bitor, tshape_tuple: operation_result_unsupported_bitor, tshape_list: operation_result_unsupported_bitor, tshape_set: operation_result_unsupported_bitor, tshape_frozenset: operation_result_unsupported_bitor, tshape_dict: operation_result_unsupported_bitor, tshape_type: operation_result_unsupported_bitor, tshape_none: operation_result_unsupported_bitor, } ) bitand_shapes_int.update( cloneWithUnsupportedChange(bitor_shapes_int, operation_result_unsupported_bitand) ) bitxor_shapes_int.update( cloneWithUnsupportedChange(bitor_shapes_int, operation_result_unsupported_bitand) ) lshift_shapes_int.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_valueerror_intorlong, tshape_long: operation_result_valueerror_long, tshape_int_or_long: operation_result_valueerror_intorlong, tshape_bool: operation_result_valueerror_intorlong, # Unsupported: tshape_float: operation_result_unsupported_lshift, tshape_complex: operation_result_unsupported_lshift, tshape_str: operation_result_unsupported_lshift, tshape_bytes: operation_result_unsupported_lshift, tshape_bytearray: operation_result_unsupported_lshift, tshape_unicode: operation_result_unsupported_lshift, tshape_tuple: operation_result_unsupported_lshift, tshape_list: operation_result_unsupported_lshift, tshape_set: operation_result_unsupported_lshift, tshape_frozenset: operation_result_unsupported_lshift, tshape_dict: operation_result_unsupported_lshift, tshape_type: operation_result_unsupported_lshift, tshape_none: operation_result_unsupported_lshift, } ) rshift_shapes_int.update( cloneWithUnsupportedChange(lshift_shapes_int, operation_result_unsupported_rshift) ) add_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_long_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_long_noescape, tshape_bool: operation_result_long_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_long_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_long_noescape, tshape_bool: operation_result_long_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_unsupported_sub, tshape_bytes: operation_result_unsupported_sub, tshape_bytearray: operation_result_unsupported_sub, tshape_unicode: operation_result_unsupported_sub, tshape_tuple: operation_result_unsupported_sub, tshape_list: operation_result_unsupported_sub, # Unsupported: tshape_set: operation_result_unsupported_sub, tshape_frozenset: operation_result_unsupported_sub, tshape_dict: operation_result_unsupported_sub, tshape_type: operation_result_unsupported_sub, tshape_none: operation_result_unsupported_sub, } ) mult_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_long_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_long_noescape, tshape_bool: operation_result_long_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat: tshape_str: operation_result_str_noescape, tshape_bytes: operation_result_bytes_noescape, tshape_bytearray: operation_result_bytearray_noescape, tshape_unicode: operation_result_unicode_noescape, tshape_tuple: operation_result_tuple_noescape, tshape_list: operation_result_list_noescape, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) floordiv_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math ops tshape_int: operation_result_zerodiv_long, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_long, tshape_bool: operation_result_zerodiv_long, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_floordiv, tshape_bytes: operation_result_unsupported_floordiv, tshape_bytearray: operation_result_unsupported_floordiv, tshape_unicode: operation_result_unsupported_floordiv, tshape_tuple: operation_result_unsupported_floordiv, tshape_list: operation_result_unsupported_floordiv, tshape_set: operation_result_unsupported_floordiv, tshape_frozenset: operation_result_unsupported_floordiv, tshape_dict: operation_result_unsupported_floordiv, tshape_type: operation_result_unsupported_floordiv, tshape_none: operation_result_unsupported_floordiv, } ) olddiv_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math tshape_int: operation_result_zerodiv_long, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_long, tshape_bool: operation_result_zerodiv_long, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_olddiv, tshape_bytes: operation_result_unsupported_olddiv, tshape_bytearray: operation_result_unsupported_olddiv, tshape_unicode: operation_result_unsupported_olddiv, tshape_tuple: operation_result_unsupported_olddiv, tshape_list: operation_result_unsupported_olddiv, tshape_set: operation_result_unsupported_olddiv, tshape_dict: operation_result_unsupported_olddiv, tshape_type: operation_result_unsupported_olddiv, tshape_none: operation_result_unsupported_olddiv, } ) mod_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # ints do math tshape_int: operation_result_zerodiv_long, tshape_long: operation_result_zerodiv_long, tshape_int_or_long: operation_result_zerodiv_long, tshape_bool: operation_result_zerodiv_long, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex if python_version < 0x300 else operation_result_unsupported_mod, # Unsupported: tshape_str: operation_result_unsupported_mod, tshape_bytes: operation_result_unsupported_mod, tshape_bytearray: operation_result_unsupported_mod, tshape_unicode: operation_result_unsupported_mod, tshape_tuple: operation_result_unsupported_mod, tshape_list: operation_result_unsupported_mod, tshape_set: operation_result_unsupported_mod, tshape_frozenset: operation_result_unsupported_mod, tshape_dict: operation_result_unsupported_mod, tshape_type: operation_result_unsupported_mod, tshape_none: operation_result_unsupported_mod, } ) pow_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_unknown, # TODO: operation_result_intorlongorfloat, tshape_long: operation_result_unknown, # TODO: operation_result_longorfloat, tshape_int_or_long: operation_result_unknown, # TODO: operation_result_intorlongorfloat, tshape_bool: operation_result_long_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Unsupported: tshape_str: operation_result_unsupported_pow, tshape_bytes: operation_result_unsupported_pow, tshape_bytearray: operation_result_unsupported_pow, tshape_unicode: operation_result_unsupported_pow, tshape_tuple: operation_result_unsupported_pow, tshape_list: operation_result_unsupported_pow, tshape_set: operation_result_unsupported_pow, tshape_frozenset: operation_result_unsupported_pow, tshape_dict: operation_result_unsupported_pow, tshape_type: operation_result_unsupported_pow, tshape_none: operation_result_unsupported_pow, } ) bitor_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Long keep their type tshape_int: operation_result_long_noescape, tshape_long: operation_result_long_noescape, tshape_int_or_long: operation_result_long_noescape, tshape_bool: operation_result_long_noescape, # Unsupported: tshape_float: operation_result_unsupported_bitor, tshape_complex: operation_result_unsupported_bitor, tshape_str: operation_result_unsupported_bitor, tshape_bytes: operation_result_unsupported_bitor, tshape_bytearray: operation_result_unsupported_bitor, tshape_unicode: operation_result_unsupported_bitor, tshape_tuple: operation_result_unsupported_bitor, tshape_list: operation_result_unsupported_bitor, tshape_set: operation_result_unsupported_bitor, tshape_frozenset: operation_result_unsupported_bitor, tshape_dict: operation_result_unsupported_bitor, tshape_type: operation_result_unsupported_bitor, tshape_none: operation_result_unsupported_bitor, } ) bitand_shapes_long.update( cloneWithUnsupportedChange(bitor_shapes_long, operation_result_unsupported_bitand) ) bitxor_shapes_long.update( cloneWithUnsupportedChange(bitor_shapes_long, operation_result_unsupported_bitand) ) lshift_shapes_long.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Long keep their type, as bool is 0 or 1 int. tshape_int: operation_result_valueerror_long, tshape_long: operation_result_valueerror_long, tshape_int_or_long: operation_result_valueerror_long, tshape_bool: operation_result_valueerror_long, # Unsupported: tshape_float: operation_result_unsupported_lshift, tshape_complex: operation_result_unsupported_lshift, tshape_str: operation_result_unsupported_lshift, tshape_bytes: operation_result_unsupported_lshift, tshape_bytearray: operation_result_unsupported_lshift, tshape_unicode: operation_result_unsupported_lshift, tshape_tuple: operation_result_unsupported_lshift, tshape_list: operation_result_unsupported_lshift, tshape_set: operation_result_unsupported_lshift, tshape_frozenset: operation_result_unsupported_lshift, tshape_dict: operation_result_unsupported_lshift, tshape_type: operation_result_unsupported_lshift, tshape_none: operation_result_unsupported_lshift, } ) rshift_shapes_long.update( cloneWithUnsupportedChange(lshift_shapes_long, operation_result_unsupported_rshift) ) def mergeIntOrLong(op_shapes_int, op_shapes_long): r = {} for key, value in op_shapes_int.items(): value2 = op_shapes_long[key] if value is value2: r[key] = value elif value[0] is tshape_int_or_long and value2[0] is tshape_long: assert value[1] is value2[1] r[key] = value elif value[0] is tshape_int and value2[0] is tshape_long: assert value[1] is value2[1] if value[1] is operation_result_intorlong_noescape[1]: r[key] = operation_result_intorlong_noescape elif value[1] is operation_result_zerodiv_intorlong[1]: r[key] = operation_result_zerodiv_intorlong else: assert False else: assert False, (key, "->", value, "!=", value2) return r add_shapes_intorlong.update(mergeIntOrLong(add_shapes_int, add_shapes_long)) sub_shapes_intorlong.update(mergeIntOrLong(sub_shapes_int, sub_shapes_long)) mult_shapes_intorlong.update(mergeIntOrLong(mult_shapes_int, mult_shapes_long)) floordiv_shapes_intorlong.update( mergeIntOrLong(floordiv_shapes_int, floordiv_shapes_long) ) truediv_shapes_intorlong.update(mergeIntOrLong(truediv_shapes_int, truediv_shapes_long)) olddiv_shapes_intorlong.update(mergeIntOrLong(olddiv_shapes_int, olddiv_shapes_long)) mod_shapes_intorlong.update(mergeIntOrLong(mod_shapes_int, mod_shapes_long)) divmod_shapes_intorlong.update(mergeIntOrLong(divmod_shapes_int, divmod_shapes_long)) pow_shapes_intorlong.update(mergeIntOrLong(pow_shapes_int, pow_shapes_long)) lshift_shapes_intorlong.update(mergeIntOrLong(lshift_shapes_int, lshift_shapes_long)) rshift_shapes_intorlong.update(mergeIntOrLong(rshift_shapes_int, rshift_shapes_long)) bitor_shapes_intorlong.update(mergeIntOrLong(bitor_shapes_int, bitor_shapes_long)) bitand_shapes_intorlong.update(mergeIntOrLong(bitand_shapes_int, bitand_shapes_long)) bitxor_shapes_intorlong.update(mergeIntOrLong(bitxor_shapes_int, bitxor_shapes_long)) add_shapes_float.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_float_noescape, tshape_long: operation_result_float_noescape, tshape_int_or_long: operation_result_float_noescape, tshape_bool: operation_result_float_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_float.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_float_noescape, tshape_long: operation_result_float_noescape, tshape_int_or_long: operation_result_float_noescape, tshape_bool: operation_result_float_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_sub, tshape_bytes: operation_result_unsupported_sub, tshape_bytearray: operation_result_unsupported_sub, tshape_unicode: operation_result_unsupported_sub, tshape_tuple: operation_result_unsupported_sub, tshape_list: operation_result_unsupported_sub, # Unsupported: tshape_set: operation_result_unsupported_sub, tshape_frozenset: operation_result_unsupported_sub, tshape_dict: operation_result_unsupported_sub, tshape_type: operation_result_unsupported_sub, tshape_none: operation_result_unsupported_sub, } ) mult_shapes_float.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_float_noescape, tshape_long: operation_result_float_noescape, tshape_int_or_long: operation_result_float_noescape, tshape_bool: operation_result_float_noescape, tshape_float: operation_result_float_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) floordiv_shapes_float.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # floats do math ops tshape_int: operation_result_zerodiv_float, tshape_long: operation_result_zerodiv_float, tshape_int_or_long: operation_result_zerodiv_float, tshape_bool: operation_result_zerodiv_float, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_floordiv, tshape_bytes: operation_result_unsupported_floordiv, tshape_bytearray: operation_result_unsupported_floordiv, tshape_unicode: operation_result_unsupported_floordiv, tshape_tuple: operation_result_unsupported_floordiv, tshape_list: operation_result_unsupported_floordiv, tshape_set: operation_result_unsupported_floordiv, tshape_frozenset: operation_result_unsupported_floordiv, tshape_dict: operation_result_unsupported_floordiv, tshape_type: operation_result_unsupported_floordiv, tshape_none: operation_result_unsupported_floordiv, } ) truediv_shapes_float.update( cloneWithUnsupportedChange( floordiv_shapes_float, operation_result_unsupported_truediv ) ) olddiv_shapes_float.update( cloneWithUnsupportedChange( floordiv_shapes_float, operation_result_unsupported_olddiv ) ) mod_shapes_float.update( cloneWithUnsupportedChange(floordiv_shapes_float, operation_result_unsupported_mod) ) pow_shapes_float.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int keep their type, as bool is 0 or 1 int. tshape_int: operation_result_zerodiv_float, tshape_long: operation_result_zerodiv_float, tshape_int_or_long: operation_result_zerodiv_float, tshape_bool: operation_result_float_noescape, tshape_float: operation_result_zerodiv_float, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_pow, tshape_bytes: operation_result_unsupported_pow, tshape_bytearray: operation_result_unsupported_pow, tshape_unicode: operation_result_unsupported_pow, tshape_tuple: operation_result_unsupported_pow, tshape_list: operation_result_unsupported_pow, tshape_set: operation_result_unsupported_pow, tshape_frozenset: operation_result_unsupported_pow, tshape_dict: operation_result_unsupported_pow, tshape_type: operation_result_unsupported_pow, tshape_none: operation_result_unsupported_pow, } ) add_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_complex_noescape, tshape_long: operation_result_complex_noescape, tshape_int_or_long: operation_result_complex_noescape, tshape_bool: operation_result_complex_noescape, tshape_float: operation_result_complex_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_complex_noescape, tshape_long: operation_result_complex_noescape, tshape_int_or_long: operation_result_complex_noescape, tshape_bool: operation_result_complex_noescape, tshape_float: operation_result_complex_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_sub, tshape_bytes: operation_result_unsupported_sub, tshape_bytearray: operation_result_unsupported_sub, tshape_unicode: operation_result_unsupported_sub, tshape_tuple: operation_result_unsupported_sub, tshape_list: operation_result_unsupported_sub, # Unsupported: tshape_set: operation_result_unsupported_sub, tshape_frozenset: operation_result_unsupported_sub, tshape_dict: operation_result_unsupported_sub, tshape_type: operation_result_unsupported_sub, tshape_none: operation_result_unsupported_sub, } ) mult_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int might turn into long when growing due to possible overflow. tshape_int: operation_result_complex_noescape, tshape_long: operation_result_complex_noescape, tshape_int_or_long: operation_result_complex_noescape, tshape_bool: operation_result_complex_noescape, tshape_float: operation_result_complex_noescape, tshape_complex: operation_result_complex_noescape, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) truediv_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # floats do math ops tshape_int: operation_result_zerodiv_complex, tshape_long: operation_result_zerodiv_complex, tshape_int_or_long: operation_result_zerodiv_complex, tshape_bool: operation_result_zerodiv_complex, tshape_float: operation_result_zerodiv_complex, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_truediv, tshape_bytes: operation_result_unsupported_truediv, tshape_bytearray: operation_result_unsupported_truediv, tshape_unicode: operation_result_unsupported_truediv, tshape_tuple: operation_result_unsupported_truediv, tshape_list: operation_result_unsupported_truediv, tshape_set: operation_result_unsupported_truediv, tshape_frozenset: operation_result_unsupported_truediv, tshape_dict: operation_result_unsupported_truediv, tshape_type: operation_result_unsupported_truediv, tshape_none: operation_result_unsupported_truediv, } ) if python_version < 0x300: floordiv_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # floats do math ops tshape_int: operation_result_zerodiv_complex, tshape_long: operation_result_zerodiv_complex, tshape_int_or_long: operation_result_zerodiv_complex, tshape_bool: operation_result_zerodiv_complex, tshape_float: operation_result_zerodiv_complex, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_floordiv, tshape_bytes: operation_result_unsupported_floordiv, tshape_bytearray: operation_result_unsupported_floordiv, tshape_unicode: operation_result_unsupported_floordiv, tshape_tuple: operation_result_unsupported_floordiv, tshape_list: operation_result_unsupported_floordiv, tshape_set: operation_result_unsupported_floordiv, tshape_frozenset: operation_result_unsupported_floordiv, tshape_dict: operation_result_unsupported_floordiv, tshape_type: operation_result_unsupported_floordiv, tshape_none: operation_result_unsupported_floordiv, } ) olddiv_shapes_complex.update( cloneWithUnsupportedChange( truediv_shapes_complex, operation_result_unsupported_olddiv ) ) mod_shapes_complex.update( cloneWithUnsupportedChange(truediv_shapes_complex, operation_result_unsupported_mod) ) pow_shapes_complex.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, tshape_int: operation_result_zerodiv_complex, tshape_long: operation_result_zerodiv_complex, tshape_int_or_long: operation_result_zerodiv_complex, tshape_bool: operation_result_complex_noescape, tshape_float: operation_result_zerodiv_complex, tshape_complex: operation_result_zerodiv_complex, # Unsupported: tshape_str: operation_result_unsupported_pow, tshape_bytes: operation_result_unsupported_pow, tshape_bytearray: operation_result_unsupported_pow, tshape_unicode: operation_result_unsupported_pow, tshape_tuple: operation_result_unsupported_pow, tshape_list: operation_result_unsupported_pow, tshape_set: operation_result_unsupported_pow, tshape_frozenset: operation_result_unsupported_pow, tshape_dict: operation_result_unsupported_pow, tshape_type: operation_result_unsupported_pow, tshape_none: operation_result_unsupported_pow, } ) add_shapes_tuple.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, tshape_complex: operation_result_unsupported_add, # Sequence mixing is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_tuple_noescape, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) mult_shapes_tuple.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_tuple_noescape, tshape_long: operation_result_tuple_noescape, tshape_int_or_long: operation_result_tuple_noescape, tshape_bool: operation_result_tuple_noescape, tshape_float: operation_result_unsupported_mul, tshape_complex: operation_result_unsupported_mul, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) add_shapes_list.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, tshape_complex: operation_result_unsupported_add, # Sequence concat mixing is not allowed except for list tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_list_noescape, tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) iadd_shapes_list.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, tshape_complex: operation_result_unsupported_add, # Sequence concat mixing is not allowed tshape_str: operation_result_list_noescape, tshape_bytes: operation_result_list_noescape, tshape_bytearray: operation_result_list_noescape, tshape_unicode: operation_result_list_noescape, tshape_tuple: operation_result_list_noescape, tshape_list: operation_result_list_noescape, tshape_set: operation_result_list_noescape, tshape_frozenset: operation_result_list_noescape, tshape_dict: operation_result_list_noescape, # Unsupported: tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) # These multiply with nothing really. nothing_multiplicants = ( tshape_none, tshape_set, tshape_dict, tshape_type, tshape_list_iterator, tshape_dict_iterator, tshape_set_iterator, tshape_tuple_iterator, ) def updateNonMultiplicants(op_shapes): for shape in nothing_multiplicants: op_shapes[shape] = operation_result_unsupported_mul sequence_non_multiplicants = ( tshape_float, tshape_str, tshape_bytes, tshape_bytearray, tshape_unicode, tshape_tuple, tshape_list, tshape_set, tshape_frozenset, tshape_dict, ) def updateSequenceNonMultiplicants(op_shapes): updateNonMultiplicants(op_shapes) for shape in sequence_non_multiplicants: op_shapes[shape] = operation_result_unsupported_mul mult_shapes_list.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_list_noescape, tshape_long: operation_result_list_noescape, tshape_int_or_long: operation_result_list_noescape, tshape_bool: operation_result_list_noescape, } ) # Sequence repeat is not allowed with most types. updateSequenceNonMultiplicants(mult_shapes_list) add_shapes_set.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Sets to do not multiply tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_set.update(sub_shapes_none) sub_shapes_set[tshape_set] = operation_result_set_noescape sub_shapes_set[tshape_frozenset] = operation_result_set_noescape bitor_shapes_set.update(bitor_shapes_none) bitor_shapes_set[tshape_set] = operation_result_set_noescape bitor_shapes_set[tshape_frozenset] = operation_result_set_noescape bitand_shapes_set.update( cloneWithUnsupportedChange(bitor_shapes_set, operation_result_unsupported_bitand) ) bitxor_shapes_set.update( cloneWithUnsupportedChange(bitor_shapes_set, operation_result_unsupported_bitxor) ) add_shapes_frozenset.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Sets to do not multiply tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, # Unsupported: tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) sub_shapes_frozenset.update(sub_shapes_set) sub_shapes_frozenset[tshape_set] = operation_result_frozenset_noescape sub_shapes_frozenset[tshape_frozenset] = operation_result_frozenset_noescape bitor_shapes_frozenset.update(bitor_shapes_none) bitor_shapes_frozenset[tshape_set] = operation_result_frozenset_noescape bitor_shapes_frozenset[tshape_frozenset] = operation_result_frozenset_noescape bitand_shapes_frozenset.update( cloneWithUnsupportedChange( bitor_shapes_frozenset, operation_result_unsupported_bitand ) ) bitxor_shapes_frozenset.update( cloneWithUnsupportedChange( bitor_shapes_frozenset, operation_result_unsupported_bitxor ) ) add_shapes_dict.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Sets to do not multiply tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) add_shapes_str.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_str_noescape, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_bytearray_noescape if python_version < 0x300 else operation_result_unsupported_add, tshape_unicode: operation_result_unicode_noescape, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) mult_shapes_str.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_str_noescape, tshape_long: operation_result_str_noescape, tshape_int_or_long: operation_result_str_noescape, tshape_bool: operation_result_str_noescape, tshape_float: operation_result_unsupported_mul, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) mod_shapes_str.update( { # Standard, TODO: should be string, but may escape with exception. tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # str formatting with all kinds of values tshape_int: operation_result_str_formaterror, tshape_long: operation_result_str_formaterror, tshape_int_or_long: operation_result_str_formaterror, tshape_bool: operation_result_str_formaterror, tshape_float: operation_result_str_formaterror, tshape_str: operation_result_str_formaterror, tshape_bytes: operation_result_str_formaterror, tshape_bytearray: operation_result_str_formaterror, tshape_unicode: operation_result_str_formaterror, tshape_tuple: operation_result_str_formaterror, tshape_list: operation_result_str_formaterror, tshape_set: operation_result_str_formaterror, tshape_frozenset: operation_result_str_formaterror, tshape_dict: operation_result_str_formaterror, tshape_type: operation_result_str_formaterror, tshape_none: operation_result_str_formaterror, } ) add_shapes_bytes.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_add, tshape_bytes: operation_result_bytes_noescape, tshape_bytearray: operation_result_bytearray_noescape, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) mult_shapes_bytes.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_bytes_noescape, tshape_long: operation_result_bytes_noescape, tshape_int_or_long: operation_result_bytes_noescape, tshape_bool: operation_result_bytes_noescape, tshape_float: operation_result_unsupported_mul, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) if python_version < 0x350: operation_result_350_bytes_mod_noescape = operation_result_unsupported_mod else: operation_result_350_bytes_mod_noescape = operation_result_bytes_formaterror mod_shapes_bytes.update( { # Standard, TODO: should be string, but may escape with exception. tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # bytes formatting with all kinds of values tshape_int: operation_result_350_bytes_mod_noescape, tshape_bool: operation_result_350_bytes_mod_noescape, tshape_float: operation_result_350_bytes_mod_noescape, tshape_bytes: operation_result_350_bytes_mod_noescape, tshape_bytearray: operation_result_350_bytes_mod_noescape, tshape_unicode: operation_result_350_bytes_mod_noescape, tshape_tuple: operation_result_350_bytes_mod_noescape, tshape_list: operation_result_350_bytes_mod_noescape, tshape_set: operation_result_350_bytes_mod_noescape, tshape_frozenset: operation_result_350_bytes_mod_noescape, tshape_dict: operation_result_350_bytes_mod_noescape, tshape_type: operation_result_350_bytes_mod_noescape, tshape_none: operation_result_350_bytes_mod_noescape, } ) add_shapes_bytearray.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_bytearray_noescape if python_version < 0x300 else operation_result_unsupported_add, tshape_bytes: operation_result_bytearray_noescape, tshape_bytearray: operation_result_bytearray_noescape, tshape_unicode: operation_result_unsupported_add, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) mult_shapes_bytearray.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_bytearray_noescape, tshape_long: operation_result_bytearray_noescape, tshape_int_or_long: operation_result_bytearray_noescape, tshape_bool: operation_result_bytearray_noescape, tshape_float: operation_result_unsupported_mul, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) if python_version < 0x350: operation_result_350_bytearray_mod_noescape = operation_result_unsupported_mod else: operation_result_350_bytearray_mod_noescape = operation_result_bytearray_formaterror mod_shapes_bytearray.update( { tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # bytes formatting with all kinds of values tshape_int: operation_result_350_bytearray_mod_noescape, tshape_bool: operation_result_350_bytearray_mod_noescape, tshape_float: operation_result_350_bytearray_mod_noescape, tshape_bytes: operation_result_350_bytearray_mod_noescape, tshape_bytearray: operation_result_350_bytearray_mod_noescape, tshape_unicode: operation_result_350_bytearray_mod_noescape, tshape_tuple: operation_result_350_bytearray_mod_noescape, tshape_list: operation_result_350_bytearray_mod_noescape, tshape_set: operation_result_350_bytearray_mod_noescape, tshape_frozenset: operation_result_350_bytes_mod_noescape, tshape_dict: operation_result_350_bytearray_mod_noescape, tshape_type: operation_result_350_bytearray_mod_noescape, tshape_none: operation_result_350_bytearray_mod_noescape, } ) add_shapes_unicode.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unsupported_add, tshape_long: operation_result_unsupported_add, tshape_int_or_long: operation_result_unsupported_add, tshape_bool: operation_result_unsupported_add, tshape_float: operation_result_unsupported_add, # Sequence repeat is not allowed tshape_str: operation_result_unicode_noescape, tshape_bytes: operation_result_unsupported_add, tshape_bytearray: operation_result_unsupported_add, tshape_unicode: operation_result_unicode_noescape, tshape_tuple: operation_result_unsupported_add, tshape_list: operation_result_unsupported_add, # Unsupported: tshape_set: operation_result_unsupported_add, tshape_frozenset: operation_result_unsupported_add, tshape_dict: operation_result_unsupported_add, tshape_type: operation_result_unsupported_add, tshape_none: operation_result_unsupported_add, } ) mult_shapes_unicode.update( { # Standard tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # Int is sequence repeat tshape_int: operation_result_unicode_noescape, tshape_long: operation_result_unicode_noescape, tshape_int_or_long: operation_result_unicode_noescape, tshape_bool: operation_result_unicode_noescape, tshape_float: operation_result_unsupported_mul, # Sequence repeat is not allowed tshape_str: operation_result_unsupported_mul, tshape_bytes: operation_result_unsupported_mul, tshape_bytearray: operation_result_unsupported_mul, tshape_unicode: operation_result_unsupported_mul, tshape_tuple: operation_result_unsupported_mul, tshape_list: operation_result_unsupported_mul, # Unsupported: tshape_set: operation_result_unsupported_mul, tshape_frozenset: operation_result_unsupported_mul, tshape_dict: operation_result_unsupported_mul, tshape_type: operation_result_unsupported_mul, tshape_none: operation_result_unsupported_mul, } ) mod_shapes_unicode.update( { # Standard, TODO: should be unicode, but may escape with exception. tshape_unknown: operation_result_unknown, tshape_long_derived: operation_result_unknown, tshape_int_or_long_derived: operation_result_unknown, tshape_float_derived: operation_result_unknown, tshape_str_derived: operation_result_unknown, tshape_unicode_derived: operation_result_unknown, tshape_bytes_derived: operation_result_unknown, # str formatting with all kinds of values tshape_int: operation_result_unicode_formaterror, tshape_long: operation_result_unicode_formaterror, tshape_int_or_long: operation_result_unicode_formaterror, tshape_bool: operation_result_unicode_formaterror, tshape_float: operation_result_unicode_formaterror, tshape_str: operation_result_unicode_formaterror, tshape_bytes: operation_result_unicode_formaterror, tshape_bytearray: operation_result_unicode_formaterror, tshape_unicode: operation_result_unicode_formaterror, tshape_tuple: operation_result_unicode_formaterror, tshape_list: operation_result_unicode_formaterror, tshape_set: operation_result_unicode_formaterror, tshape_frozenset: operation_result_unicode_formaterror, tshape_dict: operation_result_unicode_formaterror, tshape_type: operation_result_unicode_formaterror, tshape_none: operation_result_unicode_formaterror, } ) def mergeStrOrUnicode(op_shapes_str, op_shapes_unicode): r = {} for key, value in op_shapes_str.items(): value2 = op_shapes_unicode[key] if value is value2: r[key] = value elif value[0] is tshape_str_or_unicode and value2[0] is tshape_unicode: assert value[1] is value2[1] r[key] = value elif value[0] is tshape_str and value2[0] is tshape_unicode: assert ( value[1] is value2[1] in ( operation_result_strorunicode_noescape[1], ControlFlowDescriptionFormatError, ) ), (value, value2) r[key] = operation_result_strorunicode_noescape elif key == tshape_bytearray: # They differ here on Python2 r[key] = operation_result_unknown else: assert False, (key, "->", value, "!=", value2) return r add_shapes_strorunicode.update(mergeStrOrUnicode(add_shapes_str, add_shapes_unicode)) sub_shapes_strorunicode.update(mergeStrOrUnicode(sub_shapes_str, sub_shapes_unicode)) mult_shapes_strorunicode.update(mergeStrOrUnicode(mult_shapes_str, mult_shapes_unicode)) floordiv_shapes_strorunicode.update( mergeStrOrUnicode(floordiv_shapes_str, floordiv_shapes_unicode) ) truediv_shapes_strorunicode.update( mergeStrOrUnicode(truediv_shapes_str, truediv_shapes_unicode) ) olddiv_shapes_strorunicode.update( mergeStrOrUnicode(olddiv_shapes_str, olddiv_shapes_unicode) ) mod_shapes_strorunicode.update(mergeStrOrUnicode(mod_shapes_str, mod_shapes_unicode)) divmod_shapes_strorunicode.update( mergeStrOrUnicode(divmod_shapes_str, divmod_shapes_unicode) ) pow_shapes_strorunicode.update(mergeStrOrUnicode(pow_shapes_str, pow_shapes_unicode)) lshift_shapes_strorunicode.update( mergeStrOrUnicode(lshift_shapes_str, lshift_shapes_unicode) ) rshift_shapes_strorunicode.update( mergeStrOrUnicode(rshift_shapes_str, rshift_shapes_unicode) ) bitor_shapes_strorunicode.update( mergeStrOrUnicode(bitor_shapes_str, bitor_shapes_unicode) ) bitand_shapes_strorunicode.update( mergeStrOrUnicode(bitand_shapes_str, bitand_shapes_unicode) ) bitxor_shapes_strorunicode.update( mergeStrOrUnicode(bitxor_shapes_str, bitxor_shapes_unicode) ) if python_version >= 0x390: bitor_shapes_dict[tshape_dict] = operation_result_dict_noescape ibitor_shapes_dict[tshape_dict] = operation_result_dict_noescape ibitor_shapes_dict[tshape_tuple] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_list] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_set] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_frozenset] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_str] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_bytes] = operation_result_dict_valueerror ibitor_shapes_dict[tshape_bytearray] = operation_result_dict_valueerror class ShapeTypeBuiltinExceptionClass( ShapeNotContainerMixin, ShapeNotNumberMixin, ShapeBase ): typical_value = None tshape_exception_class = ShapeTypeBuiltinExceptionClass() Nuitka-0.6.19.1/nuitka/nodes/shapes/ShapeMixins.py0000600000372100037210000001007114166627112026756 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Mixins to use for composing type shapes. """ from .ControlFlowDescriptions import ( ControlFlowDescriptionElementBasedEscape, ControlFlowDescriptionNoEscape, ) class ShapeContainerMixin(object): """Mixin that defines the common container shape functions.""" @staticmethod def hasShapeSlotBool(): return True @staticmethod def hasShapeSlotLen(): return True @staticmethod def hasShapeSlotContains(): return True @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotNext(): return False @staticmethod def hasShapeModule(): return False @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionElementBasedEscape @staticmethod def hasShapeTrustedAttributes(): return True class ShapeContainerMutableMixin(ShapeContainerMixin): @staticmethod def hasShapeSlotHash(): return False class ShapeContainerImmutableMixin(ShapeContainerMixin): @staticmethod def hasShapeSlotHash(): return True class ShapeNotContainerMixin(object): @staticmethod def hasShapeSlotBool(): return True @staticmethod def hasShapeSlotLen(): return False @staticmethod def hasShapeSlotIter(): return False @staticmethod def hasShapeSlotNext(): return False @staticmethod def hasShapeSlotContains(): return False @staticmethod def hasShapeModule(): return False @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionNoEscape class ShapeNotNumberMixin(object): """Mixin that defines the number slots to be set.""" @staticmethod def hasShapeSlotBool(): return True @staticmethod def hasShapeSlotAbs(): return False @staticmethod def hasShapeSlotInt(): return False @staticmethod def hasShapeSlotLong(): return False @staticmethod def hasShapeSlotFloat(): return False @staticmethod def hasShapeSlotComplex(): return False @staticmethod def hasShapeModule(): return False class ShapeNumberMixin(object): """Mixin that defines the number slots to be set.""" @staticmethod def hasShapeSlotBool(): return True @staticmethod def hasShapeSlotAbs(): return True @staticmethod def hasShapeSlotInt(): return True @staticmethod def hasShapeSlotLong(): return True @staticmethod def hasShapeSlotFloat(): return True @staticmethod def hasShapeSlotComplex(): return True @staticmethod def hasShapeSlotHash(): return True @staticmethod def hasShapeModule(): return False @staticmethod def hasShapeTrustedAttributes(): return True @staticmethod def getOperationUnaryReprEscape(): return ControlFlowDescriptionNoEscape class ShapeIteratorMixin(ShapeNotContainerMixin): @staticmethod def hasShapeSlotIter(): return True @staticmethod def hasShapeSlotNext(): return True @staticmethod def hasShapeSlotContains(): return True @staticmethod def hasShapeSlotHash(): return True Nuitka-0.6.19.1/nuitka/nodes/shapes/ControlFlowDescriptions.py0000600000372100037210000001044314166627112031370 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Objects use to describe control flow escapes. Typically returned by shape operations to indicate what can and can not have happened. """ class ControlFlowDescriptionBase(object): @staticmethod def isUnsupported(): return False class ControlFlowDescriptionElementBasedEscape(ControlFlowDescriptionBase): @staticmethod def getExceptionExit(): return BaseException @staticmethod def isValueEscaping(): return True @staticmethod def isControlFlowEscape(): return True class ControlFlowDescriptionFullEscape(ControlFlowDescriptionBase): @staticmethod def getExceptionExit(): return BaseException @staticmethod def isValueEscaping(): return True @staticmethod def isControlFlowEscape(): return True class ControlFlowDescriptionNoEscape(ControlFlowDescriptionBase): @staticmethod def getExceptionExit(): return None @staticmethod def isValueEscaping(): return False @staticmethod def isControlFlowEscape(): return False class ControlFlowDescriptionZeroDivisionNoEscape(ControlFlowDescriptionNoEscape): @staticmethod def getExceptionExit(): return ZeroDivisionError class ControlFlowDescriptionValueErrorNoEscape(ControlFlowDescriptionNoEscape): @staticmethod def getExceptionExit(): return ValueError class ControlFlowDescriptionComparisonUnorderable(ControlFlowDescriptionNoEscape): @staticmethod def getExceptionExit(): return TypeError @staticmethod def isUnsupported(): return True class ControlFlowDescriptionFormatError(ControlFlowDescriptionFullEscape): pass class ControlFlowDescriptionOperationUnsupportedBase(ControlFlowDescriptionNoEscape): @staticmethod def getExceptionExit(): return TypeError @staticmethod def isUnsupported(): return True class ControlFlowDescriptionAddUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionSubUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionMulUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionFloorDivUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionTrueDivUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionOldDivUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionModUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionDivmodUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionPowUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionBitorUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionBitandUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionBitxorUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionLshiftUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionRshiftUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass class ControlFlowDescriptionMatmultUnsupported( ControlFlowDescriptionOperationUnsupportedBase ): pass Nuitka-0.6.19.1/nuitka/nodes/shapes/__init__.py0000600000372100037210000000150114166627112026263 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/nodes/AssignNodes.py0000600000372100037210000006162314166627112025471 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Assignment related nodes. The most simple assignment statement ``a = b`` is what we have here. All others are either re-formulated using temporary variables, e.g. ``a, b = c`` or are attribute, slice, subscript assignments. The deletion is a separate node unlike in CPython where assigning to ``NULL`` is internally what deletion is. But deleting is something entirely different to us during code generation, which is why we keep them separate. Tracing assignments in SSA form is the core of optimization for which we use the traces. """ from nuitka.ModuleRegistry import getOwnerFromCodeName from nuitka.Options import isExperimental from .NodeBases import StatementBase, StatementChildHavingBase from .NodeMakingHelpers import ( makeRaiseExceptionReplacementStatement, makeStatementExpressionOnlyReplacementNode, makeStatementsSequenceReplacementNode, ) from .shapes.StandardShapes import tshape_unknown class StatementAssignmentVariableName(StatementChildHavingBase): """Precursor of StatementAssignmentVariable used during tree building phase""" kind = "STATEMENT_ASSIGNMENT_VARIABLE_NAME" named_child = "source" nice_child = "assignment source" __slots__ = ("variable_name", "provider") def __init__(self, provider, variable_name, source, source_ref): assert source is not None, source_ref StatementChildHavingBase.__init__(self, value=source, source_ref=source_ref) self.variable_name = variable_name self.provider = provider assert not provider.isExpressionOutlineBody(), source_ref def getDetails(self): return {"variable_name": self.variable_name, "provider": self.provider} def getVariableName(self): return self.variable_name def computeStatement(self, trace_collection): # Only for abc, pylint: disable=no-self-use # These must not enter real optimization, they only live during the # tree building. assert False @staticmethod def getStatementNiceName(): return "variable assignment statement" class StatementDelVariableName(StatementBase): """Precursor of StatementDelVariable used during tree building phase""" kind = "STATEMENT_DEL_VARIABLE_NAME" __slots__ = "variable_name", "provider", "tolerant" def __init__(self, provider, variable_name, tolerant, source_ref): StatementBase.__init__(self, source_ref=source_ref) self.variable_name = variable_name self.provider = provider self.tolerant = tolerant def finalize(self): del self.parent del self.provider def getDetails(self): return { "variable_name": self.variable_name, "provider": self.provider, "tolerant": self.tolerant, } def getVariableName(self): return self.variable_name def computeStatement(self, trace_collection): # Only for abc, pylint: disable=no-self-use # These must not enter real optimization, they only live during the # tree building. assert False class StatementAssignmentVariable(StatementChildHavingBase): """Assignment to a variable from an expression. All assignment forms that are not to attributes, slices, subscripts use this. The source might be a complex expression. The target can be any kind of variable, temporary, local, global, etc. Assigning a variable is something we trace in a new version, this is hidden behind target variable reference, which has this version once it can be determined. """ kind = "STATEMENT_ASSIGNMENT_VARIABLE" named_child = "source" nice_child = "assignment source" __slots__ = ( "subnode_source", "variable", "variable_version", "variable_trace", "inplace_suspect", ) def __init__(self, source, variable, source_ref, version=None): assert source is not None, source_ref if version is None: version = variable.allocateTargetNumber() self.variable = variable self.variable_version = version StatementChildHavingBase.__init__(self, value=source, source_ref=source_ref) self.variable_trace = None self.inplace_suspect = None def finalize(self): StatementChildHavingBase.finalize(self) del self.variable del self.variable_trace def getDetails(self): return {"variable": self.variable} def getDetailsForDisplay(self): return { "variable_name": self.getVariableName(), "is_temp": self.variable.isTempVariable(), "var_type": self.variable.getVariableType(), "owner": self.variable.getOwner().getCodeName(), } @classmethod def fromXML(cls, provider, source_ref, **args): assert cls is StatementAssignmentVariable, cls owner = getOwnerFromCodeName(args["owner"]) if args["is_temp"] == "True": variable = owner.createTempVariable( args["variable_name"], temp_type=["var_type"] ) else: variable = owner.getProvidedVariable(args["variable_name"]) del args["is_temp"] del args["var_type"] del args["owner"] version = variable.allocateTargetNumber() return cls(variable=variable, version=version, source_ref=source_ref, **args) def makeClone(self): if self.variable is not None: version = self.variable.allocateTargetNumber() else: version = None return StatementAssignmentVariable( source=self.subnode_source.makeClone(), variable=self.variable, version=version, source_ref=self.source_ref, ) def getVariableName(self): return self.variable.getName() def getVariable(self): return self.variable def setVariable(self, variable): self.variable = variable self.variable_version = variable.allocateTargetNumber() def getVariableTrace(self): return self.variable_trace def markAsInplaceSuspect(self): self.inplace_suspect = True def isInplaceSuspect(self): return self.inplace_suspect def unmarkAsInplaceSuspect(self): self.inplace_suspect = False def mayRaiseException(self, exception_type): return self.subnode_source.mayRaiseException(exception_type) def computeStatement(self, trace_collection): # This is very complex stuff, pylint: disable=too-many-branches,too-many-return-statements # TODO: Way too ugly to have global trace kinds just here, and needs to # be abstracted somehow. But for now we let it live here. source = self.subnode_source if source.isExpressionSideEffects(): # If the assignment source has side effects, we can put them into a # sequence and compute that instead. statements = [ makeStatementExpressionOnlyReplacementNode(side_effect, self) for side_effect in source.subnode_side_effects ] statements.append(self) # Remember out parent, we will assign it for the sequence to use. parent = self.parent # Need to update ourselves to no longer reference the side effects, # but go to the wrapped thing. self.setChild("source", source.subnode_expression) result = makeStatementsSequenceReplacementNode( statements=statements, node=self ) result.parent = parent return ( result.computeStatementsSequence(trace_collection), "new_statements", """\ Side effects of assignments promoted to statements.""", ) # Let assignment source may re-compute first. source = trace_collection.onExpression(self.subnode_source) # No assignment will occur, if the assignment source raises, so give up # on this, and return it as the only side effect. if source.willRaiseException(BaseException): result = makeStatementExpressionOnlyReplacementNode( expression=source, node=self ) del self.parent return ( result, "new_raise", """\ Assignment raises exception in assigned value, removed assignment.""", ) variable = self.variable # Assigning from and to the same variable, can be optimized away # immediately, there is no point in doing it. Exceptions are of course # module variables that collide with built-in names. # TODO: The variable type checks ought to become unnecessary, as they # are to be a feature of the trace. Assigning from known assigned is # supposed to be possible to eliminate. If we get that wrong, we are # doing it wrong. if ( not variable.isModuleVariable() and source.isExpressionVariableRef() and source.getVariable() is variable ): # A variable access that has a side effect, must be preserved, # so it can e.g. raise an exception, otherwise we can be fully # removed. if source.mayHaveSideEffects(): result = makeStatementExpressionOnlyReplacementNode( expression=source, node=self ) return ( result, "new_statements", """\ Lowered assignment of %s from itself to mere access of it.""" % variable.getDescription(), ) else: return ( None, "new_statements", """\ Removed assignment of %s from itself which is known to be defined.""" % variable.getDescription(), ) # Set-up the trace to the trace collection, so future references will # find this assignment. self.variable_trace = trace_collection.onVariableSet( variable=variable, version=self.variable_version, assign_node=self ) provider = trace_collection.getOwner() if variable.hasAccessesOutsideOf(provider) is False: last_trace = variable.getMatchingAssignTrace(self) if last_trace is not None and not last_trace.getMergeOrNameUsageCount(): if source.isCompileTimeConstant(): if ( variable.isModuleVariable() or variable.owner.locals_scope.isUnoptimizedFunctionScope() ): # TODO: We do not trust these yet a lot, but more might be pass else: # Unused constants can be eliminated in any case. if not last_trace.getUsageCount(): if not last_trace.getPrevious().isUnassignedTrace(): result = StatementDelVariable( variable=self.variable, version=self.variable_version, tolerant=True, source_ref=self.source_ref, ) else: result = None return ( result, "new_statements", "Dropped dead assignment statement to '%s'." % (self.getVariableName()), ) # Can safely forward propagate only non-mutable constants. if not source.isMutable(): self.variable_trace.setReplacementNode( lambda _usage: source.makeClone() ) if not last_trace.getPrevious().isUnassignedTrace(): result = StatementDelVariable( variable=self.variable, version=self.variable_version, tolerant=True, source_ref=self.source_ref, ) else: result = None return ( result, "new_statements", "Dropped propagated assignment statement to '%s'." % self.getVariableName(), ) elif source.isExpressionFunctionCreation(): # TODO: Prepare for inlining. pass else: # More cases thinkable. pass return self, None, None def needsReleasePreviousValue(self): previous = self.variable_trace.getPrevious() if previous.mustNotHaveValue(): return False elif previous.mustHaveValue(): return True else: return None @staticmethod def getStatementNiceName(): return "variable assignment statement" def getTypeShape(self): # Might be finalized, e.g. due to being dead code. try: source = self.subnode_source except AttributeError: return tshape_unknown return source.getTypeShape() class StatementDelVariable(StatementBase): """Deleting a variable. All del forms that are not to attributes, slices, subscripts use this. The target can be any kind of variable, temporary, local, global, etc. Deleting a variable is something we trace in a new version, this is hidden behind target variable reference, which has this version once it can be determined. Tolerance means that the value might be unset. That can happen with re-formulation of ours, and Python3 exception variables. """ kind = "STATEMENT_DEL_VARIABLE" __slots__ = ( "variable", "variable_version", "variable_trace", "previous_trace", "tolerant", ) def __init__(self, tolerant, source_ref, variable, version=None): if type(tolerant) is str: tolerant = tolerant == "True" assert tolerant is True or tolerant is False, repr(tolerant) if variable is not None: if version is None: version = variable.allocateTargetNumber() StatementBase.__init__(self, source_ref=source_ref) self.variable = variable self.variable_version = version self.variable_trace = None self.previous_trace = None self.tolerant = tolerant def finalize(self): del self.parent del self.variable del self.variable_trace del self.previous_trace def getDetails(self): return { "variable": self.variable, "version": self.variable_version, "tolerant": self.tolerant, } def getDetailsForDisplay(self): return { "variable_name": self.getVariableName(), "is_temp": self.variable.isTempVariable(), "var_type": self.variable.getVariableType(), "owner": self.variable.getOwner().getCodeName(), "tolerant": self.tolerant, } @classmethod def fromXML(cls, provider, source_ref, **args): assert cls is StatementDelVariable, cls owner = getOwnerFromCodeName(args["owner"]) if args["is_temp"] == "True": variable = owner.createTempVariable( args["variable_name"], temp_type=args["var_type"] ) else: variable = owner.getProvidedVariable(args["variable_name"]) del args["is_temp"] del args["var_type"] del args["owner"] version = variable.allocateTargetNumber() variable.version_number = max(variable.version_number, version) return cls(variable=variable, source_ref=source_ref, **args) def makeClone(self): if self.variable is not None: version = self.variable.allocateTargetNumber() else: version = None return StatementDelVariable( variable=self.variable, version=version, tolerant=self.tolerant, source_ref=self.source_ref, ) # TODO: Value propagation needs to make a difference based on this. def isTolerant(self): return self.tolerant def getVariableName(self): return self.variable.getName() def getVariableTrace(self): return self.variable_trace def getPreviousVariableTrace(self): return self.previous_trace def getVariable(self): return self.variable def setVariable(self, variable): self.variable = variable self.variable_version = variable.allocateTargetNumber() def computeStatement(self, trace_collection): variable = self.variable # Special case, boolean temp variables need no "del". # TODO: Later, these might not exist, if we forward propagate them not as "del" # at all if variable.isTempVariableBool(): return ( None, "new_statements", "Removed 'del' statement of boolean '%s' without effect." % (self.getVariableName(),), ) self.previous_trace = trace_collection.getVariableCurrentTrace(variable) # First eliminate us entirely if we can. if self.previous_trace.mustNotHaveValue(): if self.tolerant: return ( None, "new_statements", "Removed tolerant 'del' statement of '%s' without effect." % (self.getVariableName(),), ) else: if self.variable.isLocalVariable(): result = makeRaiseExceptionReplacementStatement( statement=self, exception_type="UnboundLocalError", exception_value="""local variable '%s' referenced before assignment""" % variable.getName(), ) else: result = makeRaiseExceptionReplacementStatement( statement=self, exception_type="NameError", exception_value="""name '%s' is not defined""" % variable.getName(), ) return trace_collection.computedStatementResult( result, "new_raise", "Variable del of not initialized variable '%s'" % variable.getName(), ) if not self.tolerant: self.previous_trace.addNameUsage() # TODO: Why doesn't this module variable check not follow from other checks done here, e.g. name usages. # TODO: This currently cannot be done as releases do not create successor traces yet, although they # probably should. if isExperimental("del_optimization") and not variable.isModuleVariable(): provider = trace_collection.getOwner() if variable.hasAccessesOutsideOf(provider) is False: last_trace = variable.getMatchingDelTrace(self) if last_trace is not None and not last_trace.getMergeOrNameUsageCount(): if not last_trace.getUsageCount(): result = StatementReleaseVariable( variable=variable, source_ref=self.source_ref ) return trace_collection.computedStatementResult( result, "new_statements", "Changed del to release for variable '%s' not used afterwards." % variable.getName(), ) # If not tolerant, we may exception exit now during the __del__ if not self.tolerant and not self.previous_trace.mustHaveValue(): trace_collection.onExceptionRaiseExit(BaseException) # Record the deletion, needs to start a new version then. self.variable_trace = trace_collection.onVariableDel( variable=variable, version=self.variable_version, del_node=self ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self, None, None def mayRaiseException(self, exception_type): if self.tolerant: return False else: if self.variable_trace is not None: # Temporary variables deletions won't raise, just because we # don't create them that way. We can avoid going through SSA in # these cases. if self.variable.isTempVariable(): return False # If SSA knows, that's fine. if ( self.previous_trace is not None and self.previous_trace.mustHaveValue() ): return False return True class StatementReleaseVariable(StatementBase): """Releasing a variable. Just release the value, which of course is not to be used afterwards. Typical code: Function exit, try/finally release of temporary variables. """ kind = "STATEMENT_RELEASE_VARIABLE" __slots__ = "variable", "variable_trace" def __init__(self, variable, source_ref): assert variable is not None, source_ref StatementBase.__init__(self, source_ref=source_ref) self.variable = variable self.variable_trace = None def finalize(self): del self.variable del self.variable_trace del self.parent def getDetails(self): return {"variable": self.variable} def getDetailsForDisplay(self): return { "variable_name": self.variable.getName(), "owner": self.variable.getOwner().getCodeName(), } @classmethod def fromXML(cls, provider, source_ref, **args): assert cls is StatementReleaseVariable, cls owner = getOwnerFromCodeName(args["owner"]) assert owner is not None, args["owner"] variable = owner.getProvidedVariable(args["variable_name"]) return cls(variable=variable, source_ref=source_ref) def getVariable(self): return self.variable def getVariableTrace(self): return self.variable_trace def setVariable(self, variable): self.variable = variable def computeStatement(self, trace_collection): if self.variable.isParameterVariable(): if self.variable.getOwner().isAutoReleaseVariable(self.variable): return ( None, "new_statements", "Original parameter variable value of '%s' is not released." % self.variable.getName(), ) self.variable_trace = trace_collection.getVariableCurrentTrace(self.variable) if self.variable_trace.mustNotHaveValue(): return ( None, "new_statements", "Uninitialized %s is not released." % (self.variable.getDescription()), ) # TODO: Annotate value content as escaped, as destruction might run. # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # TODO: We might be able to remove ourselves based on the trace # we belong to. return self, None, None @staticmethod def mayHaveSideEffects(): # TODO: May execute "__del__" code, it would be sweet to be able to predict # if another reference will still be active for a value though, or if there # is such a code for the type shape. return True def mayRaiseException(self, exception_type): # By default, __del__ is not allowed to raise an exception. return False Nuitka-0.6.19.1/nuitka/nodes/ExpressionBases.py0000600000372100037210000014757314166627112026402 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Expression base classes. These classes provide the generic base classes available for expressions. They have a richer interface, mostly related to abstract execution, and different from statements. """ from abc import abstractmethod from nuitka import Options from nuitka.__past__ import long from nuitka.Constants import isCompileTimeConstantValue from nuitka.PythonVersions import python_version from .NodeBases import ChildrenHavingMixin, NodeBase from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, wrapExpressionWithNodeSideEffects, wrapExpressionWithSideEffects, ) from .shapes.BuiltinTypeShapes import tshape_dict, tshape_str, tshape_unicode from .shapes.StandardShapes import tshape_unknown class ExpressionBase(NodeBase): # TODO: Maybe we can do this only for debug mode. __slots__ = ("code_generated",) @staticmethod def getTypeShape(): return tshape_unknown def getValueShape(self): return self @staticmethod def isCompileTimeConstant(): """Has a value that we can use at compile time. Yes or no. If it has such a value, simulations can be applied at compile time and e.g. operations or conditions, or even calls may be executed against it. """ return False @staticmethod def getTruthValue(): """Return known truth value. The "None" value indicates unknown.""" return None @staticmethod def getComparisonValue(): """Return known value used for compile time comparison. The "None" value indicates unknown.""" return False, None @staticmethod def isKnownToBeIterable(count): """Can be iterated at all (count is None) or exactly count times. Yes or no. If it can be iterated a known number of times, it may be asked to unpack itself. """ # Virtual method, pylint: disable=unused-argument return False @staticmethod def isKnownToBeIterableAtMin(count): # Virtual method, pylint: disable=unused-argument return False def getIterationLength(self): """Value that "len" or "PyObject_Size" would give, if known. Otherwise it is "None" to indicate unknown. """ # Virtual method, pylint: disable=no-self-use return None def getIterationMinLength(self): """Value that "len" or "PyObject_Size" would give at minimum, if known. Otherwise it is "None" to indicate unknown. """ return self.getIterationLength() @staticmethod def getStringValue(): """Node as string value, if possible.""" return None def getStrValue(self): """Value that "str" or "PyObject_Str" would give, if known. Otherwise it is "None" to indicate unknown. Users must not forget to take side effects into account, when replacing a node with its string value. """ string_value = self.getStringValue() if string_value is not None: # Those that are user provided, need to overload this. return makeConstantReplacementNode( node=self, constant=string_value, user_provided=False ) return None def getTypeValue(self): """Type of the node.""" from .TypeNodes import ExpressionBuiltinType1 return ExpressionBuiltinType1( value=self.makeClone(), source_ref=self.source_ref ) def getIterationHandle(self): # Virtual method, pylint: disable=no-self-use return None @staticmethod def isKnownToBeHashable(): """Is the value hashable, i.e. suitable for dictionary/set key usage.""" # Unknown by default. return None @staticmethod def extractUnhashableNodeType(): """Return the value type that is not hashable, if isKnowtoBeHashable() returns False.""" # Not available by default. return None def onRelease(self, trace_collection): # print "onRelease", self pass def isKnownToHaveAttribute(self, attribute_name): # Virtual method, pylint: disable=no-self-use,unused-argument return None @abstractmethod def computeExpressionRaw(self, trace_collection): """Abstract execution of the node. Returns: tuple(node, tags, description) The return value can be node itself. Notes: Replaces a node with computation result. This is the low level form for the few cases, where the children are not simply all evaluated first, but this allows e.g. to deal with branches, do not overload this unless necessary. """ def computeExpressionAttribute(self, lookup_node, attribute_name, trace_collection): # By default, an attribute lookup may change everything about the lookup # source. # trace_collection.onValueEscapeAttributeLookup(self, attribute_name) if self.mayRaiseExceptionAttributeLookup(BaseException, attribute_name): trace_collection.onExceptionRaiseExit(BaseException) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return lookup_node, None, None def computeExpressionAttributeSpecial( self, lookup_node, attribute_name, trace_collection ): # By default, an attribute lookup may change everything about the lookup # source. Virtual method, pylint: disable=unused-argument # trace_collection.onValueEscapeAttributeLookup(self, attribute_name) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def computeExpressionImportName(self, import_node, import_name, trace_collection): if self.mayRaiseExceptionImportName(BaseException, import_name): trace_collection.onExceptionRaiseExit(BaseException) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return import_node, None, None def computeExpressionSetAttribute( self, set_node, attribute_name, value_node, trace_collection ): # By default, an attribute lookup may change everything about the lookup # source. Virtual method, pylint: disable=unused-argument # trace_collection.removeKnowledge(self) # trace_collection.removeKnowledge(value_node) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) # Better mechanics? return set_node, None, None def computeExpressionDelAttribute(self, set_node, attribute_name, trace_collection): # By default, an attribute lookup may change everything about the lookup # source. Virtual method, pylint: disable=unused-argument # trace_collection.removeKnowledge(self) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) # Better mechanics? return set_node, None, None def computeExpressionSubscript(self, lookup_node, subscript, trace_collection): # By default, an subscript can execute any code and change all values # that escaped. This is a virtual method that may consider the subscript # but generally we don't know what to do. pylint: disable=unused-argument trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def computeExpressionSetSubscript( self, set_node, subscript, value_node, trace_collection ): # By default, an subscript can execute any code and change all values # that escaped. This is a virtual method that may consider the subscript # but generally we don't know what to do. pylint: disable=unused-argument trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return set_node, None, None def computeExpressionDelSubscript(self, del_node, subscript, trace_collection): # By default, an subscript can execute any code and change all values # that escaped. This is a virtual method that may consider the subscript # but generally we don't know what to do. pylint: disable=unused-argument trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return del_node, None, None def computeExpressionSlice(self, lookup_node, lower, upper, trace_collection): # pylint: disable=unused-argument # By default, a slicing may change everything about the lookup source. # trace_collection.removeKnowledge(self) # trace_collection.onValueEscapeSliceOperation(self, lower, upper) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def computeExpressionSetSlice( self, set_node, lower, upper, value_node, trace_collection ): # pylint: disable=unused-argument # By default, an subscript may change everything about the lookup # source. trace_collection.removeKnowledge(self) # trace_collection.onValueEscapeSliceArguments(self, lower, upper) # trace_collection.onValueEscapeSliceSetSource(self, lower, upper) trace_collection.removeKnowledge(value_node) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return set_node, None, None def computeExpressionDelSlice(self, set_node, lower, upper, trace_collection): # pylint: disable=unused-argument # By default, an subscript may change everything about the lookup # source. trace_collection.removeKnowledge(self) # trace_collection.onValueEscapeSliceArguments(self, lower, upper) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return set_node, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): # The called and the arguments escape for good. self.onContentEscapes(trace_collection) if call_args is not None: call_args.onContentEscapes(trace_collection) if call_kw is not None: call_kw.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return call_node, None, None def computeExpressionLen(self, len_node, trace_collection): shape = self.getValueShape() has_len = shape.hasShapeSlotLen() if has_len is False: # An exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="object of type '%s' has no len()", operation="len", original_node=len_node, value_node=self, ) elif has_len is True: iter_length = self.getIterationLength() if iter_length is not None: from .ConstantRefNodes import makeConstantRefNode result = makeConstantRefNode( constant=int(iter_length), # make sure to downcast long source_ref=len_node.getSourceReference(), ) result = wrapExpressionWithNodeSideEffects( new_node=result, old_node=self ) return ( result, "new_constant", "Predicted 'len' result from value shape.", ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return len_node, None, None def computeExpressionAbs(self, abs_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotAbs() is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="bad operand type for abs(): '%s'", operation="abs", original_node=abs_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return abs_node, None, None def computeExpressionInt(self, int_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotInt() is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="int() argument must be a string or a number, not '%s'" if python_version < 0x300 else "int() argument must be a string, a bytes-like object or a number, not '%s'", operation="int", original_node=int_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return int_node, None, None def computeExpressionLong(self, long_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotLong() is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="long() argument must be a string or a number, not '%s'", operation="long", original_node=long_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return long_node, None, None def computeExpressionFloat(self, float_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotFloat() is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( "float() argument must be a string or a number" if Options.is_fullcompat and python_version < 0x300 else "float() argument must be a string or a number, not '%s'", operation="long", original_node=float_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return float_node, None, None def computeExpressionBytes(self, bytes_node, trace_collection): shape = self.getTypeShape() if ( shape.hasShapeSlotBytes() is False and shape.hasShapeSlotInt() is False and shape.hasShapeSlotIter() is False ): # An exception is raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( "'%s' object is not iterable", operation="bytes", original_node=bytes_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return bytes_node, None, None def computeExpressionComplex(self, complex_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotComplex() is False: # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( "complex() argument must be a string or a number" if Options.is_fullcompat and python_version < 0x300 else "complex() argument must be a string or a number, not '%s'", operation="complex", original_node=complex_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return complex_node, None, None def computeExpressionIter1(self, iter_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotIter() is False: # An exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="iter", original_node=iter_node, value_node=self, ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return iter_node, None, None def computeExpressionNext1(self, next_node, trace_collection): # TODO: This is only true for a few value types, use type shape to tell if # it might escape or raise. self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return False, (next_node, None, None) def computeExpressionAsyncIter(self, iter_node, trace_collection): self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return iter_node, None, None def computeExpressionOperationNot(self, not_node, trace_collection): # Virtual method, pylint: disable=no-self-use # The value of that node escapes and could change its contents. # trace_collection.onValueEscapeNot(self) # Any code could be run, note that. trace_collection.onControlFlowEscape(not_node) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return not_node, None, None def computeExpressionOperationRepr(self, repr_node, trace_collection): type_shape = self.getTypeShape() escape_desc = type_shape.getOperationUnaryReprEscape() # Annotate if exceptions might be raised. exception_raise_exit = escape_desc.getExceptionExit() if exception_raise_exit is not None: trace_collection.onExceptionRaiseExit(exception_raise_exit) if escape_desc.isValueEscaping(): # The value of that node escapes and could change its contents during repr # only, which might be more limited. # trace_collection.onValueEscapeRepr(self) trace_collection.removeKnowledge(self) if escape_desc.isControlFlowEscape(): # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return (repr_node, None, None), escape_desc def computeExpressionComparisonIn(self, in_node, value_node, trace_collection): # Virtual method, pylint: disable=unused-argument shape = self.getTypeShape() assert shape is not None, self if shape.hasShapeSlotContains() is False: # An exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="argument of type '%s' object is not iterable", operation="in", original_node=in_node, value_node=self, ) # Any code could be run, note that. trace_collection.onControlFlowEscape(in_node) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return in_node, None, None def computeExpressionDrop(self, statement, trace_collection): if not self.mayHaveSideEffects(): return ( None, "new_statements", lambda: "Removed %s without effect." % self.getDescription(), ) return statement, None, None def computeExpressionBool(self, trace_collection): if not self.mayRaiseException(BaseException) and self.mayRaiseExceptionBool( BaseException ): trace_collection.onExceptionRaiseExit(BaseException) @staticmethod def onContentEscapes(trace_collection): pass @staticmethod def mayRaiseExceptionBool(exception_type): """Unless we are told otherwise, everything may raise being checked.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionAbs(exception_type): """Unless we are told otherwise, everything may raise in 'abs'.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionInt(exception_type): """Unless we are told otherwise, everything may raise in __int__.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionLong(exception_type): """Unless we are told otherwise, everything may raise in __long__.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionFloat(exception_type): """Unless we are told otherwise, everything may raise in __float__.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionBytes(exception_type): """Unless we are told otherwise, everything may raise in __bytes__.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionIn(exception_type, checked_value): """Unless we are told otherwise, everything may raise being iterated.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionAttributeLookup(exception_type, attribute_name): """Unless we are told otherwise, everything may raise for attribute access.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionAttributeLookupSpecial(exception_type, attribute_name): """Unless we are told otherwise, everything may raise for attribute access.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionAttributeLookupObject(exception_type, attribute): """Unless we are told otherwise, everything may raise for attribute access.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayRaiseExceptionImportName(exception_type, import_name): """Unless we are told otherwise, everything may raise for name import.""" # Virtual method, pylint: disable=unused-argument return True @staticmethod def mayHaveSideEffectsBool(): """Unless we are told otherwise, everything may have a side effect for bool check.""" return True @staticmethod def mayHaveSideEffectsAbs(): """Unless we are told otherwise, everything may have a side effect for abs check.""" # TODO: Bonus points for check type shapes that will be good # for abs, i.e. number shapes like Int, Long, Float, Complex. return True def hasShapeSlotLen(self): """The type shape tells us, if "len" is available.""" return self.getTypeShape().hasShapeSlotLen() def hasShapeSlotIter(self): """The type shape tells us, if "iter" is available.""" return self.getTypeShape().hasShapeSlotIter() def hasShapeSlotNext(self): """The type shape tells us, if "next" is available.""" return self.getTypeShape().hasShapeSlotNext() # TODO: Maybe this is a shape slot thing. @staticmethod def isIndexable(): """Unless we are told otherwise, it's not indexable.""" return False # TODO: There ought to be a type shape check for that too. @staticmethod def getIntegerValue(): """Node as integer value, if possible.""" return None # TODO: There ought to be a type shape check for that too. @staticmethod def getIndexValue(): """Node as index value, if possible. This should only work for int, bool, and long values, but e.g. not floats. """ return None @staticmethod def getIntValue(): """Value that "int" or "PyNumber_Int" (sp) would give, if known. Otherwise it is "None" to indicate unknown. Users must not forget to take side effects into account, when replacing a node with its string value. """ return None def hasShapeTrustedAttributes(self): return self.getTypeShape().hasShapeTrustedAttributes() def hasShapeDictionaryExact(self): """Does a node have exactly a dictionary shape.""" return self.getTypeShape() is tshape_dict def hasShapeStrExact(self): """Does an expression have exactly a string shape.""" return self.getTypeShape() is tshape_str def hasShapeUnicodeExact(self): """Does an expression have exactly a unicode shape.""" return self.getTypeShape() is tshape_unicode if str is bytes: def hasShapeStrOrUnicodeExact(self): return self.getTypeShape() in (tshape_str, tshape_unicode) else: def hasShapeStrOrUnicodeExact(self): return self.getTypeShape() is tshape_str class ExpressionNoSideEffectsMixin(object): __slots__ = () @staticmethod def mayHaveSideEffects(): # Virtual method overload return False @staticmethod def extractSideEffects(): # Virtual method overload, we said we have no effects. return () def computeExpressionDrop(self, statement, trace_collection): # Virtual method overload, pylint: disable=unused-argument # # We said we have no effects, so we can be removed. return ( None, "new_statements", lambda: "Removed %s that never has an effect." % self.getDescription(), ) @staticmethod def mayRaiseException(exception_type): # Virtual method overload, pylint: disable=unused-argument # An exception would be considered a side effect too. return False class CompileTimeConstantExpressionBase(ExpressionNoSideEffectsMixin, ExpressionBase): # TODO: Do this for all computations, do this in the base class of all # nodes. __slots__ = ("computed_attribute",) def __init__(self, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.computed_attribute = None @staticmethod def isCompileTimeConstant(): """Has a value that we can use at compile time. Yes or no. If it has such a value, simulations can be applied at compile time and e.g. operations or conditions, or even calls may be executed against it. """ return True def getTruthValue(self): return bool(self.getCompileTimeConstant()) def getComparisonValue(self): return True, self.getCompileTimeConstant() @abstractmethod def getCompileTimeConstant(self): """Return compile time constant. Notes: Only available after passing "isCompileTimeConstant()". """ @staticmethod def isMutable(): """Return if compile time constant is mutable. Notes: Only useful after passing "isCompileTimeConstant()". """ return False @staticmethod def hasShapeTrustedAttributes(): # All compile time constants must be fixed for attributes. return True @staticmethod def mayHaveSideEffectsBool(): # Virtual method overload return False @staticmethod def mayRaiseExceptionBool(exception_type): return False def mayRaiseExceptionAttributeLookup(self, exception_type, attribute_name): # We remember it from our computation. return not self.computed_attribute def mayRaiseExceptionAttributeLookupSpecial(self, exception_type, attribute_name): # We remember it from our computation. return not self.computed_attribute def computeExpressionOperationNot(self, not_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=not_node, computation=lambda: not self.getCompileTimeConstant(), description="""\ Compile time constant negation truth value pre-computed.""", ) def computeExpressionOperationRepr(self, repr_node, trace_collection): return ( trace_collection.getCompileTimeComputationResult( node=repr_node, computation=lambda: repr(self.getCompileTimeConstant()), description="""\ Compile time constant repr value pre-computed.""", ), None, ) def computeExpressionLen(self, len_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=len_node, computation=lambda: len(self.getCompileTimeConstant()), description="""\ Compile time constant len value pre-computed.""", ) def computeExpressionAbs(self, abs_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=abs_node, computation=lambda: abs(self.getCompileTimeConstant()), description="""\ Compile time constant abs value pre-computed.""", ) def computeExpressionInt(self, int_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=int_node, computation=lambda: int(self.getCompileTimeConstant()), description="""\ Compile time constant int value pre-computed.""", ) def computeExpressionLong(self, long_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=long_node, computation=lambda: long(self.getCompileTimeConstant()), description="""\ Compile time constant long value pre-computed.""", ) def computeExpressionFloat(self, float_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=float_node, computation=lambda: float(self.getCompileTimeConstant()), description="""\ Compile time constant float value pre-computed.""", ) def computeExpressionBytes(self, bytes_node, trace_collection): constant_value = self.getCompileTimeConstant() if type(constant_value) in (int, long): if constant_value > 1000: return bytes_node, None, None return trace_collection.getCompileTimeComputationResult( node=bytes_node, computation=lambda: bytes(constant_value), description="""\ Compile time constant bytes value pre-computed.""", ) def isKnownToHaveAttribute(self, attribute_name): if self.computed_attribute is None: self.computed_attribute = hasattr( self.getCompileTimeConstant(), attribute_name ) return self.computed_attribute def getKnownAttributeValue(self, attribute_name): return getattr(self.getCompileTimeConstant(), attribute_name) def computeExpressionAttribute(self, lookup_node, attribute_name, trace_collection): value = self.getCompileTimeConstant() if self.computed_attribute is None: self.computed_attribute = hasattr(value, attribute_name) # If it raises, or the attribute itself is a compile time constant, # then do execute it. if not self.computed_attribute or isCompileTimeConstantValue( getattr(value, attribute_name, None) ): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: getattr(value, attribute_name), description="Attribute '%s' pre-computed." % (attribute_name), ) return lookup_node, None, None def computeExpressionSubscript(self, lookup_node, subscript, trace_collection): if subscript.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[ subscript.getCompileTimeConstant() ], description="Subscript of constant with constant value.", ) # TODO: Look-up of subscript to index may happen. # Any code could be run due to that, note that. trace_collection.onControlFlowEscape(self) trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def computeExpressionSlice(self, lookup_node, lower, upper, trace_collection): # TODO: Could be happy with predictable index values and not require # constants. if lower is not None: if upper is not None: if lower.isCompileTimeConstant() and upper.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[ lower.getCompileTimeConstant() : upper.getCompileTimeConstant() ], description="Slicing of constant with constant indexes.", user_provided=False, ) else: if lower.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[ lower.getCompileTimeConstant() : ], description="Slicing of constant with constant lower index only.", user_provided=False, ) else: if upper is not None: if upper.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[ : upper.getCompileTimeConstant() ], description="Slicing of constant with constant upper index only.", user_provided=False, ) else: return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[:], description="Slicing of constant with no indexes.", user_provided=False, ) # Any exception might be raised, although it's not likely. trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def computeExpressionComparisonIn(self, in_node, value_node, trace_collection): if value_node.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=in_node, computation=lambda: in_node.getSimulator()( value_node.getCompileTimeConstant(), self.getCompileTimeConstant() ), description="""\ Predicted '%s' on compiled time constant values.""" % in_node.comparator, user_provided=False, ) # Look-up of __contains__ on compile time constants does mostly nothing. trace_collection.onExceptionRaiseExit(BaseException) return in_node, None, None def computeExpressionBool(self, trace_collection): constant = self.getCompileTimeConstant() assert type(constant) is not bool self.parent.replaceChild( self, makeConstantReplacementNode(bool(constant), self, user_provided=False) ) trace_collection.signalChange( tags="new_constant", source_ref=self.source_ref, message="Predicted compile time constant truth value.", ) class ExpressionChildrenHavingBase(ChildrenHavingMixin, ExpressionBase): def __init__(self, values, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) ChildrenHavingMixin.__init__(self, values=values) def computeExpressionRaw(self, trace_collection): """Compute an expression. Default behavior is to just visit the child expressions first, and then the node "computeExpression". For a few cases this needs to be overloaded, e.g. conditional expressions. """ # First apply the sub-expressions, as they are evaluated before # the actual operation. for count, sub_expression in enumerate(self.getVisitableNodes()): expression = trace_collection.onExpression(sub_expression) if expression.willRaiseException(BaseException): sub_expressions = self.getVisitableNodes() wrapped_expression = wrapExpressionWithSideEffects( side_effects=sub_expressions[:count], old_node=sub_expression, new_node=expression, ) return ( wrapped_expression, "new_raise", lambda: "For '%s' the child expression '%s' will raise." % (self.getChildNameNice(), expression.getChildNameNice()), ) # Then ask ourselves to work on it. return self.computeExpression(trace_collection=trace_collection) class ExpressionChildHavingBase(ExpressionBase): checker = None def __init__(self, value, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable if value is not None: value.parent = self attr_name = "subnode_" + self.named_child setattr(self, attr_name, value) def finalize(self): del self.parent attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) if value is not None: value.finalize() # TODO: De-duplicate this with multiple child variant. def computeExpressionRaw(self, trace_collection): """Compute an expression. Default behavior is to just visit the child expressions first, and then the node "computeExpression". For a few cases this needs to be overloaded, e.g. conditional expressions. """ # First apply the sub-expression, as they it's evaluated before. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) if value is not None: expression = trace_collection.onExpression(expression=value) if expression.willRaiseException(BaseException): return ( expression, "new_raise", lambda: "For '%s' the child expression '%s' will raise." % (self.getChildNameNice(), expression.getChildNameNice()), ) # Then ask ourselves to work on it. return self.computeExpression(trace_collection=trace_collection) def setChild(self, name, value): """Set a child value. Do not overload, provide self.checkers instead. """ # Only accept legal child name assert name == self.named_child, name if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable attr_name = "subnode_" + self.named_child # Checks if it's a real change in debug mode. if Options.is_debug: # Determine old value, and inform it about losing its parent. old_value = getattr(self, attr_name) assert old_value is not value, value # Re-parent value to us. if value is not None: value.parent = self setattr(self, attr_name, value) def clearChild(self, name): # Only accept legal child name assert name == self.named_child, name if self.checker is not None: self.checker(None) # False alarm, pylint: disable=not-callable attr_name = "subnode_" + name # Determine old value, and inform it about losing its parent. old_value = getattr(self, attr_name) assert old_value is not None setattr(self, attr_name, None) def getChild(self, name): # Only accept legal child name assert name == self.named_child, name attr_name = "subnode_" + name return getattr(self, attr_name) def getVisitableNodes(self): # TODO: attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) # In this case, generator is not faster. if value is None: return () else: return (value,) def getVisitableNodesNamed(self): """Named children items. For generic code to use in outputs and code generation. """ attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) yield self.named_child, value def replaceChild(self, old_node, new_node): if new_node is not None and not isinstance(new_node, NodeBase): raise AssertionError( "Cannot replace with", new_node, "old", old_node, "in", self ) # Find the replaced node, as an added difficulty, what might be # happening, is that the old node is an element of a tuple, in which we # may also remove that element, by setting it to None. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) if old_node is value: new_node.parent = self setattr(self, attr_name, new_node) else: raise AssertionError("Didn't find child", old_node, "in", self) def getCloneArgs(self): # Make clones of child nodes too. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) values = {self.named_child: value.makeClone()} values.update(self.getDetails()) return values class ExpressionChildTupleHavingBase(ExpressionBase): checker = None def __init__(self, value, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable assert type(value) is tuple, self.named_child assert None not in value, self.named_child for expression in value: expression.parent = self attr_name = "subnode_" + self.named_child setattr(self, attr_name, value) def finalize(self): del self.parent for c in self.getVisitableNodes(): c.finalize() # TODO: De-duplicate this with multiple child variant. def computeExpressionRaw(self, trace_collection): """Compute an expression. Default behavior is to just visit the child expressions first, and then the node "computeExpression". For a few cases this needs to be overloaded, e.g. conditional expressions. """ # First apply the sub-expressions, as they are evaluated before. sub_expressions = self.getVisitableNodes() for count, sub_expression in enumerate(sub_expressions): assert sub_expression.isExpression(), (self, sub_expression) expression = trace_collection.onExpression(expression=sub_expression) if expression.willRaiseException(BaseException): wrapped_expression = wrapExpressionWithSideEffects( side_effects=sub_expressions[:count], old_node=sub_expression, new_node=expression, ) return ( wrapped_expression, "new_raise", lambda: "For '%s' the child expression '%s' will raise." % (self.getChildNameNice(), expression.getChildNameNice()), ) # Then ask ourselves to work on it. return self.computeExpression(trace_collection=trace_collection) def setChild(self, name, value): """Set a child value. Do not overload, provide self.checkers instead. """ # Only accept legal child name assert name == self.named_child, name # Lists as inputs are OK, but turn them into tuples. if type(value) is list: value = tuple(value) if self.checker is not None: value = self.checker(value) # False alarm, pylint: disable=not-callable # Re-parent value to us. for val in value: val.parent = self attr_name = "subnode_" + name setattr(self, attr_name, value) def clearChild(self, name): # We do not do this for tuples, pylint: disable=unused-argument assert False, self.named_child def getChild(self, name): # Only accept legal child names assert name == self.named_child, name attr_name = "subnode_" + name return getattr(self, attr_name) def getVisitableNodes(self): attr_name = "subnode_" + self.named_child return getattr(self, attr_name) def getVisitableNodesNamed(self): """Named children items. For generic code to use in outputs and code generation. """ attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) yield self.named_child, value def replaceChild(self, old_node, new_node): if new_node is not None and not isinstance(new_node, NodeBase): raise AssertionError( "Cannot replace with", new_node, "old", old_node, "in", self ) # Find the replaced node, as an added difficulty, what might be # happening, is that the old node is an element of a tuple, in which we # may also remove that element, by setting it to None. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) if old_node not in value: raise AssertionError("Didn't find child", old_node, "in", self) if new_node is not None: new_value = tuple( (val if val is not old_node else new_node) for val in value ) else: new_value = tuple(val for val in value if val is not old_node) new_node.parent = self setattr(self, attr_name, new_value) def getCloneArgs(self): # Make clones of child nodes too. attr_name = "subnode_" + self.named_child value = getattr(self, attr_name) values = {self.named_child: tuple(v.makeClone() for v in value)} values.update(self.getDetails()) return values class ExpressionSpecBasedComputationMixin(object): # Mixins are not allow to specify slots. __slots__ = () builtin_spec = None def computeBuiltinSpec(self, trace_collection, given_values): assert self.builtin_spec is not None, self if not self.builtin_spec.isCompileTimeComputable(given_values): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin_spec.simulateCall(given_values), description="Built-in call to '%s' pre-computed." % (self.builtin_spec.getName()), ) class ExpressionSpecBasedComputationNoRaiseMixin(object): # Mixins are not allow to specify slots. __slots__ = () builtin_spec = None def computeBuiltinSpec(self, trace_collection, given_values): assert self.builtin_spec is not None, self if not self.builtin_spec.isCompileTimeComputable(given_values): return self, None, None return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin_spec.simulateCall(given_values), description="Built-in call to '%s' pre-computed." % (self.builtin_spec.getName()), ) class ExpressionBuiltinSingleArgBase( ExpressionSpecBasedComputationMixin, ExpressionChildHavingBase ): named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) def computeExpression(self, trace_collection): value = self.subnode_value if value is None: return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=() ) else: return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=(value,) ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinIteratorNodes.py0000600000372100037210000002731314166627112027363 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in iterator nodes. These play a role in for loops, and in unpacking. They can something be predicted to succeed or fail, in which case, code can become less complex. The length of things is an important optimization issue for these to be good. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ( ExpressionBuiltinSingleArgBase, ExpressionChildrenHavingBase, ) from .NodeBases import StatementChildHavingBase from .NodeMakingHelpers import ( makeRaiseExceptionReplacementStatement, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, wrapExpressionWithSideEffects, ) from .shapes.StandardShapes import tshape_iterator class ExpressionBuiltinIter1(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_BUILTIN_ITER1" simulator = iter def computeExpression(self, trace_collection): trace_collection.initIteratorValue(self) return self.subnode_value.computeExpressionIter1( iter_node=self, trace_collection=trace_collection ) def computeExpressionIter1(self, iter_node, trace_collection): # Iteration over an iterator is that iterator. return self, "new_builtin", "Eliminated useless iterator creation." def getTypeShape(self): return self.subnode_value.getTypeShape().getShapeIter() def computeExpressionNext1(self, next_node, trace_collection): value = self.subnode_value if value.isKnownToBeIterableAtMin(1) and value.canPredictIterationValues(): result = wrapExpressionWithSideEffects( new_node=value.getIterationValue(0), old_node=value, side_effects=value.getIterationValueRange(1, None), ) return False, ( result, "new_expression", "Predicted 'next' value from iteration.", ) # TODO: This is only true for a few value types, use type shape to tell if # it might escape or raise. self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return True, (next_node, None, None) def isKnownToBeIterable(self, count): if count is None: return True iter_length = self.subnode_value.getIterationLength() return iter_length == count def isKnownToBeIterableAtMin(self, count): assert type(count) is int iter_length = self.subnode_value.getIterationMinLength() return iter_length is not None and count <= iter_length def getIterationLength(self): return self.subnode_value.getIterationLength() def canPredictIterationValues(self): return self.subnode_value.canPredictIterationValues() def getIterationValue(self, element_index): return self.subnode_value.getIterationValue(element_index) def getIterationHandle(self): return self.subnode_value.getIterationHandle() def extractSideEffects(self): # Iterator making is the side effect itself. value = self.subnode_value if value.isCompileTimeConstant() and value.isKnownToBeIterable(None): return () else: return (self,) def mayHaveSideEffects(self): value = self.subnode_value if value.isCompileTimeConstant(): return not value.isKnownToBeIterable(None) return True def mayRaiseException(self, exception_type): value = self.subnode_value if value.mayRaiseException(exception_type): return True if value.isKnownToBeIterable(None): return False return True def mayRaiseExceptionOperation(self): value = self.subnode_value return value.isKnownToBeIterable(None) is not True def onRelease(self, trace_collection): # print "onRelease", self pass class ExpressionBuiltinIterForUnpack(ExpressionBuiltinIter1): kind = "EXPRESSION_BUILTIN_ITER_FOR_UNPACK" def computeExpression(self, trace_collection): trace_collection.initIteratorValue(self) result = self.subnode_value.computeExpressionIter1( iter_node=self, trace_collection=trace_collection ) result_node = result[0] # Rewrite exceptions to correct message. if ( result_node.isExpressionRaiseException() and result_node.subnode_exception_type.isExpressionBuiltinExceptionRef() and result_node.subnode_exception_type.getExceptionName() == "TypeError" ): return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="cannot unpack non-iterable %s object", operation="iter", original_node=self, value_node=self.subnode_value, ) return result @staticmethod def simulator(value): try: return iter(value) except TypeError: raise TypeError( "cannot unpack non-iterable %s object" % (type(value).__name__) ) class StatementSpecialUnpackCheck(StatementChildHavingBase): kind = "STATEMENT_SPECIAL_UNPACK_CHECK" named_child = "iterator" __slots__ = ("count",) def __init__(self, iterator, count, source_ref): StatementChildHavingBase.__init__(self, value=iterator, source_ref=source_ref) self.count = int(count) def getDetails(self): return {"count": self.getCount()} def getCount(self): return self.count def computeStatement(self, trace_collection): iterator = trace_collection.onExpression(self.subnode_iterator) if iterator.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if iterator.willRaiseException(BaseException): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=iterator, node=self ) return ( result, "new_raise", """\ Explicit raise already raises implicitly building exception type.""", ) if ( iterator.isExpressionTempVariableRef() and iterator.variable_trace.isAssignTrace() ): iterator = iterator.variable_trace.getAssignNode().subnode_source current_index = trace_collection.getIteratorNextCount(iterator) else: current_index = None if current_index is not None: iter_length = iterator.getIterationLength() if iter_length is not None: # Remove the check if it can be decided at compile time. if current_index == iter_length: return ( None, "new_statements", """\ Determined iteration end check to be always true.""", ) else: result = makeRaiseExceptionReplacementStatement( statement=self, exception_type="ValueError", exception_value="too many values to unpack" if python_version < 0x300 else "too many values to unpack (expected %d)" % self.getCount(), ) trace_collection.onExceptionRaiseExit(TypeError) return ( result, "new_raise", """\ Determined iteration end check to always raise.""", ) trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getStatementNiceName(): return "iteration check statement" class ExpressionBuiltinIter2(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_ITER2" named_children = ("callable_arg", "sentinel") def __init__(self, callable_arg, sentinel, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"callable_arg": callable_arg, "sentinel": sentinel}, source_ref=source_ref, ) @staticmethod def getTypeShape(): # TODO: This could be more specific, this one is a fixed thing! return tshape_iterator def computeExpression(self, trace_collection): # TODO: The "callable" should be investigated here, maybe it is not # really callable, or raises an exception. return self, None, None def computeExpressionIter1(self, iter_node, trace_collection): return self, "new_builtin", "Eliminated useless iterator creation." class ExpressionAsyncIter(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_ASYNC_ITER" def computeExpression(self, trace_collection): value = self.subnode_value return value.computeExpressionAsyncIter( iter_node=self, trace_collection=trace_collection ) def isKnownToBeIterable(self, count): if count is None: return True # TODO: Should ask value if it is. return None def getIterationLength(self): return self.subnode_value.getIterationLength() def extractSideEffects(self): # Iterator making is the side effect itself. if self.subnode_value.isCompileTimeConstant(): return () else: return (self,) def mayHaveSideEffects(self): if self.subnode_value.isCompileTimeConstant(): return self.subnode_value.isKnownToBeIterable(None) return True def mayRaiseException(self, exception_type): value = self.subnode_value if value.mayRaiseException(exception_type): return True if value.isKnownToBeIterable(None): return False return True def isKnownToBeIterableAtMin(self, count): assert type(count) is int iter_length = self.subnode_value.getIterationMinLength() return iter_length is not None and iter_length < count def onRelease(self, trace_collection): # print "onRelease", self pass class ExpressionAsyncNext(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_ASYNC_NEXT" def __init__(self, value, source_ref): ExpressionBuiltinSingleArgBase.__init__( self, value=value, source_ref=source_ref ) def computeExpression(self, trace_collection): # TODO: Predict iteration result if possible via SSA variable trace of # the iterator state. # Assume exception is possible. TODO: We might query the next from the # source with a computeExpressionAsyncNext slot, but we delay that. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/CallNodes.py0000600000372100037210000001215714166627112025116 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Call node Function calls and generally calling expressions are the same thing. This is very important, because it allows to predict most things, and avoid expensive operations like parameter parsing at run time. There will be a method "computeExpressionCall" to aid predicting them in other nodes. """ from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) class ExpressionCall(ExpressionChildrenHavingBase): kind = "EXPRESSION_CALL" named_children = ("called", "args", "kwargs") def __init__(self, called, args, kwargs, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"called": called, "args": args, "kwargs": kwargs}, source_ref=source_ref, ) @staticmethod def isExpressionCall(): return True def computeExpression(self, trace_collection): called = self.subnode_called return called.computeExpressionCall( call_node=self, call_args=self.subnode_args, call_kw=self.subnode_kwargs, trace_collection=trace_collection, ) def extractSideEffectsPreCall(self): args = self.subnode_args kw = self.subnode_kwargs return args.extractSideEffects() + kw.extractSideEffects() class ExpressionCallNoKeywords(ExpressionChildrenHavingBase): kind = "EXPRESSION_CALL_NO_KEYWORDS" named_children = ("called", "args") subnode_kwargs = None def __init__(self, called, args, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"called": called, "args": args}, source_ref=source_ref ) def computeExpression(self, trace_collection): called = self.subnode_called return called.computeExpressionCall( call_node=self, call_args=self.subnode_args, call_kw=None, trace_collection=trace_collection, ) @staticmethod def isExpressionCall(): return True def extractSideEffectsPreCall(self): args = self.subnode_args return args.extractSideEffects() class ExpressionCallKeywordsOnly(ExpressionChildrenHavingBase): kind = "EXPRESSION_CALL_KEYWORDS_ONLY" named_children = ("called", "kwargs") subnode_args = None def __init__(self, called, kwargs, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"called": called, "kwargs": kwargs}, source_ref=source_ref ) def computeExpression(self, trace_collection): called = self.subnode_called return called.computeExpressionCall( call_node=self, call_args=None, call_kw=self.subnode_kwargs, trace_collection=trace_collection, ) @staticmethod def isExpressionCall(): return True def extractSideEffectsPreCall(self): kw = self.subnode_kwargs return kw.extractSideEffects() class ExpressionCallEmpty(ExpressionChildHavingBase): kind = "EXPRESSION_CALL_EMPTY" named_child = "called" subnode_args = None subnode_kwargs = None def __init__(self, called, source_ref): ExpressionChildHavingBase.__init__(self, value=called, source_ref=source_ref) def computeExpression(self, trace_collection): called = self.subnode_called return called.computeExpressionCall( call_node=self, call_args=None, call_kw=None, trace_collection=trace_collection, ) @staticmethod def isExpressionCall(): return True @staticmethod def extractSideEffectsPreCall(): return () def makeExpressionCall(called, args, kw, source_ref): """Make the most simple call node possible. By avoiding the more complex classes, we can achieve that there is less work to do for analysis. """ has_kw = kw is not None and not kw.isExpressionConstantDictEmptyRef() has_args = args is not None and not args.isExpressionConstantTupleEmptyRef() if has_kw: if has_args: return ExpressionCall(called, args, kw, source_ref) else: return ExpressionCallKeywordsOnly(called, kw, source_ref) else: if has_args: return ExpressionCallNoKeywords(called, args, source_ref) else: return ExpressionCallEmpty(called, source_ref) Nuitka-0.6.19.1/nuitka/nodes/CoroutineNodes.py0000600000372100037210000001051014166627112026201 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for coroutine objects and their creations. Coroutines are turned into normal functions that create generator objects, whose implementation lives here. The creation itself also lives here. """ from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionNoSideEffectsMixin, ) from .FunctionNodes import ExpressionFunctionEntryPointBase class ExpressionMakeCoroutineObject( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_MAKE_COROUTINE_OBJECT" named_child = "coroutine_ref" __slots__ = ("variable_closure_traces",) def __init__(self, coroutine_ref, source_ref): assert coroutine_ref.getFunctionBody().isExpressionCoroutineObjectBody() ExpressionChildHavingBase.__init__( self, value=coroutine_ref, source_ref=source_ref ) self.variable_closure_traces = None def getDetailsForDisplay(self): return {"coroutine": self.subnode_coroutine_ref.getFunctionBody().getCodeName()} def computeExpression(self, trace_collection): self.variable_closure_traces = [] for ( closure_variable ) in self.subnode_coroutine_ref.getFunctionBody().getClosureVariables(): trace = trace_collection.getVariableCurrentTrace(closure_variable) trace.addNameUsage() self.variable_closure_traces.append((closure_variable, trace)) # TODO: Coroutine body may know something too. return self, None, None def getClosureVariableVersions(self): return self.variable_closure_traces class ExpressionCoroutineObjectBody(ExpressionFunctionEntryPointBase): kind = "EXPRESSION_COROUTINE_OBJECT_BODY" __slots__ = ("qualname_setup", "needs_generator_return_exit") def __init__(self, provider, name, code_object, flags, auto_release, source_ref): ExpressionFunctionEntryPointBase.__init__( self, provider=provider, name=name, code_object=code_object, code_prefix="coroutine", flags=flags, auto_release=auto_release, source_ref=source_ref, ) self.needs_generator_return_exit = False self.qualname_setup = None def getFunctionName(self): return self.name def markAsNeedsGeneratorReturnHandling(self, value): self.needs_generator_return_exit = max(self.needs_generator_return_exit, value) def needsGeneratorReturnHandling(self): return self.needs_generator_return_exit == 2 def needsGeneratorReturnExit(self): return bool(self.needs_generator_return_exit) @staticmethod def needsCreation(): return False @staticmethod def isUnoptimized(): return False class ExpressionAsyncWait(ExpressionChildHavingBase): kind = "EXPRESSION_ASYNC_WAIT" named_child = "expression" __slots__ = ("exception_preserving",) def __init__(self, expression, source_ref): ExpressionChildHavingBase.__init__( self, value=expression, source_ref=source_ref ) self.exception_preserving = False @staticmethod def isExpressionAsyncWait(): return True def computeExpression(self, trace_collection): # TODO: Might be predictable based awaitable analysis or for constants. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionAsyncWaitEnter(ExpressionAsyncWait): kind = "EXPRESSION_ASYNC_WAIT_ENTER" class ExpressionAsyncWaitExit(ExpressionAsyncWait): kind = "EXPRESSION_ASYNC_WAIT_EXIT" Nuitka-0.6.19.1/nuitka/nodes/GeneratorNodes.py0000600000372100037210000001405014166627112026163 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for generator objects and their creations. Generators are turned into normal functions that create generator objects, whose implementation lives here. The creation itself also lives here. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionNoSideEffectsMixin, ) from .FunctionNodes import ExpressionFunctionEntryPointBase from .IndicatorMixins import MarkUnoptimizedFunctionIndicatorMixin from .ReturnNodes import StatementReturn, StatementReturnNone class ExpressionMakeGeneratorObject( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_MAKE_GENERATOR_OBJECT" named_child = "generator_ref" __slots__ = ("variable_closure_traces",) def __init__(self, generator_ref, source_ref): assert ( generator_ref.getFunctionBody().isExpressionGeneratorObjectBody() ), generator_ref ExpressionChildHavingBase.__init__( self, value=generator_ref, source_ref=source_ref ) self.variable_closure_traces = None def getCodeObject(self): return self.code_object def computeExpression(self, trace_collection): self.variable_closure_traces = [] for ( closure_variable ) in self.subnode_generator_ref.getFunctionBody().getClosureVariables(): trace = trace_collection.getVariableCurrentTrace(closure_variable) trace.addNameUsage() self.variable_closure_traces.append((closure_variable, trace)) # TODO: Generator body may know something too. return self, None, None def getClosureVariableVersions(self): return self.variable_closure_traces class ExpressionGeneratorObjectBody( MarkUnoptimizedFunctionIndicatorMixin, ExpressionFunctionEntryPointBase ): kind = "EXPRESSION_GENERATOR_OBJECT_BODY" __slots__ = ( "unoptimized_locals", "unqualified_exec", "needs_generator_return_exit", "qualname_provider", ) if python_version >= 0x340: __slots__ += ("qualname_setup",) def __init__(self, provider, name, code_object, flags, auto_release, source_ref): ExpressionFunctionEntryPointBase.__init__( self, provider=provider, name=name, code_object=code_object, code_prefix="genexpr" if name == "" else "genobj", flags=flags, auto_release=auto_release, source_ref=source_ref, ) MarkUnoptimizedFunctionIndicatorMixin.__init__(self, flags) self.needs_generator_return_exit = False self.trace_collection = None if python_version >= 0x340: self.qualname_setup = None def getFunctionName(self): return self.name def markAsNeedsGeneratorReturnHandling(self, value): self.needs_generator_return_exit = max(self.needs_generator_return_exit, value) def needsGeneratorReturnHandling(self): return self.needs_generator_return_exit == 2 def needsGeneratorReturnExit(self): return bool(self.needs_generator_return_exit) @staticmethod def needsCreation(): return False def getConstantReturnValue(self): """Special function that checks if code generation allows to use common C code.""" body = self.subnode_body if body is None: return True, None return False, False class StatementGeneratorReturn(StatementReturn): kind = "STATEMENT_GENERATOR_RETURN" def __init__(self, expression, source_ref): StatementReturn.__init__(self, expression=expression, source_ref=source_ref) @staticmethod def isStatementGeneratorReturn(): return True def computeStatement(self, trace_collection): expression = trace_collection.onExpression(self.subnode_expression) if expression.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if expression.willRaiseException(BaseException): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=expression, node=self ) return ( result, "new_raise", """\ Return statement raises in returned expression, removed return.""", ) trace_collection.onFunctionReturn() if expression.isExpressionConstantNoneRef(): result = StatementGeneratorReturnNone(source_ref=self.source_ref) return ( result, "new_statements", """\ Generator return value is always None.""", ) return self, None, None @staticmethod def getStatementNiceName(): return "generator return statement" class StatementGeneratorReturnNone(StatementReturnNone): kind = "STATEMENT_GENERATOR_RETURN_NONE" __slots__ = () def __init__(self, source_ref): StatementReturnNone.__init__(self, source_ref=source_ref) @staticmethod def isStatementGeneratorReturn(): return True @staticmethod def getStatementNiceName(): return "generator return statement" Nuitka-0.6.19.1/nuitka/nodes/ExpressionShapeMixins.py0000600000372100037210000004754414166627112027572 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Mixins for expressions that have specific shapes. Providing derived implementation, such that e.g. for a given shape, shortcuts are automatically implemented. """ from abc import abstractmethod from nuitka.Constants import ( the_empty_bytearray, the_empty_dict, the_empty_frozenset, the_empty_list, the_empty_set, the_empty_slice, the_empty_tuple, ) from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, ) from .shapes.BuiltinTypeShapes import ( tshape_bool, tshape_bytearray, tshape_bytes, tshape_complex, tshape_dict, tshape_ellipsis, tshape_float, tshape_frozenset, tshape_int, tshape_int_or_long, tshape_list, tshape_long, tshape_none, tshape_set, tshape_slice, tshape_str, tshape_str_derived, tshape_str_or_unicode, tshape_str_or_unicode_derived, tshape_tuple, tshape_unicode, tshape_unicode_derived, ) class ExpressionSpecificDerivedMixinBase(object): """Mixin that provides all shapes exactly false overloads. This is to be used as a base class for specific or derived shape mixins, such that they automatically provide false for all other exact shape checks except the one they care about. """ __slots__ = () @staticmethod def hasShapeNoneExact(): return False @staticmethod def hasShapeBoolExact(): return False @staticmethod def hasShapeDictionaryExact(): return False @staticmethod def hasShapeListExact(): return False @staticmethod def hasShapeSetExact(): return False @staticmethod def hasShapeFrozesetExact(): return False @staticmethod def hasShapeTupleExact(): return False @staticmethod def hasShapeStrExact(): return False @staticmethod def hasShapeUnicodeExact(): return False @staticmethod def hasShapeStrOrUnicodeExact(): return False @staticmethod def hasShapeBytesExact(): return False @staticmethod def hasShapeBytearrayExact(): return False @staticmethod def hasShapeFloatExact(): return False @staticmethod def hasShapeComplexExact(): return False @staticmethod def hasShapeIntExact(): return False @staticmethod def hasShapeLongExact(): return False @staticmethod def hasShapeSliceExact(): return False class ExpressionSpecificExactMixinBase(ExpressionSpecificDerivedMixinBase): """Mixin that provides attribute knowledge for exact type shapes. This is to be used as a base class for specific shape mixins, such that they automatically provide false for all other exact shape checks except the one they care about. """ __slots__ = () @staticmethod def hasShapeTrustedAttributes(): return True @abstractmethod def isKnownToHaveAttribute(self, attribute_name): return True @abstractmethod def getKnownAttributeValue(self, attribute_name): """Can be used as isKnownToHaveAttribute is True""" def mayRaiseExceptionAttributeLookup(self, exception_type, attribute_name): # TODO: The exception_type is not checked, pylint: disable=unused-argument return not self.isKnownToHaveAttribute(attribute_name) @staticmethod def mayRaiseExceptionBool(exception_type): # We cannot raise anything, pylint: disable=unused-argument return False @staticmethod def mayHaveSideEffectsBool(): return False class ExpressionNonIterableTypeShapeMixin(object): """Mixin for nodes known to not be iterable.""" __slots__ = () @staticmethod def getIterationLength(): return None @staticmethod def isKnownToBeIterable(count): # virtual method overload, pylint: disable=unused-argument return False @staticmethod def isKnownToBeIterableAtMin(count): # virtual method overload, pylint: disable=unused-argument return False @staticmethod def canPredictIterationValues(): return False def computeExpressionIter1(self, iter_node, trace_collection): shape = self.getTypeShape() assert shape.hasShapeSlotIter() is False # An exception will be raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="iter", original_node=iter_node, value_node=self, ) class ExpressionIterableTypeShapeMixin(object): """Mixin for nodes known to not be iterable.""" __slots__ = () # Bad Implementation that the node can use, based on getIterationLength, which def isKnownToBeIterable(self, count): return count is None or self.getIterationLength() == count def isKnownToBeIterableAtMin(self, count): length = self.getIterationLength() return length is not None and length >= count def canPredictIterationValues(self): return self.isKnownToBeIterable(None) class ExpressionDictShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact dictionary shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_dict @staticmethod def hasShapeDictionaryExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_dict, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_dict, attribute_name) @staticmethod def isKnownToBeHashable(): return False def extractUnhashableNodeType(self): return makeConstantReplacementNode( constant=dict, node=self, user_provided=False ) class ExpressionListShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact list shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_list @staticmethod def hasShapeListExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_list, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_list, attribute_name) @staticmethod def isKnownToBeHashable(): return False def extractUnhashableNodeType(self): return makeConstantReplacementNode( constant=list, node=self, user_provided=False ) class ExpressionFrozensetShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact frozenset shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_frozenset @staticmethod def hasShapeListExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_frozenset, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_frozenset, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionSetShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact set shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_set @staticmethod def hasShapeSetExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_set, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_set, attribute_name) @staticmethod def isKnownToBeHashable(): return False def extractUnhashableNodeType(self): return makeConstantReplacementNode(constant=set, node=self, user_provided=False) class ExpressionTupleShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact tuple shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_tuple @staticmethod def hasShapeSetExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_tuple, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_tuple, attribute_name) @staticmethod def isKnownToBeHashable(): return None class ExpressionBoolShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact bool shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_bool @staticmethod def hasShapeBoolExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(False, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(False, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionStrShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact str shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_str @staticmethod def hasShapeStrExact(): return True @staticmethod def hasShapeStrOrUnicodeExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr("", attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr("", attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionBytesShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact bytes shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_bytes @staticmethod def hasShapeBytesExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(b"", attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(b"", attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionBytearrayShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact bytearray shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_bytearray @staticmethod def hasShapeBytearrayExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_bytearray, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_bytearray, attribute_name) @staticmethod def isKnownToBeHashable(): return False def extractUnhashableNodeType(self): return makeConstantReplacementNode( constant=bytearray, node=self, user_provided=False ) class ExpressionUnicodeShapeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact unicode shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_unicode @staticmethod def hasShapeUnicodeExact(): return True @staticmethod def hasShapeStrOrUnicodeExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(u"", attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(u"", attribute_name) @staticmethod def isKnownToBeHashable(): return True if str is not bytes: ExpressionStrOrUnicodeExactMixin = ExpressionStrShapeExactMixin else: class ExpressionStrOrUnicodeExactMixin( ExpressionIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with str_or_unicode shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_str_or_unicode @staticmethod def hasShapeStrOrUnicodeExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(u"", attribute_name) and hasattr("", attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr("", attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionFloatShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact float shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_float @staticmethod def hasShapeFloatExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(0.0, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(0.0, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionIntShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact int shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_int @staticmethod def hasShapeIntExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(0, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(0, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionLongShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact long shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_long @staticmethod def hasShapeLongExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(tshape_long.typical_value, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(tshape_long.typical_value, attribute_name) @staticmethod def isKnownToBeHashable(): return True if str is not bytes: ExpressionIntOrLongExactMixin = ExpressionIntShapeExactMixin else: class ExpressionIntOrLongExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with int_or_long shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_int_or_long @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(0, attribute_name) and hasattr( tshape_long.typical_value, attribute_name ) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(0, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionEllipsisShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact ellipsis shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_ellipsis @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(Ellipsis, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(Ellipsis, attribute_name) @staticmethod def isKnownToBeHashable(): return True @staticmethod def getTruthValue(): """Return known truth value.""" return True class ExpressionNoneShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact None shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_none @staticmethod def hasShapeNoneExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(None, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(None, attribute_name) @staticmethod def isKnownToBeHashable(): return True @staticmethod def getTruthValue(): """Return known truth value.""" return False class ExpressionComplexShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact complex shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_complex @staticmethod def hasShapeComplexExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): # These vary with instances, constant values should not enter here. if attribute_name in ("imag", "real"): return False return hasattr(0j, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(0j, attribute_name) @staticmethod def isKnownToBeHashable(): return True class ExpressionSliceShapeExactMixin( ExpressionNonIterableTypeShapeMixin, ExpressionSpecificExactMixinBase ): """Mixin for nodes with exact complex shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_slice @staticmethod def hasShapeSliceExact(): return True @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(the_empty_slice, attribute_name) @staticmethod def getKnownAttributeValue(attribute_name): return getattr(the_empty_slice, attribute_name) @staticmethod def isKnownToBeHashable(): return False class ExpressionStrDerivedShapeMixin(ExpressionSpecificDerivedMixinBase): """Mixin for nodes with str derived shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_str_derived class ExpressionUnicodeDerivedShapeMixin(ExpressionSpecificDerivedMixinBase): """Mixin for nodes with unicode derived shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_unicode_derived if str is not bytes: ExpressionStrOrUnicodeDerivedShapeMixin = ExpressionUnicodeDerivedShapeMixin else: class ExpressionStrOrUnicodeDerivedShapeMixin(ExpressionSpecificDerivedMixinBase): """Mixin for nodes with str or unicode derived shape.""" __slots__ = () @staticmethod def getTypeShape(): return tshape_str_or_unicode_derived Nuitka-0.6.19.1/nuitka/nodes/FunctionAttributeNodes.py0000600000372100037210000000662314166627112027715 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Function attribute nodes The represent special values of the modules. The "__qualname__" value node is intended and to be resolved later. And the function output for error messages, is also dynamic. These nodes are intended to allow for as much compile time optimization as possible, despite this difficulty. In some modes these node become constants quickly, in others they will present boundaries for optimization. """ from .ExpressionBases import ( CompileTimeConstantExpressionBase, ExpressionChildHavingBase, ) from .NodeBases import SideEffectsFromChildrenMixin from .NodeMakingHelpers import makeConstantReplacementNode class ExpressionFunctionQualnameRef(CompileTimeConstantExpressionBase): """Node for value __qualname__ of function or class. Notes: This is for Python 3.4 and higher only, where classes calculate the __qualname__ value at runtime, then it's determined dynamically, while 3.3 set it more statically, and Python2 didn't have this feature at all. """ kind = "EXPRESSION_FUNCTION_QUALNAME_REF" __slots__ = ("function_body",) def __init__(self, function_body, source_ref): CompileTimeConstantExpressionBase.__init__(self, source_ref=source_ref) self.function_body = function_body def finalize(self): del self.parent del self.function_body def computeExpressionRaw(self, trace_collection): result = makeConstantReplacementNode( node=self, constant=self.function_body.getFunctionQualname(), user_provided=True, ) return ( result, "new_constant", "Executed '__qualname__' resolution to '%s'." % self.function_body.getFunctionQualname(), ) def getCompileTimeConstant(self): return self.function_body.getFunctionQualname() class ExpressionFunctionErrorStr( SideEffectsFromChildrenMixin, ExpressionChildHavingBase ): """Node for value "_PyObject_FunctionStr" C-API of function or callable in general. Notes: This is for Python 3.9 and higher only, where functions have their module added to the "__qualname__" value at runtime. """ kind = "EXPRESSION_FUNCTION_ERROR_STR" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value, source_ref=source_ref) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseException(exception_type) def computeExpression(self, trace_collection): # TODO: Could compile time compute these for concrete functions. return self, None, None Nuitka-0.6.19.1/nuitka/nodes/ConstantRefNodes.py0000600000372100037210000012434514166627112026474 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for constant expressions. Can be all common built-in types. """ import sys from abc import abstractmethod from nuitka import Options from nuitka.__past__ import ( GenericAlias, UnionType, iterItems, long, unicode, xrange, ) from nuitka.Builtins import ( builtin_anon_values, builtin_exception_values_list, builtin_named_values, ) from nuitka.Constants import ( getUnhashableConstant, isConstant, isHashable, isMutable, the_empty_dict, the_empty_frozenset, the_empty_list, the_empty_set, the_empty_tuple, ) from nuitka.PythonVersions import python_version from nuitka.Tracing import optimization_logger from .ExpressionBases import CompileTimeConstantExpressionBase from .ExpressionShapeMixins import ( ExpressionBoolShapeExactMixin, ExpressionBytearrayShapeExactMixin, ExpressionBytesShapeExactMixin, ExpressionComplexShapeExactMixin, ExpressionDictShapeExactMixin, ExpressionEllipsisShapeExactMixin, ExpressionFloatShapeExactMixin, ExpressionFrozensetShapeExactMixin, ExpressionIntShapeExactMixin, ExpressionListShapeExactMixin, ExpressionLongShapeExactMixin, ExpressionNoneShapeExactMixin, ExpressionSetShapeExactMixin, ExpressionSliceShapeExactMixin, ExpressionStrShapeExactMixin, ExpressionTupleShapeExactMixin, ExpressionUnicodeShapeExactMixin, ) from .IterationHandles import ( ConstantBytearrayIterationHandle, ConstantBytesIterationHandle, ConstantDictIterationHandle, ConstantFrozensetIterationHandle, ConstantListIterationHandle, ConstantRangeIterationHandle, ConstantSetIterationHandle, ConstantStrIterationHandle, ConstantTupleIterationHandle, ConstantUnicodeIterationHandle, ) from .NodeMakingHelpers import ( makeRaiseExceptionReplacementExpression, wrapExpressionWithSideEffects, ) from .shapes.BuiltinTypeShapes import ( tshape_namedtuple, tshape_type, tshape_xrange, ) class ExpressionConstantUntrackedRefBase(CompileTimeConstantExpressionBase): __slots__ = ("constant",) def __init__(self, constant, source_ref): CompileTimeConstantExpressionBase.__init__(self, source_ref=source_ref) self.constant = constant def finalize(self): del self.parent del self.constant def __repr__(self): return "" % ( self.kind, self.constant, self.source_ref.getAsString(), ) def getDetails(self): return {"constant": self.constant} def getDetailsForDisplay(self): result = self.getDetails() if "constant" in result: result["constant"] = repr(result["constant"]) return result @staticmethod def isExpressionConstantRef(): return True def computeExpressionRaw(self, trace_collection): # Cannot compute any further, this is already the best. return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): trace_collection.onExceptionRaiseExit(TypeError) # The arguments don't matter. All constant values cannot be called, and # we just need to make and error out of that. new_node = wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpression( expression=self, exception_type="TypeError", exception_value="'%s' object is not callable" % type(self.constant).__name__, ), old_node=call_node, side_effects=call_node.extractSideEffectsPreCall(), ) return ( new_node, "new_raise", "Predicted call of constant %s value to exception raise." % type(self.constant), ) def getCompileTimeConstant(self): return self.constant # TODO: Push this to singletons for being static functions def getComparisonValue(self): return True, self.constant @staticmethod def getIterationHandle(): return None def isMutable(self): # This is expected to be overloaded by child classes. assert False, self def isKnownToBeHashable(self): # This is expected to be overloaded by child classes. assert False, self def extractUnhashableNodeType(self): value = getUnhashableConstant(self.constant) if value is not None: return makeConstantRefNode(constant=type(value), source_ref=self.source_ref) @staticmethod def isNumberConstant(): # This is expected to be overloaded by child classes that disagree, bool, int, long and float return False @staticmethod def isIndexConstant(): # This is expected to be overloaded by child classes that disagree, bool, int, long and float return False def isIndexable(self): # TODO: Suspiciously this doesn't use isIndexConstant, which includes float, bug? return self.constant is None or self.isNumberConstant() def isKnownToBeIterable(self, count): if self.isIterableConstant(): return count is None or len(self.constant) == count else: return False def isKnownToBeIterableAtMin(self, count): length = self.getIterationLength() return length is not None and length >= count def canPredictIterationValues(self): return self.isKnownToBeIterable(None) def getIterationValue(self, count): assert count < len(self.constant) return makeConstantRefNode( constant=self.constant[count], source_ref=self.source_ref ) def getIterationValueRange(self, start, stop): return [ makeConstantRefNode(constant=value, source_ref=self.source_ref) for value in self.constant[start:stop] ] def getIterationValues(self): source_ref = self.source_ref return tuple( makeConstantRefNode( constant=value, source_ref=source_ref, user_provided=self.user_provided ) for value in self.constant ) def getIntegerValue(self): if self.isNumberConstant(): return int(self.constant) else: return None @abstractmethod def isIterableConstant(self): """Is the constant type iterable.""" # This is expected to be overloaded by child classes, but it's actually wasteful # to use it, we should have overloads of using methods too. def getIterationLength(self): # This is expected to be overloaded by child classes if they are iterable assert not self.isIterableConstant(), self return None def getStrValue(self): return makeConstantRefNode( constant=str(self.constant), user_provided=False, source_ref=self.source_ref, ) def computeExpressionIter1(self, iter_node, trace_collection): # Note, this is overloaded for all the others. assert not self.isIterableConstant() # TODO: Raise static exception. return iter_node, None, None class ExpressionConstantRefBase(ExpressionConstantUntrackedRefBase): """Constants reference base class. Use this for cases, for which it makes sense to track origin, e.g. large lists are from computation or from user literals. """ # Base classes can be abstract, pylint: disable=I0021,abstract-method __slots__ = ("user_provided",) def __init__(self, constant, user_provided, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) self.user_provided = user_provided if not user_provided and Options.is_debug: try: if type(constant) in (str, unicode, bytes): max_size = 1000 elif type(constant) is xrange: max_size = None else: max_size = 256 if max_size is not None and len(constant) > max_size: optimization_logger.warning( "Too large constant (%s %d) encountered at %s." % ( type(constant), len(constant), source_ref.getAsString(), ) ) except TypeError: pass def getDetails(self): return {"constant": self.constant, "user_provided": self.user_provided} def __repr__(self): return "" % ( self.kind, self.constant, self.source_ref.getAsString(), self.user_provided, ) def getStrValue(self): try: return makeConstantRefNode( constant=str(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) except UnicodeEncodeError: # Unicode constants may not be possible to encode. return None class ExpressionConstantNoneRef( ExpressionNoneShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_NONE_REF" __slots__ = () def __init__(self, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=None, source_ref=source_ref ) @staticmethod def getDetails(): return {} @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return False class ExpressionConstantBoolRefBase( ExpressionBoolShapeExactMixin, ExpressionConstantUntrackedRefBase ): @staticmethod def isExpressionConstantBoolRef(): return True def computeExpressionBool(self, trace_collection): # Best case already. pass @staticmethod def getDetails(): return {} @staticmethod def isMutable(): return False @staticmethod def isKnownToBeHashable(): return True @staticmethod def isNumberConstant(): return True @staticmethod def isIndexConstant(): return True @staticmethod def isIterableConstant(): return False class ExpressionConstantTrueRef(ExpressionConstantBoolRefBase): kind = "EXPRESSION_CONSTANT_TRUE_REF" __slots__ = () def __init__(self, source_ref): ExpressionConstantBoolRefBase.__init__( self, constant=True, source_ref=source_ref ) @staticmethod def getTruthValue(): """Return known truth value.""" return True @staticmethod def getIndexValue(): return 1 class ExpressionConstantFalseRef(ExpressionConstantBoolRefBase): kind = "EXPRESSION_CONSTANT_FALSE_REF" __slots__ = () def __init__(self, source_ref): ExpressionConstantBoolRefBase.__init__( self, constant=False, source_ref=source_ref ) @staticmethod def getTruthValue(): """Return known truth value.""" return False @staticmethod def getIndexValue(): return 0 class ExpressionConstantEllipsisRef( ExpressionEllipsisShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_ELLIPSIS_REF" __slots__ = () def __init__(self, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=Ellipsis, source_ref=source_ref ) @staticmethod def getDetails(): return {} @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return False class ExpressionConstantDictRef( ExpressionDictShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_DICT_REF" def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantDictRef(): return True @staticmethod def isMutable(): return True @staticmethod def isKnownToBeHashable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantDictIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): result = makeConstantRefNode( constant=tuple(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) self.finalize() return ( iter_node, "new_constant", """Iteration over constant dict lowered to tuple.""", ) def isMappingWithConstantStringKeys(self): return all(type(key) in (str, unicode) for key in self.constant) def getMappingStringKeyPairs(self): pairs = [] for key, value in iterItems(self.constant): pairs.append( ( key, makeConstantRefNode( constant=value, user_provided=self.user_provided, source_ref=self.source_ref, ), ) ) return pairs @staticmethod def getTruthValue(): """Return known truth value. The empty dict is not allowed here, so we can hardcode it. """ return True class EmptyContainerMixin(object): __slots__ = () def getDetails(self): return {"user_provided": self.user_provided} @staticmethod def getIterationLength(): return 0 @staticmethod def getTruthValue(): """Return known truth value. The empty container is false, so we can hardcode it. """ return False class ExpressionConstantDictEmptyRef(EmptyContainerMixin, ExpressionConstantDictRef): kind = "EXPRESSION_CONSTANT_DICT_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantDictRef.__init__( self, constant=the_empty_dict, user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantTupleRef( ExpressionTupleShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_TUPLE_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantTupleRef(): return True @staticmethod def isMutable(): return False def isKnownToBeHashable(self): # There are a few exceptions, where non-mutable can be non-hashable, e.g. slice. return isHashable(self.constant) @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantTupleIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): # Note: Tuples are as good as it gets. return iter_node, None, None @staticmethod def getTruthValue(): """Return known truth value. The empty dict is not allowed here, so we can hardcode it. """ return True class ExpressionConstantTupleMutableRef(ExpressionConstantTupleRef): kind = "EXPRESSION_CONSTANT_TUPLE_MUTABLE_REF" __slots__ = () @staticmethod def isMutable(): return True @staticmethod def isKnownToBeHashable(): return False class ExpressionConstantTupleEmptyRef(EmptyContainerMixin, ExpressionConstantTupleRef): kind = "EXPRESSION_CONSTANT_TUPLE_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantTupleRef.__init__( self, constant=the_empty_tuple, user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantListRef( ExpressionListShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_LIST_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantListRef(): return True @staticmethod def isMutable(): return True @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantListIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): result = makeConstantRefNode( constant=tuple(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) self.finalize() return ( iter_node, "new_constant", """Iteration over constant list lowered to tuple.""", ) class ExpressionConstantListEmptyRef(EmptyContainerMixin, ExpressionConstantListRef): kind = "EXPRESSION_CONSTANT_LIST_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantListRef.__init__( self, constant=the_empty_list, user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantSetRef(ExpressionSetShapeExactMixin, ExpressionConstantRefBase): kind = "EXPRESSION_CONSTANT_SET_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantSetRef(): return True @staticmethod def isMutable(): return True @staticmethod def isKnownToBeHashable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantSetIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): result = makeConstantRefNode( constant=tuple(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) self.finalize() return ( iter_node, "new_constant", """Iteration over constant set lowered to tuple.""", ) class ExpressionConstantSetEmptyRef(EmptyContainerMixin, ExpressionConstantSetRef): kind = "EXPRESSION_CONSTANT_SET_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantSetRef.__init__( self, constant=the_empty_set, user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantFrozensetRef( ExpressionFrozensetShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_FROZENSET_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantFrozensetRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantFrozensetIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): result = makeConstantRefNode( constant=tuple(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) self.finalize() return ( iter_node, "new_constant", """Iteration over constant frozenset lowered to tuple.""", ) class ExpressionConstantFrozensetEmptyRef( EmptyContainerMixin, ExpressionConstantFrozensetRef ): kind = "EXPRESSION_CONSTANT_FROZENSET_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantFrozensetRef.__init__( self, constant=the_empty_frozenset, user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantIntRef( ExpressionIntShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_INT_REF" __slots__ = () def __init__(self, constant, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) @staticmethod def isExpressionConstantIntRef(): return True @staticmethod def isMutable(): return False @staticmethod def isNumberConstant(): return True @staticmethod def isIndexConstant(): return True def getIndexValue(self): return self.constant @staticmethod def isIterableConstant(): return False class ExpressionConstantLongRef( ExpressionLongShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_LONG_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantLongRef(): return True @staticmethod def isMutable(): return False @staticmethod def isNumberConstant(): return True @staticmethod def isIndexConstant(): return True def getIndexValue(self): # Use the int value if possible, otherwise that remains a long, which is # also OK, but often unnecessary. return int(self.constant) @staticmethod def isIterableConstant(): return False class ExpressionConstantStrRef(ExpressionStrShapeExactMixin, ExpressionConstantRefBase): kind = "EXPRESSION_CONSTANT_STR_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantStrRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantStrIterationHandle(self) def getIterationLength(self): return len(self.constant) def getStrValue(self): return self def getStringValue(self): return self.constant def computeExpressionIter1(self, iter_node, trace_collection): # Note: str are as good as it gets. return iter_node, None, None class ExpressionConstantStrEmptyRef(EmptyContainerMixin, ExpressionConstantStrRef): kind = "EXPRESSION_CONSTANT_STR_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantStrRef.__init__( self, constant="", user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantUnicodeRef( ExpressionUnicodeShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_UNICODE_REF" __slots__ = () def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantUnicodeRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantUnicodeIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): # Note: unicode are as good as it gets return iter_node, None, None class ExpressionConstantUnicodeEmptyRef( EmptyContainerMixin, ExpressionConstantUnicodeRef ): kind = "EXPRESSION_CONSTANT_UNICODE_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantUnicodeRef.__init__( self, constant=u"", user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantBytesRef( ExpressionBytesShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_BYTES_REF" def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantBytesRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantBytesIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): # Note: bytes are as good as it gets return iter_node, None, None class ExpressionConstantBytesEmptyRef(EmptyContainerMixin, ExpressionConstantBytesRef): kind = "EXPRESSION_CONSTANT_BYTES_EMPTY_REF" __slots__ = () def __init__(self, user_provided, source_ref): ExpressionConstantBytesRef.__init__( self, constant=b"", user_provided=user_provided, source_ref=source_ref, ) class ExpressionConstantBytearrayRef( ExpressionBytearrayShapeExactMixin, ExpressionConstantRefBase ): kind = "EXPRESSION_CONSTANT_BYTEARRAY_REF" def __init__(self, constant, user_provided, source_ref): ExpressionConstantRefBase.__init__( self, constant=constant, user_provided=user_provided, source_ref=source_ref ) @staticmethod def isExpressionConstantBytearrayRef(): return True @staticmethod def isMutable(): return True @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantBytearrayIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): result = makeConstantRefNode( constant=bytes(self.constant), user_provided=self.user_provided, source_ref=self.source_ref, ) self.parent.replaceChild(self, result) self.finalize() return ( iter_node, "new_constant", """Iteration over constant bytesarray lowered to bytes.""", ) class ExpressionConstantFloatRef( ExpressionFloatShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_FLOAT_REF" __slots__ = () def __init__(self, constant, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) @staticmethod def isExpressionConstantFloatRef(): return True @staticmethod def isMutable(): return False @staticmethod def isNumberConstant(): return True @staticmethod def isIterableConstant(): return False class ExpressionConstantComplexRef( ExpressionComplexShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_COMPLEX_REF" __slots__ = () def __init__(self, constant, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) @staticmethod def isExpressionConstantComplexRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return False # Overload what ExpressionComplexShapeExactMixin says, for a given instance we know all. @staticmethod def isKnownToHaveAttribute(attribute_name): return hasattr(0j, attribute_name) class ExpressionConstantSliceRef( ExpressionSliceShapeExactMixin, ExpressionConstantUntrackedRefBase ): kind = "EXPRESSION_CONSTANT_SLICE_REF" __slots__ = () def __init__(self, constant, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) @staticmethod def isExpressionConstantSliceRef(): return True @staticmethod def isMutable(): return False @staticmethod def isIterableConstant(): return False class ExpressionConstantXrangeRef(ExpressionConstantUntrackedRefBase): kind = "EXPRESSION_CONSTANT_XRANGE_REF" __slots__ = () def __init__(self, constant, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=constant, source_ref=source_ref ) @staticmethod def isExpressionConstantXrangeRef(): return True @staticmethod def getTypeShape(): return tshape_xrange @staticmethod def isMutable(): return False @staticmethod def isKnownToBeHashable(): return True @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantRangeIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): # Note: xrange are as good as it gets. return iter_node, None, None class ExpressionConstantTypeRef(ExpressionConstantUntrackedRefBase): kind = "EXPRESSION_CONSTANT_TYPE_REF" __slots__ = () @staticmethod def isExpressionConstantTypeRef(): return True @staticmethod def getTypeShape(): return tshape_type def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): from nuitka.optimizations.OptimizeBuiltinCalls import ( computeBuiltinCall, ) # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) new_node, tags, message = computeBuiltinCall( builtin_name=self.constant.__name__, call_node=call_node ) return new_node, tags, message @staticmethod def isMutable(): return False @staticmethod def isKnownToBeHashable(): return True @staticmethod def isIterableConstant(): return False @staticmethod def getTruthValue(): return True class ExpressionConstantTypeSubscriptableRef(ExpressionConstantTypeRef): kind = "EXPRESSION_CONSTANT_TYPE_SUBSCRIPTABLE_REF" __slots__ = () def computeExpressionSubscript(self, lookup_node, subscript, trace_collection): if subscript.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=lookup_node, computation=lambda: self.getCompileTimeConstant()[ subscript.getCompileTimeConstant() ], description="Subscript of subscriptable type with constant value.", ) # TODO: Not true, in fact these should become GenericAlias always. trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def makeConstantRefNode(constant, source_ref, user_provided=False): # This is dispatching per constant value and types, every case # to be a return statement, pylint: disable=too-many-branches,too-many-return-statements,too-many-statements # Dispatch based on constants first. if constant is None: return ExpressionConstantNoneRef(source_ref=source_ref) elif constant is True: return ExpressionConstantTrueRef(source_ref=source_ref) elif constant is False: return ExpressionConstantFalseRef(source_ref=source_ref) elif constant is Ellipsis: return ExpressionConstantEllipsisRef(source_ref=source_ref) else: # Next, dispatch based on type. constant_type = type(constant) if constant_type is int: return ExpressionConstantIntRef(constant=constant, source_ref=source_ref) elif constant_type is str: if constant: return ExpressionConstantStrRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantStrEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is float: return ExpressionConstantFloatRef(constant=constant, source_ref=source_ref) elif constant_type is long: return ExpressionConstantLongRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) elif constant_type is unicode: if constant: return ExpressionConstantUnicodeRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantUnicodeEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is bytes: if constant: return ExpressionConstantBytesRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantBytesEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is dict: if constant: assert isConstant(constant), repr(constant) return ExpressionConstantDictRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantDictEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is tuple: if constant: assert isConstant(constant), repr(constant) if isMutable(constant): return ExpressionConstantTupleMutableRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantTupleRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantTupleEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is list: if constant: assert isConstant(constant), repr(constant) return ExpressionConstantListRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantListEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is set: if constant: assert isConstant(constant), repr(constant) return ExpressionConstantSetRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantSetEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is frozenset: if constant: assert isConstant(constant), repr(constant) return ExpressionConstantFrozensetRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) else: return ExpressionConstantFrozensetEmptyRef( user_provided=user_provided, source_ref=source_ref, ) elif constant_type is complex: return ExpressionConstantComplexRef( constant=constant, source_ref=source_ref, ) elif constant_type is slice: return ExpressionConstantSliceRef( constant=constant, source_ref=source_ref, ) elif constant_type is type: if python_version >= 0x390 and constant in ( set, frozenset, tuple, list, dict, ): return ExpressionConstantTypeSubscriptableRef( constant=constant, source_ref=source_ref ) return ExpressionConstantTypeRef(constant=constant, source_ref=source_ref) elif constant_type is xrange: return ExpressionConstantXrangeRef( constant=constant, source_ref=source_ref, ) elif constant_type is bytearray: return ExpressionConstantBytearrayRef( constant=constant, user_provided=user_provided, source_ref=source_ref, ) elif constant in builtin_anon_values: from .BuiltinRefNodes import ExpressionBuiltinAnonymousRef return ExpressionBuiltinAnonymousRef( builtin_name=builtin_anon_values[constant], source_ref=source_ref, ) elif constant in builtin_named_values: from .BuiltinRefNodes import ExpressionBuiltinRef return ExpressionBuiltinRef( builtin_name=builtin_named_values[constant], source_ref=source_ref ) elif constant in builtin_exception_values_list: from .BuiltinRefNodes import ExpressionBuiltinExceptionRef if constant is NotImplemented: exception_name = "NotImplemented" else: exception_name = constant.__name__ return ExpressionBuiltinExceptionRef( exception_name=exception_name, source_ref=source_ref ) elif constant_type is GenericAlias: from .BuiltinTypeNodes import ExpressionConstantGenericAlias return ExpressionConstantGenericAlias( generic_alias=constant, source_ref=source_ref ) elif constant_type is UnionType: from .BuiltinTypeNodes import ExpressionConstantUnionType return ExpressionConstantUnionType( union_type=constant, source_ref=source_ref ) elif constant is sys.version_info: return ExpressionConstantSysVersionInfoRef(source_ref=source_ref) else: # Missing constant type, ought to not happen, please report. assert False, (constant, constant_type) class ExpressionConstantSysVersionInfoRef(ExpressionConstantUntrackedRefBase): kind = "EXPRESSION_CONSTANT_SYS_VERSION_INFO_REF" __slots__ = () def __init__(self, source_ref): ExpressionConstantUntrackedRefBase.__init__( self, constant=sys.version_info, source_ref=source_ref ) @staticmethod def getDetails(): return {} @staticmethod def getTypeShape(): return tshape_namedtuple @staticmethod def isMutable(): return False @staticmethod def isKnownToBeHashable(): return True @staticmethod def isIterableConstant(): return True def getIterationHandle(self): return ConstantTupleIterationHandle(self) def getIterationLength(self): return len(self.constant) def computeExpressionIter1(self, iter_node, trace_collection): # For iteration, we are just a normal tuple. return ( ExpressionConstantTupleRef( self.constant, user_provided=True, source_ref=self.source_ref ), "new_constant", """Iteration over constant sys.version_info lowered to tuple.""", ) @staticmethod def getTruthValue(): return True Nuitka-0.6.19.1/nuitka/nodes/__init__.py0000600000372100037210000000150114166627112025000 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/nodes/ReturnNodes.py0000600000372100037210000001513614166627112025522 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Return node This one exits functions. The only other exit is the default exit of functions with 'None' value, if no return is done. """ from abc import abstractmethod from .NodeBases import StatementBase, StatementChildHavingBase class StatementReturn(StatementChildHavingBase): kind = "STATEMENT_RETURN" named_child = "expression" nice_child = "return value" def __init__(self, expression, source_ref): assert expression StatementChildHavingBase.__init__(self, value=expression, source_ref=source_ref) @staticmethod def mayReturn(): return True @staticmethod def isStatementAborting(): return True def mayRaiseException(self, exception_type): return self.subnode_expression.mayRaiseException(exception_type) def computeStatement(self, trace_collection): expression = trace_collection.onExpression(self.subnode_expression) if expression.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) if expression.willRaiseException(BaseException): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=expression, node=self ) return ( result, "new_raise", """\ Return statement raises in returned expression, removed return.""", ) trace_collection.onFunctionReturn() if expression.isExpressionConstantRef(): result = makeStatementReturnConstant( constant=expression.getCompileTimeConstant(), source_ref=self.source_ref ) del self.parent return ( result, "new_statements", """\ Return value is constant.""", ) return self, None, None class StatementReturnConstantBase(StatementBase): __slots__ = () def __init__(self, source_ref): StatementBase.__init__(self, source_ref=source_ref) @staticmethod def isStatementReturn(): return True @staticmethod def isStatementReturnConstant(): return True @staticmethod def isStatementAborting(): return True @staticmethod def mayReturn(): return True @staticmethod def mayRaiseException(exception_type): return False def computeStatement(self, trace_collection): trace_collection.onFunctionReturn() return self, None, None @abstractmethod def getConstant(self): """The returned constant value.""" @staticmethod def getStatementNiceName(): return "return statement" class StatementReturnNone(StatementReturnConstantBase): kind = "STATEMENT_RETURN_NONE" __slots__ = () def __init__(self, source_ref): StatementReturnConstantBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent def getConstant(self): return None class StatementReturnFalse(StatementReturnConstantBase): kind = "STATEMENT_RETURN_FALSE" __slots__ = () def __init__(self, source_ref): StatementReturnConstantBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent def getConstant(self): return False class StatementReturnTrue(StatementReturnConstantBase): kind = "STATEMENT_RETURN_TRUE" __slots__ = () def __init__(self, source_ref): StatementReturnConstantBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent def getConstant(self): return True class StatementReturnConstant(StatementReturnConstantBase): kind = "STATEMENT_RETURN_CONSTANT" __slots__ = ("constant",) def __init__(self, constant, source_ref): StatementReturnConstantBase.__init__(self, source_ref=source_ref) self.constant = constant def finalize(self): del self.parent del self.constant def getConstant(self): return self.constant def getDetails(self): return {"constant": self.constant} class StatementReturnReturnedValue(StatementBase): kind = "STATEMENT_RETURN_RETURNED_VALUE" __slots__ = () def __init__(self, source_ref): StatementBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent @staticmethod def isStatementReturnReturnedValue(): return True @staticmethod def isStatementReturn(): return True @staticmethod def isStatementAborting(): return True @staticmethod def mayReturn(): return True @staticmethod def mayRaiseException(exception_type): return False def computeStatement(self, trace_collection): trace_collection.onFunctionReturn() return self, None, None @staticmethod def getStatementNiceName(): return "rereturn statement" def makeStatementReturnConstant(constant, source_ref): if constant is None: return StatementReturnNone(source_ref=source_ref) elif constant is True: return StatementReturnTrue(source_ref=source_ref) elif constant is False: return StatementReturnFalse(source_ref=source_ref) else: return StatementReturnConstant(constant=constant, source_ref=source_ref) def makeStatementReturn(expression, source_ref): """Create the best return statement variant.""" if expression is None: return StatementReturnNone(source_ref=source_ref) elif expression.isCompileTimeConstant(): return makeStatementReturnConstant( constant=expression.getCompileTimeConstant(), source_ref=source_ref ) else: return StatementReturn(expression=expression, source_ref=source_ref) Nuitka-0.6.19.1/nuitka/nodes/BuiltinAllNodes.py0000600000372100037210000000735714166627112026310 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Batakrishna Sahu, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'all' built-in. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ExpressionBuiltinSingleArgBase from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, wrapExpressionWithNodeSideEffects, ) from .shapes.BuiltinTypeShapes import tshape_str, tshape_unicode class ExpressionBuiltinAll( ExpressionBoolShapeExactMixin, ExpressionBuiltinSingleArgBase ): """Builtin All Node class. Args: ExpressionBase: 'all - expression' Returns: Node that represents built-in 'all' call. """ kind = "EXPRESSION_BUILTIN_ALL" builtin_spec = BuiltinParameterSpecs.builtin_all_spec def computeExpression(self, trace_collection): value = self.subnode_value shape = value.getTypeShape() if shape.hasShapeSlotIter() is False: # An exception is raised. trace_collection.onExceptionRaiseExit(BaseException) return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="all", original_node=value, value_node=value, ) if shape in (tshape_str, tshape_unicode): return ( wrapExpressionWithNodeSideEffects( new_node=makeConstantReplacementNode( constant=True, node=self, user_provided=False ), old_node=value, ), "new_constant", "Predicted truth value of built-in 'all' string type argument", ) iteration_handle = value.getIterationHandle() if iteration_handle is not None: all_true = iteration_handle.getAllElementTruthValue() if all_true is not None: result = wrapExpressionWithNodeSideEffects( new_node=makeConstantReplacementNode( constant=all_true, node=self, user_provided=False ), old_node=value, ) return ( result, "new_constant", "Predicted truth value of built-in 'all' argument", ) self.onContentEscapes(trace_collection) # All code could be run, note that. trace_collection.onControlFlowEscape(self) # All exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): """returns boolean True if try/except/finally is needed else False""" value = self.subnode_value if value.mayRaiseException(exception_type): return True return not value.getTypeShape().hasShapeSlotIter() Nuitka-0.6.19.1/nuitka/nodes/BuiltinOpenNodes.py0000600000372100037210000000623214166627112026470 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node the calls to the 'open' built-in. This is a rather two sided beast, as it may be read or write. And we would like to be able to track it, so we can include files into the executable, or write more efficiently. """ from nuitka.PythonVersions import python_version from .ExpressionBases import ExpressionChildrenHavingBase from .shapes.BuiltinTypeShapes import tshape_file class ExpressionBuiltinOpenMixin(object): # Mixins are required to slots __slots__ = () @staticmethod def getTypeShape(): return tshape_file def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # Note: Quite impossible to predict without further assumptions, but we could look # at the arguments at least. return self, None, None if python_version < 0x300: class ExpressionBuiltinOpen( ExpressionBuiltinOpenMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_OPEN" named_children = ("filename", "mode", "buffering") def __init__(self, filename, mode, buffering, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"filename": filename, "mode": mode, "buffering": buffering}, source_ref=source_ref, ) else: class ExpressionBuiltinOpen( ExpressionBuiltinOpenMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_BUILTIN_OPEN" named_children = ( "filename", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", ) def __init__( self, filename, mode, buffering, encoding, errors, newline, closefd, opener, source_ref, ): ExpressionChildrenHavingBase.__init__( self, values={ "filename": filename, "mode": mode, "buffering": buffering, "encoding": encoding, "errors": errors, "newline": newline, "closefd": closefd, "opener": opener, }, source_ref=source_ref, ) Nuitka-0.6.19.1/nuitka/nodes/BuiltinIntegerNodes.py0000600000372100037210000001215714166627112027167 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for the calls to the 'int' and 'long' (Python2) built-ins. These are divided into variants for one and two arguments and they have a common base class, because most of the behavior is the same there. The ones with 2 arguments only work on strings, and give errors otherwise, the ones with one argument, use slots, "__int__" and "__long__", so what they do does largely depend on the arguments slot. """ from nuitka.__past__ import long from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from .ConstantRefNodes import makeConstantRefNode from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionSpecBasedComputationMixin, ) from .ExpressionShapeMixins import ( ExpressionIntOrLongExactMixin, ExpressionLongShapeExactMixin, ) from .shapes.BuiltinTypeShapes import ( tshape_int_or_long_derived, tshape_long_derived, ) class ExpressionBuiltinInt1(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_INT1" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) @staticmethod def getTypeShape(): # TODO: Depending on input type shape and value, we should improve this. return tshape_int_or_long_derived def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionInt( int_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseExceptionInt(exception_type) class ExpressionBuiltinIntLong2Base( ExpressionSpecBasedComputationMixin, ExpressionChildrenHavingBase ): named_children = ("value", "base") # Note: Version specific, may be allowed or not. try: int(base=2) except TypeError: base_only_value = False else: base_only_value = True # To be overloaded by child classes with int/long. builtin = int def __init__(self, value, base, source_ref): if value is None and self.base_only_value: value = makeConstantRefNode( constant="0", source_ref=source_ref, user_provided=True ) ExpressionChildrenHavingBase.__init__( self, values={"value": value, "base": base}, source_ref=source_ref ) def computeExpression(self, trace_collection): value = self.subnode_value base = self.subnode_base if value is None: if base is not None: if not self.base_only_value: return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.builtin(base=2), description="""\ %s built-in call with only base argument""" % self.builtin.__name__, ) given_values = () else: given_values = (value, base) return self.computeBuiltinSpec( trace_collection=trace_collection, given_values=given_values ) class ExpressionBuiltinInt2( ExpressionIntOrLongExactMixin, ExpressionBuiltinIntLong2Base ): kind = "EXPRESSION_BUILTIN_INT2" builtin_spec = BuiltinParameterSpecs.builtin_int_spec builtin = int if python_version < 0x300: class ExpressionBuiltinLong1(ExpressionChildHavingBase): kind = "EXPRESSION_BUILTIN_LONG1" named_child = "value" def __init__(self, value, source_ref): ExpressionChildHavingBase.__init__(self, value=value, source_ref=source_ref) @staticmethod def getTypeShape(): # TODO: Depending on input type shape and value, we should improve this. return tshape_long_derived def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionLong( long_node=self, trace_collection=trace_collection ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseExceptionLong(exception_type) class ExpressionBuiltinLong2( ExpressionLongShapeExactMixin, ExpressionBuiltinIntLong2Base ): kind = "EXPRESSION_BUILTIN_LONG2" builtin_spec = BuiltinParameterSpecs.builtin_long_spec builtin = long Nuitka-0.6.19.1/nuitka/nodes/LoopNodes.py0000600000372100037210000003773214166627112025162 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Loop nodes. There are for and loop nodes, but both are reduced to loops with break/continue statements for it. These re-formulations require that optimization of loops has to be very general, yet the node type for loop, becomes very simple. """ from nuitka.optimizations.TraceCollections import TraceCollectionBranch from nuitka.tree.Extractions import getVariablesWrittenOrRead from .Checkers import checkStatementsSequenceOrNone from .NodeBases import StatementBase, StatementChildHavingBase from .shapes.StandardShapes import tshape_unknown, tshape_unknown_loop tshape_unknown_set = frozenset([tshape_unknown]) def minimizeShapes(shapes): # Merge some shapes automatically, no need to give a set. if tshape_unknown in shapes: return tshape_unknown_set return shapes class StatementLoop(StatementChildHavingBase): kind = "STATEMENT_LOOP" named_child = "loop_body" checker = checkStatementsSequenceOrNone __slots__ = ( "loop_variables", "loop_start", "loop_resume", "loop_previous_resume", "incomplete_count", ) def __init__(self, loop_body, source_ref): StatementChildHavingBase.__init__(self, value=loop_body, source_ref=source_ref) self.loop_variables = None # Traces of the variable at the start of loop, to detect changes and make # those restart optimization. self.loop_start = {} # Shapes currently known to be present when the loop is started or resumed # with continue statements. self.loop_resume = {} # Shapes from last time around, to detect the when it becomes complete, i.e. # we have seen it all. self.loop_previous_resume = {} # To allow an upper limit in case it doesn't terminate. self.incomplete_count = 0 def mayReturn(self): loop_body = self.subnode_loop_body if loop_body is not None and loop_body.mayReturn(): return True return False @staticmethod def mayBreak(): # The loop itself may never break another loop. return False @staticmethod def mayContinue(): # The loop itself may never continue another loop. return False def isStatementAborting(self): loop_body = self.subnode_loop_body if loop_body is None: return True else: return not loop_body.mayBreak() @staticmethod def mayRaiseException(exception_type): # Loops can only raise, if their body does, but they also issue the # async exceptions, so we must make them do it all the time. return True # loop_body = self.subnode_loop_body # return loop_body is not None and \ # self.subnode_loop_body.mayRaiseException(exception_type) def _computeLoopBody(self, trace_collection): # Rather complex stuff, pylint: disable=too-many-branches,too-many-locals,too-many-statements # print("Enter loop body", self.source_ref) loop_body = self.subnode_loop_body if loop_body is None: return None, None, None # Look ahead. what will be written and degrade to initial loop traces # about that if we are in the first iteration, later we # will have more # precise knowledge. if self.loop_variables is None: self.loop_variables = getVariablesWrittenOrRead(loop_body) all_first_pass = True else: all_first_pass = False # Track if we got incomplete knowledge due to loop. If so, we are not done, even # if no was optimization done, once we are complete, they can come. incomplete_variables = None # Mark all variables as loop wrap around that are written in the loop and # hit a 'continue' and make them become loop merges. We will strive to # reduce self.loop_variables if we find ones that have no change in all # 'continue' exits. loop_entry_traces = set() for loop_variable in self.loop_variables: current = trace_collection.getVariableCurrentTrace(loop_variable) if all_first_pass: first_pass = True # Remember what we started with, so we can detect changes from outside the # loop and make them restart the collection process, if the pre-conditions # got better. self.loop_start[loop_variable] = current else: if not self.loop_start[loop_variable].compareValueTrace(current): first_pass = True self.loop_start[loop_variable] = current else: first_pass = False if first_pass: incomplete = True self.loop_previous_resume[loop_variable] = None # Don't forget to initialize the loop resume traces with the starting point. We use # a special trace class that will not take the list too serious though. self.loop_resume[loop_variable] = set() current.getTypeShape().emitAlternatives( self.loop_resume[loop_variable].add ) else: if ( self.loop_resume[loop_variable] != self.loop_previous_resume[loop_variable] ): # print("incomplete", self.source_ref, loop_variable, ":", # self.loop_previous_resume[loop_variable], "<->", self.loop_resume[loop_variable]) incomplete = True if incomplete_variables is None: incomplete_variables = set() incomplete_variables.add(loop_variable) else: # print("complete", self.source_ref, loop_variable, ":", # self.loop_previous_resume[loop_variable], "<->", self.loop_resume[loop_variable]) incomplete = False # Mark the variable as loop usage before executing it. loop_entry_traces.add( ( loop_variable, trace_collection.markActiveVariableAsLoopMerge( loop_node=self, current=current, variable=loop_variable, shapes=self.loop_resume[loop_variable], incomplete=incomplete, ), ) ) abort_context = trace_collection.makeAbortStackContext( catch_breaks=True, catch_continues=True, catch_returns=False, catch_exceptions=False, ) with abort_context: # Forget all iterator and other value status. TODO: These should be using # more proper tracing to benefit. trace_collection.resetValueStates() result = loop_body.computeStatementsSequence( trace_collection=trace_collection ) # Might be changed. if result is not loop_body: self.setChild("loop_body", result) loop_body = result if loop_body is not None: # Emulate terminal continue if not aborting. if not loop_body.isStatementAborting(): trace_collection.onLoopContinue() continue_collections = trace_collection.getLoopContinueCollections() # Rebuild this with only the ones that actually changed in the loop. self.loop_variables = [] for loop_variable, loop_entry_trace in loop_entry_traces: # Giving up if self.incomplete_count >= 20: self.loop_previous_resume[loop_variable] = self.loop_resume[ loop_variable ] = set((tshape_unknown_loop,)) continue # Remember what it was at the start, to be able to tell if it changed. self.loop_previous_resume[loop_variable] = self.loop_resume[ loop_variable ] self.loop_resume[loop_variable] = set() loop_resume_traces = set( continue_collection.getVariableCurrentTrace(loop_variable) for continue_collection in continue_collections ) # Only if the variable is re-entering the loop, annotate that. if not loop_resume_traces or ( len(loop_resume_traces) == 1 and loop_entry_trace.compareValueTrace( next(iter(loop_resume_traces)) ) ): # Remove the variable, need not consider it # ever again. del self.loop_resume[loop_variable] del self.loop_previous_resume[loop_variable] del self.loop_start[loop_variable] continue # Keep this as a loop variable self.loop_variables.append(loop_variable) # Tell the loop trace about the continue traces. loop_entry_trace.addLoopContinueTraces(loop_resume_traces) # Also consider the entry trace before loop from here on. loop_resume_traces.add(self.loop_start[loop_variable]) shapes = set() for loop_resume_trace in loop_resume_traces: loop_resume_trace.getTypeShape().emitAlternatives(shapes.add) self.loop_resume[loop_variable] = minimizeShapes(shapes) # If we break, the outer collections becomes a merge of all those breaks # or just the one, if there is only one. break_collections = trace_collection.getLoopBreakCollections() if incomplete_variables: self.incomplete_count += 1 trace_collection.signalChange( "loop_analysis", self.source_ref, lambda: "Loop has incomplete variable types after %d attempts for '%s'." % ( self.incomplete_count, ",".join(variable.getName() for variable in incomplete_variables), ), ) else: if self.incomplete_count: trace_collection.signalChange( "loop_analysis", self.source_ref, lambda: "Loop has complete variable types after %d attempts." % self.incomplete_count, ) self.incomplete_count = 0 return loop_body, break_collections, continue_collections def computeStatement(self, trace_collection): outer_trace_collection = trace_collection trace_collection = TraceCollectionBranch(parent=trace_collection, name="loop") loop_body, break_collections, continue_collections = self._computeLoopBody( trace_collection ) if break_collections: outer_trace_collection.mergeMultipleBranches(break_collections) # Consider trailing "continue" statements, these have no effect, so we # can remove them. if loop_body is not None: assert loop_body.isStatementsSequence() statements = loop_body.subnode_statements assert statements # Cannot be empty # If the last statement is a "continue" statement, it can simply # be discarded. last_statement = statements[-1] if last_statement.isStatementLoopContinue(): if len(statements) == 1: self.subnode_body.finalize() self.clearChild("loop_body") loop_body = None else: last_statement.parent.replaceChild(last_statement, None) last_statement.finalize() trace_collection.signalChange( "new_statements", last_statement.getSourceReference(), """\ Removed useless terminal 'continue' as last statement of loop.""", ) elif last_statement.isStatementLoopBreak(): if not continue_collections and len(break_collections) == 1: loop_body = loop_body.removeStatement(last_statement) return ( loop_body, "new_statements", "Removed useless loop with only a break at the end.", ) # Consider leading "break" statements, they should be the only, and # should lead to removing the whole loop statement. Trailing "break" # statements could also be handled, but that would need to consider if # there are other "break" statements too. Numbering loop exits is # nothing we have yet. if loop_body is not None: assert loop_body.isStatementsSequence() statements = loop_body.subnode_statements assert statements # Cannot be empty if len(statements) == 1 and statements[-1].isStatementLoopBreak(): # TODO: Should be dead code now, due to the optimization above. assert False return ( None, "new_statements", """\ Removed useless loop with immediate 'break' statement.""", ) # Also consider the threading intermission. TODO: We ought to make it # explicit, so we can see it potentially disrupting and changing the # global variables. It may also raise. outer_trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getStatementNiceName(): return "loop statement" class StatementLoopContinue(StatementBase): kind = "STATEMENT_LOOP_CONTINUE" def __init__(self, source_ref): StatementBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent @staticmethod def isStatementAborting(): return True @staticmethod def mayRaiseException(exception_type): return False @staticmethod def mayContinue(): return True def computeStatement(self, trace_collection): # This statement being aborting, will already tell everything. trace_collection.onLoopContinue() return self, None, None @staticmethod def getStatementNiceName(): return "loop continue statement" class StatementLoopBreak(StatementBase): kind = "STATEMENT_LOOP_BREAK" def __init__(self, source_ref): StatementBase.__init__(self, source_ref=source_ref) def finalize(self): del self.parent @staticmethod def isStatementAborting(): return True @staticmethod def mayRaiseException(exception_type): return False @staticmethod def mayBreak(): return True def computeStatement(self, trace_collection): # This statement being aborting, will already tell everything. trace_collection.onLoopBreak() return self, None, None @staticmethod def getStatementNiceName(): return "loop break statement" Nuitka-0.6.19.1/nuitka/nodes/ImportNodes.py0000600000372100037210000010030114166627112025502 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes related to importing modules or names. Normally imports are mostly relatively static, but Nuitka also attempts to cover the uses of "__import__" built-in and other import techniques, that allow dynamic values. If other optimizations make it possible to predict these, the compiler can go deeper that what it normally could. The import expression node can lead to modules being added. After optimization it will be asked about used modules. """ import sys from nuitka.__past__ import long, unicode, xrange from nuitka.codegen.Reports import onMissingTrust from nuitka.importing.Importing import isPackageDir, locateModule from nuitka.importing.ImportResolving import resolveModuleName from nuitka.importing.StandardLibrary import isStandardLibraryPath from nuitka.Options import isStandaloneMode, shallWarnUnusualCode from nuitka.PythonVersions import ( getFutureModuleKeys, getImportlibSubPackages, python_version, ) from nuitka.specs.BuiltinParameterSpecs import ( BuiltinParameterSpec, extractBuiltinArgs, ) from nuitka.Tracing import unusual_logger from nuitka.utils.ModuleNames import ModuleName from .ConstantRefNodes import ( ExpressionConstantSysVersionInfoRef, makeConstantRefNode, ) from .ExpressionBases import ( ExpressionBase, ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .LocalsScopes import GlobalsDictHandle from .NodeBases import StatementChildHavingBase from .NodeMakingHelpers import makeRaiseExceptionReplacementExpression from .shapes.BuiltinTypeShapes import tshape_module, tshape_module_builtin # These module are supported in code generation to be imported the hard way. hard_modules = frozenset( ( "os", "sys", "types", "typing", "__future__", "site", "importlib", "_frozen_importlib", "_frozen_importlib_external", "pkgutil", "functools", ) ) hard_modules_version = { "typing": 0x350, "_frozen_importlib": 0x300, "_frozen_importlib_external": 0x350, } trust_undefined = 0 trust_constant = 1 trust_exist = 2 trust_future = trust_exist trust_importable = 3 trust_node = 4 trust_may_exist = 5 trust_not_exist = 6 trust_node_factory = {} module_importlib_trust = dict( (key, trust_importable) for key in getImportlibSubPackages() ) module_sys_trust = { "version": trust_constant, "hexversion": trust_constant, "platform": trust_constant, "maxsize": trust_constant, "builtin_module_names": trust_constant, "stdout": trust_exist, "stderr": trust_exist, } if python_version < 0x270: module_sys_trust["version_info"] = trust_constant else: module_sys_trust["version_info"] = trust_node trust_node_factory[("sys", "version_info")] = ExpressionConstantSysVersionInfoRef if python_version < 0x300: module_sys_trust["exc_type"] = trust_may_exist module_sys_trust["exc_value"] = trust_may_exist module_sys_trust["exc_traceback"] = trust_may_exist module_sys_trust["maxint"] = trust_constant module_sys_trust["subversion"] = trust_constant else: module_sys_trust["exc_type"] = trust_not_exist module_sys_trust["exc_value"] = trust_not_exist module_sys_trust["exc_traceback"] = trust_not_exist module_typing_trust = { "TYPE_CHECKING": trust_constant, } module_os_trust = {"name": trust_constant} hard_modules_trust = { "os": module_os_trust, "sys": module_sys_trust, "types": {}, "typing": module_typing_trust, "__future__": dict((key, trust_future) for key in getFutureModuleKeys()), "site": {}, "importlib": module_importlib_trust, "_frozen_importlib": {}, "_frozen_importlib_external": {}, "pkgutil": {"get_data": trust_exist}, "functools": {"partial": trust_exist}, } def isHardModuleWithoutSideEffect(module_name): return module_name in hard_modules and module_name != "site" class ExpressionImportModuleFixed(ExpressionBase): """Hard coded import names, that we know to exist." These created as result of builtin imports and "importlib.import_module" calls that were compile time resolved, and for known module names. """ kind = "EXPRESSION_IMPORT_MODULE_FIXED" __slots__ = ( "module_name", "found_module_name", "found_module_filename", "finding", ) def __init__(self, module_name, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.module_name = resolveModuleName(module_name) self.finding = None # If not found, we import the package at least ( self.found_module_name, self.found_module_filename, self.finding, ) = self._attemptFollow() def _attemptFollow(self): found_module_name, found_module_filename, finding = locateModule( module_name=self.module_name, parent_package=None, level=0, ) if self.finding == "not-found": while True: module_name = found_module_filename.getPackageName() if module_name is None: break found_module_name, found_module_filename, finding = locateModule( module_name=module_name, parent_package=None, level=0, ) if self.finding != "not-found": break return found_module_name, found_module_filename, finding def finalize(self): del self.parent def getDetails(self): return {"module_name": self.module_name} def getModuleName(self): return self.module_name @staticmethod def mayHaveSideEffects(): # TODO: For included modules, we might be able to tell, not not done now. return True @staticmethod def mayRaiseException(exception_type): # TODO: For included modules, we might be able to tell, not not done now. return True def getTypeShape(self): if self.module_name in sys.builtin_module_names: return tshape_module_builtin else: return tshape_module def getUsedModule(self): return self.found_module_name, self.found_module_filename, self.finding def computeExpressionRaw(self, trace_collection): if self.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) # Nothing to do about it. return self, None, None def computeExpressionImportName(self, import_node, import_name, trace_collection): # TODO: For include modules, something might be possible here. return self.computeExpressionAttribute( lookup_node=import_node, attribute_name=import_name, trace_collection=trace_collection, ) class ExpressionImportHardBase(ExpressionBase): # Base classes can be abstract, pylint: disable=abstract-method # __slots__ = ("module_name", "finding", "module_filename") def __init__(self, module_name, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.module_name = ModuleName(module_name) self.finding = None self.module_filename = None _module_name, self.module_filename, self.finding = locateModule( module_name=self.module_name, parent_package=None, level=0, ) # Expect to find them and to match the name of course. assert self.finding != "not-found", self.module_name assert _module_name == self.module_name def getUsedModule(self): return self.module_name, self.module_filename, self.finding class ExpressionImportModuleHard(ExpressionImportHardBase): """Hard coded import names, e.g. of "__future__" These are directly created for some Python mechanics, but also due to compile time optimization for imports of statically known modules. """ kind = "EXPRESSION_IMPORT_MODULE_HARD" __slots__ = ("module",) def __init__(self, module_name, source_ref): ExpressionImportHardBase.__init__( self, module_name=module_name, source_ref=source_ref ) if isHardModuleWithoutSideEffect(self.module_name): self.module = __import__(self.module_name) else: self.module = None def finalize(self): del self.parent def getDetails(self): return {"module_name": self.module_name} def getModuleName(self): return self.module_name def mayHaveSideEffects(self): return self.module is None def mayRaiseException(self, exception_type): return self.mayHaveSideEffects() def getTypeShape(self): if self.module_name in sys.builtin_module_names: return tshape_module_builtin else: return tshape_module def computeExpressionRaw(self, trace_collection): if self.finding is None: self._attemptFollow() if self.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def computeExpressionImportName(self, import_node, import_name, trace_collection): return self.computeExpressionAttribute( lookup_node=import_node, attribute_name=import_name, trace_collection=trace_collection, ) @staticmethod def _getImportNameErrorString(module, module_name, name): if python_version < 0x340: return "cannot import name %s" % name if python_version < 0x370: return "cannot import name %r" % name elif isStandaloneMode(): return "cannot import name %r from %r" % (name, module_name) else: return "cannot import name %r from %r (%s)" % ( name, module_name, module.__file__ if hasattr(module, "__file__") else "unknown location", ) def computeExpressionAttribute(self, lookup_node, attribute_name, trace_collection): # By default, an attribute lookup may change everything about the lookup # source. if self.module is not None: trust = hard_modules_trust[self.module_name].get( attribute_name, trust_undefined ) if trust is trust_importable: # TODO: Change this is a hard module import itself, currently these are not all trusted # themselves yet. We do not have to indicate exception, but it makes no sense to annotate # that here at this point. trace_collection.onExceptionRaiseExit(BaseException) elif trust is trust_may_exist: trace_collection.onExceptionRaiseExit(BaseException) elif ( not hasattr(self.module, attribute_name) and trust is not trust_undefined ): # TODO: Unify with below branches. trace_collection.onExceptionRaiseExit(ImportError) new_node = makeRaiseExceptionReplacementExpression( expression=lookup_node, exception_type="AttributeError", exception_value=self._getImportNameErrorString( self.module, self.module_name, attribute_name ), ) return ( new_node, "new_raise", "Hard module %r attribute missing %r pre-computed." % (self.module_name, attribute_name), ) else: if trust is trust_undefined: trace_collection.onExceptionRaiseExit(ImportError) onMissingTrust( "Hard module %r attribute %r missing trust config for existing value.", lookup_node.getSourceReference(), self.module_name, attribute_name, ) elif trust is trust_constant: # Make sure it's actually there, and not becoming the getattr default by accident. assert hasattr(self.module, attribute_name), self return ( makeConstantRefNode( constant=getattr(self.module, attribute_name), source_ref=lookup_node.getSourceReference(), user_provided=True, ), "new_constant", "Hard module '%s' imported %r pre-computed to constant value." % (self.module_name.asString(), attribute_name), ) elif trust is trust_node: result = trust_node_factory[self.module_name, attribute_name]( source_ref=lookup_node.source_ref ) return ( result, "new_expression", "Attribute lookup %r of hard module %r becomes node %r." % (self.module_name.asString(), attribute_name, result.kind), ) else: result = ExpressionImportModuleNameHard( module_name=self.module_name, import_name=attribute_name, source_ref=lookup_node.getSourceReference(), ) return ( result, "new_expression", "Attribute lookup %r of hard module %r becomes hard module name import." % (self.module_name, attribute_name), ) else: # Nothing can be known, but lets not do control flow escape, that is just # too unlikely. trace_collection.onExceptionRaiseExit(BaseException) return lookup_node, None, None def hasShapeTrustedAttributes(self): return True class ExpressionImportModuleNameHard(ExpressionImportHardBase): """Hard coded import names, e.g. of "os.path.dirname" These are directly created for some Python mechanics. """ kind = "EXPRESSION_IMPORT_MODULE_NAME_HARD" __slots__ = ("import_name", "trust", "finding", "module_filename") def __init__(self, module_name, import_name, source_ref): ExpressionImportHardBase.__init__( self, module_name=module_name, source_ref=source_ref ) self.import_name = import_name self.trust = hard_modules_trust[self.module_name].get(self.import_name) def finalize(self): del self.parent def getDetails(self): return {"module_name": self.module_name, "import_name": self.import_name} def getModuleName(self): return self.module_name def getImportName(self): return self.import_name def computeExpressionRaw(self, trace_collection): # As good as it gets, will exist, otherwise we do not get created. if self.mayHaveSideEffects(): trace_collection.onExceptionRaiseExit(AttributeError) return self, None, None def mayHaveSideEffects(self): return self.trust is None def mayRaiseException(self, exception_type): return self.trust is None importlib_import_module_spec = BuiltinParameterSpec( "importlib.import_module", ("name", "package"), default_count=1 ) class ExpressionImportlibImportModuleRef(ExpressionImportModuleNameHard): kind = "EXPRESSION_IMPORTLIB_IMPORT_MODULE_REF" def __init__(self, source_ref): ExpressionImportModuleNameHard.__init__( self, module_name="importlib", import_name="import_module", source_ref=source_ref, ) @staticmethod def getDetails(): return {} def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): # Anything may happen. On next pass, if replaced, we might be better # but not now. trace_collection.onExceptionRaiseExit(BaseException) result = extractBuiltinArgs( node=call_node, builtin_class=ExpressionImportlibImportModuleCall, builtin_spec=importlib_import_module_spec, ) return result, "new_expression", "Call of 'importlib.import_module' recognized." def _getImportNameAsStr(value): if value is None: result = None else: result = value.getCompileTimeConstant() if type(result) in (str, unicode): # TODO: This is not handling decoding errors all that well. if str is not unicode and type(result) is unicode: result = str(result) return result class ExpressionImportlibImportModuleCall(ExpressionChildrenHavingBase): """Call to "importlib.import_module" """ kind = "EXPRESSION_IMPORTLIB_IMPORT_MODULE_CALL" named_children = "name", "package" def __init__(self, name, package, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"name": name, "package": package}, source_ref=source_ref ) @staticmethod def _resolveImportLibArgs(module_name, package_name): # Relative imports need to be resolved by package name. if module_name.startswith("."): if not package_name: return None # TODO: Static exception should be created and warned about, Python2/Python3 differ # raise TypeError("relative imports require the 'package' argument") # msg = ("the 'package' argument is required to perform a relative import for {!r}") # raise TypeError(msg.format(name)) level = 0 for character in module_name: if character != ".": break level += 1 module_name = module_name[level:] dot = len(package_name) for _i in xrange(level, 1, -1): try: dot = package_name.rindex(".", 0, dot) except ValueError: return None # TODO: Static exception should be created and warned about. # raise ValueError("attempted relative import beyond top-level package") return "%s.%s" % (package_name[:dot], module_name) if package_name: return "%s.%s" % (package_name, module_name) else: return module_name def computeExpression(self, trace_collection): module_name = self.subnode_name package_name = self.subnode_package if ( package_name is None or package_name.isCompileTimeConstant() ) and module_name.isCompileTimeConstant(): imported_module_name = _getImportNameAsStr(module_name) imported_package_name = _getImportNameAsStr(package_name) if ( imported_package_name is None or type(imported_package_name) is str ) and type(imported_module_name) is str: resolved_module_name = self._resolveImportLibArgs( imported_module_name, imported_package_name ) if resolved_module_name is not None: # Importing may raise an exception obviously, unless we know it will # not. trace_collection.onExceptionRaiseExit(BaseException) result = makeExpressionImportModuleFixed( module_name=resolved_module_name, source_ref=self.source_ref ) return ( result, "new_expression", "Resolved importlib.import_module call to import of '%s'." % resolved_module_name, ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Importing may raise an exception obviously, unless we know it will # not. trace_collection.onExceptionRaiseExit(BaseException) # TODO: May return a module or module variable reference of some sort in # the future with embedded modules. return self, None, None module_importlib_trust["import_module"] = trust_node trust_node_factory[("importlib", "import_module")] = ExpressionImportlibImportModuleRef class ExpressionBuiltinImport(ExpressionChildrenHavingBase): __slots__ = ( "follow_attempted", "finding", "used_modules", "type_shape", "builtin_module", ) kind = "EXPRESSION_BUILTIN_IMPORT" named_children = ("name", "globals_arg", "locals_arg", "fromlist", "level") def __init__(self, name, globals_arg, locals_arg, fromlist, level, source_ref): ExpressionChildrenHavingBase.__init__( self, values={ "name": name, "globals_arg": globals_arg, "locals_arg": locals_arg, "fromlist": fromlist, "level": level, }, source_ref=source_ref, ) self.follow_attempted = False # The modules actually referenced in that import if it can be detected. Name # imports are considered too. self.used_modules = [] self.type_shape = tshape_module self.builtin_module = None self.finding = None def _attemptFollow(self, module_name): # Complex stuff, pylint: disable=too-many-branches parent_module = self.getParentModule() parent_package = parent_module.getFullName() if not parent_module.isCompiledPythonPackage(): parent_package = parent_package.getPackageName() level = self.subnode_level if level is None: level = 0 if parent_module.getFutureSpec().isAbsoluteImport() else -1 elif not level.isCompileTimeConstant(): return else: level = level.getCompileTimeConstant() # TODO: Catch this as a static error maybe. if type(level) not in (int, long): return None, None module_name, module_filename, self.finding = locateModule( module_name=ModuleName(module_name), parent_package=parent_package, level=level, ) if self.finding != "not-found": self.used_modules = [(module_name, module_filename, self.finding, level)] import_list = self.subnode_fromlist if import_list is not None: if import_list.isCompileTimeConstant(): import_list = import_list.getCompileTimeConstant() if type(import_list) not in (tuple, list): import_list = None if ( module_filename is not None and import_list and isPackageDir(module_filename) ): for import_item in import_list: if import_item == "*": continue ( name_import_module_name, name_import_module_filename, name_import_finding, ) = locateModule( module_name=ModuleName(import_item), parent_package=module_name, level=-1, # Relative import, so child is used. ) if name_import_module_filename is not None: self.used_modules.append( ( name_import_module_name, name_import_module_filename, name_import_finding, -1, ) ) return module_filename else: module_name = resolveModuleName(module_name) while True: module_name = module_name.getPackageName() if module_name is None: break module_name_found, module_filename, finding = locateModule( module_name=module_name, parent_package=parent_package, level=level, ) if module_filename is not None: self.used_modules = [ (module_name_found, module_filename, finding, level) ] return None def getUsedModules(self): return self.used_modules def computeExpression(self, trace_collection): # Attempt to recurse if not already done. if self.follow_attempted: if self.finding == "not-found": # Importing and not finding, may raise an exception obviously. trace_collection.onExceptionRaiseExit(BaseException) else: # If we know it exists, only RuntimeError shall occur. trace_collection.onExceptionRaiseExit(RuntimeError) # We stay here. return self, None, None module_name = self.subnode_name if module_name.isCompileTimeConstant(): imported_module_name = module_name.getCompileTimeConstant() module_filename = self._attemptFollow(module_name=imported_module_name) self.follow_attempted = True if type(imported_module_name) in (str, unicode): imported_module_name = resolveModuleName(imported_module_name) if self.finding == "absolute" and imported_module_name in hard_modules: if isStandardLibraryPath(module_filename): result = ExpressionImportModuleHard( module_name=imported_module_name, source_ref=self.source_ref ) return ( result, "new_expression", "Lowered import of standard library module '%s' to hard import." % imported_module_name.asString(), ) elif shallWarnUnusualCode(): unusual_logger.warning( "%s: Standard library module '%s' used from outside path %r." % ( self.source_ref.getAsString(), imported_module_name.asString(), self.module_filename, ) ) if self.finding == "built-in": if imported_module_name in hard_modules: result = ExpressionImportModuleHard( module_name=imported_module_name, source_ref=self.source_ref ) return ( result, "new_expression", "Lowered import of built-in module '%s' to hard import." % imported_module_name.asString(), ) self.type_shape = tshape_module_builtin self.builtin_module = __import__(imported_module_name) else: # TODO: This doesn't preserve side effects. # Non-strings is going to raise an error. ( new_node, change_tags, message, ) = trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: __import__( module_name.getCompileTimeConstant() ), description="Replaced '__import__' call with non-string module name argument.", ) # Must fail, must not go on when it doesn't. assert change_tags == "new_raise", module_name return new_node, change_tags, message # Importing may raise an exception obviously, unless we know it will # not. if self.finding != "built-in": trace_collection.onExceptionRaiseExit(BaseException) # TODO: May return a module or module variable reference of some sort in # the future with embedded modules. return self, None, None # TODO: Add computeExpressionImportName def mayRaiseException(self, exception_type): return self.finding != "built-in" def mayRaiseExceptionImportName(self, exception_type, import_name): if self.finding == "built-in": return not hasattr(self.builtin_module, import_name) else: return True def getTypeShape(self): return self.type_shape class StatementImportStar(StatementChildHavingBase): kind = "STATEMENT_IMPORT_STAR" named_child = "module" __slots__ = ("target_scope",) def __init__(self, target_scope, module_import, source_ref): StatementChildHavingBase.__init__( self, value=module_import, source_ref=source_ref ) self.target_scope = target_scope # TODO: Abstract these things. if type(self.target_scope) is GlobalsDictHandle: self.target_scope.markAsEscaped() def getTargetDictScope(self): return self.target_scope def computeStatement(self, trace_collection): trace_collection.onExpression(self.subnode_module) trace_collection.onLocalsDictEscaped(self.target_scope) # Need to invalidate everything, and everything could be assigned to # something else now. trace_collection.removeAllKnowledge() # We could always encounter that __all__ is a strange beast and causes # the exception. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def mayRaiseException(exception_type): # Not done. TODO: Later we can try and check for "__all__" if it # really can be that way. return True @staticmethod def getStatementNiceName(): return "star import statement" class ExpressionImportName(ExpressionChildHavingBase): kind = "EXPRESSION_IMPORT_NAME" named_child = "module" __slots__ = ("import_name", "level") def __init__(self, module, import_name, level, source_ref): ExpressionChildHavingBase.__init__(self, value=module, source_ref=source_ref) self.import_name = import_name self.level = level # Not allowed. assert level is not None assert module is not None def getImportName(self): return self.import_name def getImportLevel(self): return self.level def getDetails(self): return {"import_name": self.import_name, "level": self.level} def computeExpression(self, trace_collection): return self.subnode_module.computeExpressionImportName( import_node=self, import_name=self.import_name, trace_collection=trace_collection, ) def mayRaiseException(self, exception_type): return self.subnode_module.mayRaiseExceptionImportName( exception_type=exception_type, import_name=self.import_name ) def makeExpressionImportModuleFixed(module_name, source_ref): if module_name in hard_modules: return ExpressionImportModuleHard( module_name=module_name, source_ref=source_ref ) else: return ExpressionImportModuleFixed( module_name=module_name, source_ref=source_ref ) Nuitka-0.6.19.1/nuitka/nodes/DictionaryNodes.py0000600000372100037210000013452014166627112026347 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes that build and operate on dictionaries. The "pair" is a sub-structure of the dictionary, representing a key/value pair that is the child of the dictionary creation. """ from nuitka import Constants from nuitka.PythonVersions import python_version from .AttributeNodes import makeExpressionAttributeLookup from .BuiltinHashNodes import ExpressionBuiltinHash from .ConstantRefNodes import ( ExpressionConstantDictEmptyRef, makeConstantRefNode, ) from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionChildTupleHavingBase, ExpressionNoSideEffectsMixin, ) from .ExpressionShapeMixins import ( ExpressionBoolShapeExactMixin, ExpressionDictShapeExactMixin, ExpressionListShapeExactMixin, ExpressionNoneShapeExactMixin, ) from .NodeBases import ( SideEffectsFromChildrenMixin, StatementChildrenHavingBase, ) from .NodeMakingHelpers import ( makeConstantReplacementNode, makeRaiseExceptionExpressionFromTemplate, makeRaiseExceptionReplacementExpression, makeStatementOnlyNodesFromExpressions, wrapExpressionWithSideEffects, ) from .shapes.StandardShapes import tshape_iterator def makeExpressionPairs(keys, values): assert len(keys) == len(values) return [ ExpressionKeyValuePair( key=key, value=value, source_ref=key.getSourceReference() ) for key, value in zip(keys, values) ] class ExpressionKeyValuePair( SideEffectsFromChildrenMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_KEY_VALUE_PAIR" # They changed the order of evaluation with 3.5 to what you normally would expect. if python_version < 0x350: named_children = ("value", "key") else: named_children = ("key", "value") def __init__(self, key, value, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"key": key, "value": value}, source_ref=source_ref ) def computeExpression(self, trace_collection): key = self.subnode_key hashable = key.isKnownToBeHashable() # If not known to be hashable, that can raise an exception. if not hashable: trace_collection.onExceptionRaiseExit(TypeError) if hashable is False: # TODO: If it's not hashable, we should turn it into a raise, it's # just difficult to predict the exception value precisely, as it # could be e.g. (2, []), and should then complain about the list. pass return self, None, None def mayRaiseException(self, exception_type): key = self.subnode_key return ( key.mayRaiseException(exception_type) or key.isKnownToBeHashable() is not True or self.subnode_value.mayRaiseException(exception_type) ) def extractSideEffects(self): if self.subnode_key.isKnownToBeHashable() is True: key_part = self.subnode_key.extractSideEffects() else: key_part = ( ExpressionBuiltinHash( value=self.subnode_key, source_ref=self.subnode_key.source_ref ), ) if python_version < 0x350: return self.subnode_value.extractSideEffects() + key_part else: return key_part + self.subnode_value.extractSideEffects() def onContentEscapes(self, trace_collection): self.subnode_key.onContentEscapes(trace_collection) self.subnode_value.onContentEscapes(trace_collection) def makeExpressionMakeDict(pairs, source_ref): if pairs: return ExpressionMakeDict(pairs, source_ref) else: # TODO: Get rid of user provided for empty dict refs, makes no sense. return ExpressionConstantDictEmptyRef( user_provided=False, source_ref=source_ref ) def makeExpressionMakeDictOrConstant(pairs, user_provided, source_ref): # Create dictionary node. Tries to avoid it for constant values that are not # mutable. for pair in pairs: # TODO: Compile time constant ought to be the criterion. if ( not pair.subnode_value.isExpressionConstantRef() or not pair.subnode_key.isExpressionConstantRef() ): result = makeExpressionMakeDict(pairs, source_ref) break else: # Unless told otherwise, create the dictionary in its full size, so # that no growing occurs and the constant becomes as similar as possible # before being marshaled. result = makeConstantRefNode( constant=Constants.createConstantDict( keys=[pair.subnode_key.getCompileTimeConstant() for pair in pairs], values=[pair.subnode_value.getCompileTimeConstant() for pair in pairs], ), user_provided=user_provided, source_ref=source_ref, ) if pairs: result.setCompatibleSourceReference( source_ref=pairs[-1].subnode_value.getCompatibleSourceReference() ) return result class ExpressionMakeDict( ExpressionDictShapeExactMixin, SideEffectsFromChildrenMixin, ExpressionChildTupleHavingBase, ): kind = "EXPRESSION_MAKE_DICT" named_child = "pairs" def __init__(self, pairs, source_ref): assert pairs ExpressionChildTupleHavingBase.__init__( self, value=tuple(pairs), source_ref=source_ref ) def computeExpression(self, trace_collection): pairs = self.subnode_pairs is_constant = True for pair in pairs: key = pair.subnode_key if key.isKnownToBeHashable() is False: side_effects = [] for pair2 in pairs: side_effects.extend(pair2.extractSideEffects()) if pair2 is pair: break result = makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template="unhashable type: '%s'", template_args=makeExpressionAttributeLookup( expression=key.extractUnhashableNodeType(), attribute_name="__name__", source_ref=key.source_ref, ), source_ref=key.source_ref, ) result = wrapExpressionWithSideEffects( side_effects=side_effects, old_node=key, new_node=result ) return ( result, "new_raise", "Dictionary key is known to not be hashable.", ) if is_constant: if not key.isExpressionConstantRef(): is_constant = False else: value = pair.subnode_value if not value.isExpressionConstantRef(): is_constant = False if not is_constant: return self, None, None constant_value = Constants.createConstantDict( keys=[pair.subnode_key.getCompileTimeConstant() for pair in pairs], values=[pair.subnode_value.getCompileTimeConstant() for pair in pairs], ) new_node = makeConstantReplacementNode( constant=constant_value, node=self, user_provided=True ) return ( new_node, "new_constant", """\ Created dictionary found to be constant.""", ) def mayRaiseException(self, exception_type): for pair in self.subnode_pairs: if pair.mayRaiseException(exception_type): return True return False def isKnownToBeIterable(self, count): return count is None or count == len(self.subnode_pairs) def getIterationLength(self): pair_count = len(self.subnode_pairs) # Hashing may consume elements. if pair_count > 1: return None else: return pair_count @staticmethod def getIterationMinLength(): return 1 def canPredictIterationValues(self): # Dictionaries are assumed to be fully predictable # TODO: For some things, that may not be true, when key collisions # happen for example. We will have to check that then. return True def getIterationValue(self, count): return self.subnode_pairs[count].subnode_key @staticmethod def getTruthValue(): return True def isMappingWithConstantStringKeys(self): return all( pair.subnode_key.isExpressionConstantStrRef() for pair in self.subnode_pairs ) def getMappingStringKeyPairs(self): return [ (pair.subnode_key.getCompileTimeConstant(), pair.subnode_value) for pair in self.subnode_pairs ] # TODO: Missing computeExpressionIter1 here. For now it would require us to # add lots of temporary variables for keys, which then becomes the tuple, # but for as long as we don't have efficient forward propagation of these, # we won't do that. Otherwise we loose execution order of values with them # remaining as side effects. We could limit ourselves to cases where # isMappingWithConstantStringKeys is true, or keys had no side effects, but # that feels wasted effort as we are going to have full propagation. def computeExpressionDrop(self, statement, trace_collection): expressions = [] for pair in self.subnode_pairs: expressions.extend(pair.extractSideEffects()) result = makeStatementOnlyNodesFromExpressions(expressions=expressions) del self.parent return ( result, "new_statements", """\ Removed sequence creation for unused sequence.""", ) def computeExpressionIter1(self, iter_node, trace_collection): return iter_node, None, None def onContentEscapes(self, trace_collection): for pair in self.subnode_pairs: pair.onContentEscapes(trace_collection) class StatementDictOperationSet(StatementChildrenHavingBase): kind = "STATEMENT_DICT_OPERATION_SET" named_children = ("value", "dict_arg", "key") def __init__(self, dict_arg, key, value, source_ref): assert dict_arg is not None assert key is not None assert value is not None StatementChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key, "value": value}, source_ref=source_ref, ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.computeStatementOperation(trace_collection) def computeStatementOperation(self, trace_collection): key = self.subnode_key if not key.isKnownToBeHashable(): # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(self.subnode_dict_arg) return self, None, None def mayRaiseException(self, exception_type): key = self.subnode_key if not key.isKnownToBeHashable(): return True if key.mayRaiseException(exception_type): return True value = self.subnode_value if value.mayRaiseException(exception_type): return True return False def mayRaiseExceptionOperation(self): return not self.subnode_key.isKnownToBeHashable() class StatementDictOperationSetKeyValue(StatementDictOperationSet): kind = "STATEMENT_DICT_OPERATION_SET_KEY_VALUE" named_children = ("key", "value", "dict_arg") class StatementDictOperationRemove(StatementChildrenHavingBase): kind = "STATEMENT_DICT_OPERATION_REMOVE" named_children = ("dict_arg", "key") def __init__(self, dict_arg, key, source_ref): assert dict_arg is not None assert key is not None StatementChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc return self.computeStatementOperation(trace_collection) def computeStatementOperation(self, trace_collection): # Any exception may be raised, we don't know if the key is present. trace_collection.onExceptionRaiseExit(BaseException) # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(self.subnode_dict_arg) return self, None, None def mayRaiseException(self, exception_type): key = self.subnode_key if not key.isKnownToBeHashable(): return True if key.mayRaiseException(exception_type): return True # TODO: Could check dict for knowledge about keys. return True class ExpressionDictOperationPop2(ExpressionChildrenHavingBase): """This operation represents d.pop(key), i.e. default None.""" kind = "EXPRESSION_DICT_OPERATION_POP2" named_children = ("dict_arg", "key") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, source_ref): assert dict_arg is not None assert key is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref, ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.pop", side_effects=(dict_arg, key), ) # TODO: Check if dict_arg has key. # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(dict_arg) # TODO: Until we can know KeyError won't happen, but then we should change into # something else. trace_collection.onExceptionRaiseExit(BaseException) # TODO: Check for "None" default and demote to ExpressionDictOperationSetdefault3 in # that case. return self, None, None # TODO: These turn this into dictionary item removals, as value is unused. # def computeExpressionDrop(self, statement, trace_collection): # TODO: Might raise KeyError depending on dictionary. @staticmethod def mayRaiseException(exception_type): return True # if self.known_hashable_key is None: # return True # else: # return self.subnode_dict_arg.mayRaiseException( # exception_type # ) or self.subnode_key.mayRaiseException(exception_type) class ExpressionDictOperationPop3(ExpressionChildrenHavingBase): """This operation represents d.pop(key, default).""" kind = "EXPRESSION_DICT_OPERATION_POP3" named_children = ("dict_arg", "key", "default") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, default, source_ref): assert dict_arg is not None assert key is not None assert default is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key, "default": default}, source_ref=source_ref, ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.pop", side_effects=(dict_arg, key, self.subnode_default), ) # TODO: Check if dict_arg has key # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(dict_arg) # TODO: Check for "None" default and demote to ExpressionDictOperationSetdefault3 in # that case. return self, None, None # TODO: These turn this into dictionary item removals, as value is unused. # def computeExpressionDrop(self, statement, trace_collection): def mayRaiseException(self, exception_type): if self.known_hashable_key is None: return True else: return ( self.subnode_dict_arg.mayRaiseException(exception_type) or self.subnode_key.mayRaiseException(exception_type) or self.subnode_default.mayRaiseException(exception_type) ) class ExpressionDictOperationSetdefault2(ExpressionChildrenHavingBase): """This operation represents d.setdefault(key), i.e. default None.""" kind = "EXPRESSION_DICT_OPERATION_SETDEFAULT2" named_children = ("dict_arg", "key") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, source_ref): assert dict_arg is not None assert key is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref, ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.setdefault", side_effects=(dict_arg, key), ) # TODO: Check if dict_arg has key, and eliminate this node entirely # if that's the case with hashing of the key as a remaining side effect # though. # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(dict_arg) # TODO: Check for "None" default and demote to ExpressionDictOperationSetdefault3 in # that case. return self, None, None def mayRaiseException(self, exception_type): if self.known_hashable_key is None: return True else: return self.subnode_dict_arg.mayRaiseException( exception_type ) or self.subnode_key.mayRaiseException(exception_type) class ExpressionDictOperationSetdefault3(ExpressionChildrenHavingBase): """This operation represents d.setdefault(key, default).""" kind = "EXPRESSION_DICT_OPERATION_SETDEFAULT3" named_children = ("dict_arg", "key", "default") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, default, source_ref): assert dict_arg is not None assert key is not None assert default is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key, "default": default}, source_ref=source_ref, ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.setdefault", side_effects=(dict_arg, key, self.subnode_default), ) # TODO: Check if dict_arg has key, and eliminate this node entirely # if that's the case with hashing of the key as a remaining side effect # though. # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(dict_arg) # TODO: Check for "None" default and demote to ExpressionDictOperationSetdefault3 in # that case. return self, None, None def mayRaiseException(self, exception_type): if self.known_hashable_key is None: return True else: return ( self.subnode_dict_arg.mayRaiseException(exception_type) or self.subnode_key.mayRaiseException(exception_type) or self.subnode_default.mayRaiseException(exception_type) ) class ExpressionDictOperationItem(ExpressionChildrenHavingBase): """This operation represents d[key] with an exception for missing key.""" kind = "EXPRESSION_DICT_OPERATION_ITEM" named_children = ("dict_arg", "key") def __init__(self, dict_arg, key, source_ref): assert dict_arg is not None assert key is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref ) def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if dict_arg.isCompileTimeConstant() and key.isCompileTimeConstant(): return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: self.getCompileTimeConstant()[ dict_arg.getCompileTimeConstant()[key.getCompileTimeConstant()] ], user_provided=dict_arg.user_provided, description="Dictionary item lookup with constant key.", ) # TODO: Only if the key is not hashable. trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionDictOperationGet2(ExpressionChildrenHavingBase): """This operation represents d.get(key) with no exception for missing key but None default.""" kind = "EXPRESSION_DICT_OPERATION_GET2" named_children = ("dict_arg", "key") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, source_ref): assert dict_arg is not None assert key is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = self.subnode_key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.get", side_effects=(dict_arg, key), ) if dict_arg.isCompileTimeConstant() and key.isCompileTimeConstant(): result = wrapExpressionWithSideEffects( new_node=makeConstantReplacementNode( constant=dict_arg.getCompileTimeConstant().get( key.getCompileTimeConstant() ), node=self, user_provided=dict_arg.user_provided, ), old_node=self, side_effects=(dict_arg, key), ) return ( result, "new_expression", "Compile time computed 'dict.get' on constant argument.", ) if self.known_hashable_key is None: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): if self.known_hashable_key is None: return True else: return self.subnode_dict_arg.mayRaiseException( exception_type ) or self.subnode_key.mayRaiseException(exception_type) def mayHaveSideEffects(self): if self.known_hashable_key is None: return True else: return ( self.subnode_dict_arg.mayHaveSideEffects() or self.subnode_key.mayHaveSideEffects() ) def extractSideEffects(self): if self.known_hashable_key is None: return (self,) else: return ( self.subnode_dict_arg.extractSideEffects() + self.subnode_key.extractSideEffects() ) class ExpressionDictOperationGet3(ExpressionChildrenHavingBase): """This operation represents d.get(key, default) with no exception for missing key but default value.""" kind = "EXPRESSION_DICT_OPERATION_GET3" named_children = ("dict_arg", "key", "default") __slots__ = ("known_hashable_key",) def __init__(self, dict_arg, key, default, source_ref): assert dict_arg is not None assert key is not None assert default is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key, "default": default}, source_ref=source_ref, ) self.known_hashable_key = None def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg key = self.subnode_key if self.known_hashable_key is None: self.known_hashable_key = key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=key, operation="dict.get", side_effects=(dict_arg, key, self.subnode_default), ) # TODO: With dictionary tracing, this could become more transparent. if dict_arg.isCompileTimeConstant() and key.isCompileTimeConstant(): dict_value = dict_arg.getCompileTimeConstant() key_value = key.getCompileTimeConstant() if key_value in dict_value: # Side effects of args must be retained, but it's not used. result = wrapExpressionWithSideEffects( new_node=makeConstantReplacementNode( constant=dict_value[key_value], node=self, user_provided=dict_arg.user_provided, ), old_node=self, side_effects=( dict_arg, key, self.subnode_default, ), ) description = "Compile time computed 'dict.get' on constant argument to not use default." else: # Side effects of dict and key must be retained, but it's not used. result = wrapExpressionWithSideEffects( new_node=self.subnode_default, old_node=self, side_effects=(dict_arg, key), ) description = "Compile time computed 'dict.get' on constant argument to use default." return (result, "new_expression", description) if self.known_hashable_key is None: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): if self.known_hashable_key is None: return True else: return ( self.subnode_dict_arg.mayRaiseException(exception_type) or self.subnode_key.mayRaiseException(exception_type) or self.subnode_default.mayRaiseException(exception_type) ) def mayHaveSideEffects(self): if self.known_hashable_key is None: return True else: return ( self.subnode_dict_arg.mayHaveSideEffects() or self.subnode_key.mayHaveSideEffects() or self.subnode_default.mayHaveSideEffects() ) def extractSideEffects(self): if self.known_hashable_key is None: return (self,) else: return ( self.subnode_dict_arg.extractSideEffects() + self.subnode_key.extractSideEffects() + self.subnode_defaults.extractSideEffects() ) class ExpressionDictOperationCopy( ExpressionDictShapeExactMixin, ExpressionNoSideEffectsMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_DICT_OPERATION_COPY" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg if dict_arg.isCompileTimeConstant(): result = makeConstantReplacementNode( constant=dict_arg.getCompileTimeConstant().copy(), node=self, user_provided=dict_arg.user_provided, ) return ( result, "new_expression", "Compile time computed 'dict.copy' on constant argument.", ) trace_collection.onExceptionRaiseExit(BaseException) return self, None, None class ExpressionDictOperationClear( ExpressionNoneShapeExactMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_CLEAR" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): # Once we do dictionary tracing, we should tell it, we know its new value # perfectly, and that we have no use for previous value. # trace_collection.onDictionaryReplaceValueWithKnownValue(self.subnode_dict_arg, {}) return self, None, None @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationKeys( ExpressionListShapeExactMixin, ExpressionNoSideEffectsMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_DICT_OPERATION_KEYS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg if dict_arg.isCompileTimeConstant(): result = makeConstantReplacementNode( constant=dict_arg.getCompileTimeConstant().keys(), node=self, user_provided=dict_arg.user_provided, ) return ( result, "new_expression", "Compile time computed 'dict.keys' on constant argument.", ) return self, None, None @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationViewkeys( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_VIEWKEYS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): # TODO: Actually iterator that yields key values return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationIterkeys( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_ITERKEYS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationValues( ExpressionListShapeExactMixin, ExpressionNoSideEffectsMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_DICT_OPERATION_VALUES" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg if dict_arg.isCompileTimeConstant(): result = makeConstantReplacementNode( constant=dict_arg.getCompileTimeConstant().values(), node=self, user_provided=dict_arg.user_provided, ) return ( result, "new_expression", "Compile time computed 'dict.values' on constant argument.", ) return self, None, None @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationViewvalues( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_VIEWVALUES" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): # TODO: Actually iterator that yields key values return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationItervalues( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_ITERVALUES" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationItems( ExpressionListShapeExactMixin, ExpressionNoSideEffectsMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_DICT_OPERATION_ITEMS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): dict_arg = self.subnode_dict_arg if dict_arg.isCompileTimeConstant(): result = makeConstantReplacementNode( constant=dict_arg.getCompileTimeConstant().items(), node=self, user_provided=dict_arg.user_provided, ) return ( result, "new_expression", "Compile time computed 'dict.items' on constant argument.", ) return self, None, None @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationIteritems( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_ITERITEMS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): # TODO: Actually iterator that yields 2 element tuples, add shapes # for that too. return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationViewitems( ExpressionNoSideEffectsMixin, ExpressionChildHavingBase ): kind = "EXPRESSION_DICT_OPERATION_VIEWITEMS" named_child = "dict_arg" def __init__(self, dict_arg, source_ref): assert dict_arg is not None ExpressionChildHavingBase.__init__(self, value=dict_arg, source_ref=source_ref) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None @staticmethod def getTypeShape(): # TODO: Actually iterator that yields key values return tshape_iterator @staticmethod def mayRaiseException(exception_type): return False class ExpressionDictOperationUpdate2( ExpressionNoneShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents d.update(iterable).""" kind = "EXPRESSION_DICT_OPERATION_UPDATE2" named_children = ("dict_arg", "iterable") def __init__(self, dict_arg, iterable, source_ref): assert dict_arg is not None assert iterable is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "iterable": iterable}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(self.subnode_dict_arg) # TODO: Using it might change it, unfortunately trace_collection.removeKnowledge(self.iterable) # TODO: Until we can know KeyError won't happen, but then we should change into # something else. trace_collection.onExceptionRaiseExit(BaseException) # TODO: Check empty, and remove itself if that's the case. return self, None, None # TODO: Might raise non-iterable depending on value shape, or not hashable from content. @staticmethod def mayRaiseException(exception_type): return True class ExpressionDictOperationUpdate3( ExpressionNoneShapeExactMixin, ExpressionChildrenHavingBase ): """This operation represents d.update(iterable).""" kind = "EXPRESSION_DICT_OPERATION_UPDATE3" named_children = ("dict_arg", "iterable", "pairs") def __init__(self, dict_arg, iterable, pairs, source_ref): assert dict_arg is not None # Artefact of star argument parsing, should be resolved on the outside though. if type(iterable) is tuple: if not iterable: iterable = None else: (iterable,) = iterable ExpressionChildrenHavingBase.__init__( self, values={ "dict_arg": dict_arg, "iterable": iterable, "pairs": tuple( ExpressionKeyValuePair( makeConstantRefNode(key, source_ref), value, value.getSourceReference(), ) for key, value in pairs ), }, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Until we have proper dictionary tracing, do this. trace_collection.removeKnowledge(self.subnode_dict_arg) # TODO: Using it might change it, unfortunately # TODO: When iterable is None, this should be specialized further. if self.subnode_iterable is not None: trace_collection.removeKnowledge(self.subnode_iterable) for pair in self.subnode_pairs: trace_collection.removeKnowledge(pair) # TODO: Until we can know KeyError won't happen, but then we should change into # something else. trace_collection.onExceptionRaiseExit(BaseException) # TODO: Check empty, and remove itself if that's the case. return self, None, None # TODO: Might raise non-iterable depending on value shape, or not hashable from content. @staticmethod def mayRaiseException(exception_type): return True class StatementDictOperationUpdate(StatementChildrenHavingBase): """Update dict value. This is mainly used for re-formulations, where a dictionary update will be performed on what is known not to be a general mapping. """ kind = "STATEMENT_DICT_OPERATION_UPDATE" named_children = ("dict_arg", "value") def __init__(self, dict_arg, value, source_ref): assert dict_arg is not None assert value is not None StatementChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "value": value}, source_ref=source_ref ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def makeUnhashableExceptionReplacementExpression(node, key, side_effects, operation): unhashable_type_name = ( key.extractUnhashableNodeType().getCompileTimeConstant().__name__ ) result = makeRaiseExceptionReplacementExpression( expression=node, exception_type="TypeError", exception_value="unhashable type: '%s'" % unhashable_type_name, ) result = wrapExpressionWithSideEffects( side_effects=side_effects, old_node=node, new_node=result, ) return ( result, "new_raise", "Dictionary operation '%s' with key of type '%s' that is known to not be hashable." % (operation, unhashable_type_name), ) class ExpressionDictOperationInNotInUncertainBase( ExpressionBoolShapeExactMixin, ExpressionChildrenHavingBase ): # Follows the reversed nature of "in", with the dictionary on the right # side of things. named_children = ("key", "dict_arg") __slots__ = ("known_hashable_key",) def __init__(self, key, dict_arg, source_ref): assert dict_arg is not None assert key is not None ExpressionChildrenHavingBase.__init__( self, values={"dict_arg": dict_arg, "key": key}, source_ref=source_ref ) self.known_hashable_key = None def computeExpression(self, trace_collection): if self.known_hashable_key is None: self.known_hashable_key = self.subnode_key.isKnownToBeHashable() if self.known_hashable_key is False: trace_collection.onExceptionRaiseExit(BaseException) return makeUnhashableExceptionReplacementExpression( node=self, key=self.subnode_key, operation="in (dict)", side_effects=self.getVisitableNodes(), ) if self.known_hashable_key is None: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): return ( self.subnode_key.mayRaiseException(exception_type) or self.subnode_dict_arg.mayRaiseException(exception_type) or self.known_hashable_key is not True ) def mayHaveSideEffects(self): return self.mayRaiseException(BaseException) def extractSideEffects(self): if self.known_hashable_key is not True: return (self,) else: # No side effects at all but from the children. result = [] # The order of evaluation is different for "in" and "has_key", so we go # through visitable nodes. for child in self.getVisitableNodes(): result.extend(child.extractSideEffects()) return tuple(result) class ExpressionDictOperationIn(ExpressionDictOperationInNotInUncertainBase): kind = "EXPRESSION_DICT_OPERATION_IN" class ExpressionDictOperationNotIn(ExpressionDictOperationInNotInUncertainBase): kind = "EXPRESSION_DICT_OPERATION_NOT_IN" class ExpressionDictOperationHaskey(ExpressionDictOperationIn): kind = "EXPRESSION_DICT_OPERATION_HASKEY" # Different order of arguments. named_children = ("dict_arg", "key") Nuitka-0.6.19.1/nuitka/nodes/ContainerOperationNodes.py0000600000372100037210000001071214166627112030041 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Operations on Containers. """ from .ExpressionBases import ( ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .NodeBases import StatementChildrenHavingBase class StatementListOperationAppend(StatementChildrenHavingBase): kind = "STATEMENT_LIST_OPERATION_APPEND" named_children = ("list_arg", "value") def __init__(self, list_arg, value, source_ref): assert list_arg is not None assert value is not None StatementChildrenHavingBase.__init__( self, values={"list_arg": list_arg, "value": value}, source_ref=source_ref ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc # TODO: Until we have proper list tracing. trace_collection.removeKnowledge(self.subnode_list_arg) return self, None, None class ExpressionListOperationExtend(ExpressionChildrenHavingBase): kind = "EXPRESSION_LIST_OPERATION_EXTEND" named_children = ("list_arg", "value") def __init__(self, list_arg, value, source_ref): assert list_arg is not None assert value is not None ExpressionChildrenHavingBase.__init__( self, values={"list_arg": list_arg, "value": value}, source_ref=source_ref ) def computeExpression(self, trace_collection): # TODO: Until we have proper list tracing. trace_collection.removeKnowledge(self.subnode_list_arg) return self, None, None class ExpressionListOperationExtendForUnpack(ExpressionListOperationExtend): kind = "EXPRESSION_LIST_OPERATION_EXTEND_FOR_UNPACK" class ExpressionListOperationPop(ExpressionChildHavingBase): kind = "EXPRESSION_LIST_OPERATION_POP" named_child = "list_arg" def __init__(self, list_arg, source_ref): assert list_arg is not None ExpressionChildHavingBase.__init__(self, value=list_arg, source_ref=source_ref) def computeExpression(self, trace_collection): if not self.subnode_list_arg.isKnownToBeIterableAtMin(1): trace_collection.onExceptionRaiseExit(IndexError) # TODO: Until we have proper list tracing. trace_collection.removeKnowledge(self.subnode_list_arg) return self, None, None class StatementSetOperationAdd(StatementChildrenHavingBase): kind = "STATEMENT_SET_OPERATION_ADD" named_children = ("set_arg", "value") def __init__(self, set_arg, value, source_ref): assert set_arg is not None assert value is not None StatementChildrenHavingBase.__init__( self, values={"set_arg": set_arg, "value": value}, source_ref=source_ref ) def computeStatement(self, trace_collection): result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc trace_collection.removeKnowledge(self.subnode_set_arg) return self, None, None class ExpressionSetOperationUpdate(ExpressionChildrenHavingBase): kind = "EXPRESSION_SET_OPERATION_UPDATE" named_children = ("set_arg", "value") def __init__(self, set_arg, value, source_ref): assert set_arg is not None assert value is not None ExpressionChildrenHavingBase.__init__( self, values={"set_arg": set_arg, "value": value}, source_ref=source_ref ) def computeExpression(self, trace_collection): trace_collection.removeKnowledge(self.subnode_set_arg) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/BuiltinDecodingNodes.py0000600000372100037210000000324214166627112027301 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-in ord/chr nodes These are good for optimizations, as they give a very well known result. In the case of 'chr', it's one of 256 strings, and in case of 'ord' it's one of 256 numbers, so these can answer quite a few questions at compile time. """ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ExpressionBuiltinSingleArgBase class ExpressionBuiltinOrd(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_BUILTIN_ORD" builtin_spec = BuiltinParameterSpecs.builtin_ord_spec @staticmethod def isKnownToBeIterable(count): return False class ExpressionBuiltinChr(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_BUILTIN_CHR" builtin_spec = BuiltinParameterSpecs.builtin_chr_spec def isKnownToBeIterable(self, count): if self.mayRaiseException(BaseException): return None return count is None or count == 1 Nuitka-0.6.19.1/nuitka/nodes/StringConcatenationNodes.py0000600000372100037210000000654214166627112030220 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node dedicated to "".join() code pattern. This is used for Python 3.6 fstrings re-formulation and has pretty direct code alternative to actually looking up that method from the empty string object, so it got a dedicated node, also to perform optimizations specific to this. """ from .ConstantRefNodes import makeConstantRefNode from .ExpressionBases import ExpressionChildTupleHavingBase from .ExpressionShapeMixins import ExpressionStrOrUnicodeExactMixin class ExpressionStringConcatenation( ExpressionStrOrUnicodeExactMixin, ExpressionChildTupleHavingBase ): kind = "EXPRESSION_STRING_CONCATENATION" named_child = "values" def __init__(self, values, source_ref): assert values ExpressionChildTupleHavingBase.__init__( self, value=tuple(values), source_ref=source_ref ) def computeExpression(self, trace_collection): # TODO: Could remove itself if only one argument or merge arguments # of mergeable types. streaks = [] start = None values = self.subnode_values for count, value in enumerate(values): if value.isCompileTimeConstant() and value.hasShapeStrOrUnicodeExact(): if start is None: start = count else: if start is not None: if start != count - 1: streaks.append((start, count)) start = None # Catch final one too. if start is not None: if start != len(values) - 1: streaks.append((start, len(values))) if streaks: values = list(values) for streak in reversed(streaks): new_element = makeConstantRefNode( constant="".join( value.getCompileTimeConstant() for value in values[streak[0] : streak[1]] ), source_ref=values[streak[0]].source_ref, user_provided=True, ) values[streak[0] : streak[1]] = (new_element,) if len(values) > 1: self.setChild("values", values) return ( self, "new_constant", "Partially combined strings for concatenation", ) if len(values) == 1 and values[0].hasShapeStrOrUnicodeExact(): return ( values[0], "new_constant", "Removed strings concatenation of one value.", ) return self, None, None Nuitka-0.6.19.1/nuitka/nodes/FunctionNodes.py0000600000372100037210000011104214166627112026021 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes for functions and their creations. Lambdas are functions too. The functions are at the core of the language and have their complexities. Creating a CPython function object is an optional thing. Some things might only be used to be called directly, while knowing exactly what it is. So the "ExpressionFunctionCreation" might be used to provide that kind of CPython reference, and may escape. Coroutines and generators live in their dedicated module and share base classes. """ import inspect from nuitka import Options, Variables from nuitka.Constants import isMutable from nuitka.optimizations.TraceCollections import ( TraceCollectionPureFunction, withChangeIndicationsTo, ) from nuitka.PythonVersions import python_version from nuitka.specs.ParameterSpecs import ( ParameterSpec, TooManyArguments, matchCall, ) from nuitka.Tracing import optimization_logger from nuitka.tree.Extractions import updateVariableUsage from nuitka.tree.TreeHelpers import makeDictCreationOrConstant2 from .Checkers import checkStatementsSequenceOrNone from .CodeObjectSpecs import CodeObjectSpec from .ExpressionBases import ( ExpressionBase, ExpressionChildHavingBase, ExpressionChildrenHavingBase, ExpressionNoSideEffectsMixin, ) from .FutureSpecs import fromFlags from .IndicatorMixins import ( EntryPointMixin, MarkUnoptimizedFunctionIndicatorMixin, ) from .LocalsScopes import getLocalsDictHandle from .NodeBases import ( ClosureGiverNodeMixin, ClosureTakerMixin, SideEffectsFromChildrenMixin, ) from .NodeMakingHelpers import ( makeRaiseExceptionReplacementExpressionFromInstance, wrapExpressionWithSideEffects, ) from .shapes.BuiltinTypeShapes import tshape_function _is_verbose = Options.isVerbose() class MaybeLocalVariableUsage(Exception): pass class ExpressionFunctionBodyBase( ClosureTakerMixin, ClosureGiverNodeMixin, ExpressionChildHavingBase ): # TODO: The code_prefix should be a class attribute instead. __slots__ = ( "provider", "taken", "name", "code_prefix", "code_name", "uids", "temp_variables", "temp_scopes", "preserver_id", "flags", ) if python_version >= 0x340: __slots__ += ("qualname_provider",) if python_version >= 0x300: __slots__ += ("non_local_declarations",) named_child = "body" checker = checkStatementsSequenceOrNone def __init__(self, provider, name, body, code_prefix, flags, source_ref): while provider.isExpressionOutlineBody(): provider = provider.getParentVariableProvider() ExpressionChildHavingBase.__init__( self, value=body, # Might be None initially in some cases. source_ref=source_ref, ) ClosureTakerMixin.__init__(self, provider=provider) ClosureGiverNodeMixin.__init__(self, name=name, code_prefix=code_prefix) # Special things, "has_super" indicates presence of "super" in variable # usage, which modifies some behaviors. self.flags = flags or None # Hack: This allows some APIs to work although this is not yet # officially a child yet. Important during building. self.parent = provider # Python3.4: Might be overridden by global statement on the class name. # TODO: Make this class only code. if python_version >= 0x340: self.qualname_provider = provider # Non-local declarations. if python_version >= 0x300: self.non_local_declarations = None @staticmethod def isExpressionFunctionBodyBase(): return True def getEntryPoint(self): """Entry point for code. Normally ourselves. Only outlines will refer to their parent which technically owns them. """ return self def getContainingClassDictCreation(self): current = self while not current.isCompiledPythonModule(): if current.isExpressionClassBody(): return current current = current.getParentVariableProvider() return None def hasFlag(self, flag): return self.flags is not None and flag in self.flags def discardFlag(self, flag): if self.flags is not None: self.flags.discard(flag) @staticmethod def isEarlyClosure(): """Early closure taking means immediate binding of references. Normally it's good to lookup name references immediately, but not for functions. In case of a function body it is not allowed to do that, because a later assignment needs to be queried first. Nodes need to indicate via this if they would like to resolve references at the same time as assignments. """ return False def getLocalsScope(self): return self.locals_scope # TODO: Dubious function doing to distinct things, should be moved to users. def hasVariableName(self, variable_name): return ( self.locals_scope.hasProvidedVariable(variable_name) or variable_name in self.temp_variables ) def getProvidedVariables(self): if self.locals_scope is not None: return self.locals_scope.getProvidedVariables() else: return () def getLocalVariables(self): return [ variable for variable in self.getProvidedVariables() if variable.isLocalVariable() ] def getUserLocalVariables(self): return [ variable for variable in self.getProvidedVariables() if variable.isLocalVariable() and not variable.isParameterVariable() if variable.getOwner() is self ] def getOutlineLocalVariables(self): result = [] outlines = self.getTraceCollection().getOutlineFunctions() if outlines is None: return result for outline in outlines: result.extend(outline.getUserLocalVariables()) return result def removeClosureVariable(self, variable): # Do not remove parameter variables of ours. assert not variable.isParameterVariable() or variable.getOwner() is not self self.locals_scope.unregisterClosureVariable(variable) self.taken.remove(variable) self.code_object.removeFreeVarname(variable.getName()) def demoteClosureVariable(self, variable): assert variable.isLocalVariable() self.taken.remove(variable) assert variable.getOwner() is not self new_variable = Variables.LocalVariable( owner=self, variable_name=variable.getName() ) for variable_trace in variable.traces: if variable_trace.getOwner() is self: new_variable.addTrace(variable_trace) new_variable.updateUsageState() self.locals_scope.unregisterClosureVariable(variable) self.locals_scope.registerProvidedVariable(new_variable) updateVariableUsage( provider=self, old_variable=variable, new_variable=new_variable ) def hasClosureVariable(self, variable): return variable in self.taken def getVariableForAssignment(self, variable_name): # print("ASS func", self, variable_name) if self.hasTakenVariable(variable_name): result = self.getTakenVariable(variable_name) else: result = self.getProvidedVariable(variable_name) return result def getVariableForReference(self, variable_name): # print( "REF func", self, variable_name ) if self.hasProvidedVariable(variable_name): result = self.getProvidedVariable(variable_name) else: result = self.getClosureVariable(variable_name=variable_name) # Remember that we need that closure variable for something, so # we don't create it again all the time. if not result.isModuleVariable(): self.locals_scope.registerClosureVariable(result) entry_point = self.getEntryPoint() # For "exec" containing/star import containing, we raise this exception to indicate # that instead of merely a variable, to be assigned, we need to replace with locals # dict access. if ( python_version < 0x300 and not entry_point.isExpressionClassBody() and not entry_point.isPythonMainModule() and result.isModuleVariable() and entry_point.isUnoptimized() ): raise MaybeLocalVariableUsage return result def getVariableForClosure(self, variable_name): # print( "getVariableForClosure", self.getCodeName(), variable_name, self.isUnoptimized() ) if self.hasProvidedVariable(variable_name): return self.getProvidedVariable(variable_name) return self.takeVariableForClosure(variable_name) def takeVariableForClosure(self, variable_name): result = self.provider.getVariableForClosure(variable_name) self.taken.add(result) return result def createProvidedVariable(self, variable_name): # print("createProvidedVariable", self, variable_name) assert self.locals_scope, self return self.locals_scope.getLocalVariable( variable_name=variable_name, owner=self ) def addNonlocalsDeclaration(self, names, user_provided, source_ref): """Add a nonlocal declared name. This happens during tree building, and is a Python3 only feature. We remember the names for later use through the function @consumeNonlocalDeclarations """ if self.non_local_declarations is None: self.non_local_declarations = [] self.non_local_declarations.append((names, user_provided, source_ref)) def consumeNonlocalDeclarations(self): """Return the nonlocal declared names for this function. There may not be any, which is why we assigned it to None originally and now check and return empty tuple in that case. """ result = self.non_local_declarations or () self.non_local_declarations = None return result def getFunctionName(self): return self.name def getFunctionQualname(self): """Function __qualname__ new in CPython3.3 Should contain some kind of full name descriptions for the closure to recognize and will be used for outputs. """ function_name = self.getFunctionName() if python_version < 0x340: provider = self.getParentVariableProvider() else: provider = self.qualname_provider if provider.isCompiledPythonModule(): return function_name elif provider.isExpressionClassBody(): return provider.getFunctionQualname() + "." + function_name else: return provider.getFunctionQualname() + ".." + function_name def computeExpression(self, trace_collection): assert False # Function body is quite irreplaceable. return self, None, None def mayRaiseException(self, exception_type): body = self.subnode_body if body is None: return False else: return self.subnode_body.mayRaiseException(exception_type) def getFunctionInlineCost(self, values): """Cost of inlining this function with given arguments Returns: None or integer values, None means don't do it. """ # For overload, pylint: disable=no-self-use,unused-argument return None def optimizeUnusedClosureVariables(self): """Gets called once module is complete, to consider giving up on closure variables.""" changed = False for closure_variable in self.getClosureVariables(): # Need to take closure of those either way if ( closure_variable.isParameterVariable() and self.isExpressionGeneratorObjectBody() ): continue empty = self.trace_collection.hasEmptyTraces(closure_variable) if empty: changed = True self.trace_collection.signalChange( "var_usage", self.source_ref, message="Remove unused closure variable '%s'." % closure_variable.getName(), ) self.removeClosureVariable(closure_variable) return changed def optimizeVariableReleases(self): for parameter_variable in self.getParameterVariablesWithManualRelease(): read_only = self.trace_collection.hasReadOnlyTraces(parameter_variable) if read_only: self.trace_collection.signalChange( "var_usage", self.source_ref, message="Schedule removal releases of unassigned parameter variable '%s'." % parameter_variable.getName(), ) self.removeVariableReleases(parameter_variable) class ExpressionFunctionEntryPointBase(EntryPointMixin, ExpressionFunctionBodyBase): __slots__ = ("trace_collection", "code_object", "locals_scope", "auto_release") def __init__( self, provider, name, code_object, code_prefix, flags, auto_release, source_ref ): ExpressionFunctionBodyBase.__init__( self, provider=provider, name=name, code_prefix=code_prefix, flags=flags, body=None, source_ref=source_ref, ) EntryPointMixin.__init__(self) self.code_object = code_object provider.getParentModule().addFunction(self) if flags is not None and "has_exec" in flags: locals_kind = "python2_function_exec" else: locals_kind = "python_function" self.locals_scope = getLocalsDictHandle( "locals_%s" % self.getCodeName(), locals_kind, self ) # Automatic parameter variable releases. self.auto_release = auto_release or None def getDetails(self): result = ExpressionFunctionBodyBase.getDetails(self) result["auto_release"] = tuple(sorted(self.auto_release or ())) return result def getCodeObject(self): return self.code_object def computeFunctionRaw(self, trace_collection): from nuitka.optimizations.TraceCollections import ( TraceCollectionFunction, ) trace_collection = TraceCollectionFunction( parent=trace_collection, function_body=self ) old_collection = self.setTraceCollection(trace_collection) self.computeFunction(trace_collection) trace_collection.updateVariablesFromCollection(old_collection, self.source_ref) def computeFunction(self, trace_collection): statements_sequence = self.subnode_body # TODO: Lift this restriction to only functions here and it code generation. if statements_sequence is not None and self.isExpressionFunctionBody(): if statements_sequence.subnode_statements[0].isStatementReturnNone(): self.clearChild("body") statements_sequence.finalize() statements_sequence = None if statements_sequence is not None: result = statements_sequence.computeStatementsSequence( trace_collection=trace_collection ) if result is not statements_sequence: self.setChild("body", result) def removeVariableReleases(self, variable): assert variable in self.locals_scope.providing.values(), (self, variable) if self.auto_release is None: self.auto_release = set() self.auto_release.add(variable) def getParameterVariablesWithManualRelease(self): """Return the list of parameter variables that have release statements. These are for consideration if these can be dropped, and if so, they are releases automatically by function code. """ return tuple( variable for variable in self.locals_scope.getProvidedVariables() if not self.auto_release or variable not in self.auto_release if variable.isParameterVariable() if variable.getOwner() is self ) def isAutoReleaseVariable(self, variable): """Is this variable to be automatically released.""" return self.auto_release is not None and variable in self.auto_release def getFunctionVariablesWithAutoReleases(self): """Return the list of function variables that should be released at exit.""" if self.auto_release is None: return () return tuple( variable for variable in self.locals_scope.getProvidedVariables() if variable in self.auto_release ) @staticmethod def getConstantReturnValue(): """Special function that checks if code generation allows to use common C code. Notes: This is only done for standard functions. """ return False, False class ExpressionFunctionBody( ExpressionNoSideEffectsMixin, MarkUnoptimizedFunctionIndicatorMixin, ExpressionFunctionEntryPointBase, ): kind = "EXPRESSION_FUNCTION_BODY" # TODO: These should be more special than the general type in order to not cover exec ones. __slots__ = ( "unoptimized_locals", "unqualified_exec", "doc", "return_exception", "needs_creation", "needs_direct", "cross_module_use", "parameters", ) if python_version >= 0x340: __slots__ += ("qualname_setup",) checkers = { # TODO: Is "None" really an allowed value. "body": checkStatementsSequenceOrNone } def __init__( self, provider, name, code_object, doc, parameters, flags, auto_release, source_ref, ): ExpressionFunctionEntryPointBase.__init__( self, provider=provider, name=name, code_object=code_object, code_prefix="function", flags=flags, auto_release=auto_release, source_ref=source_ref, ) MarkUnoptimizedFunctionIndicatorMixin.__init__(self, flags) self.doc = doc # Indicator if the return value exception might be required. self.return_exception = False # Indicator if the function needs to be created as a function object. self.needs_creation = False # Indicator if the function is called directly. self.needs_direct = False # Indicator if the function is used outside of where it's defined. self.cross_module_use = False if python_version >= 0x340: self.qualname_setup = None self.parameters = parameters self.parameters.setOwner(self) for variable in self.parameters.getAllVariables(): self.locals_scope.registerProvidedVariable(variable) def getDetails(self): return { "name": self.getFunctionName(), "ref_name": self.getCodeName(), "parameters": self.getParameters(), "code_object": self.code_object, "provider": self.provider.getCodeName(), "doc": self.doc, "flags": self.flags, } def getDetailsForDisplay(self): result = { "name": self.getFunctionName(), "provider": self.provider.getCodeName(), "flags": self.flags, } result.update(self.parameters.getDetails()) if self.code_object: result.update(self.code_object.getDetails()) if self.doc is not None: result["doc"] = self.doc return result @classmethod def fromXML(cls, provider, source_ref, **args): assert provider is not None parameter_spec_args = {} code_object_args = {} other_args = {} for key, value in args.items(): if key.startswith("ps_"): parameter_spec_args[key] = value elif key.startswith("co_"): code_object_args[key] = value elif key == "code_flags": code_object_args["future_spec"] = fromFlags(args["code_flags"]) else: other_args[key] = value parameters = ParameterSpec(**parameter_spec_args) code_object = CodeObjectSpec(**code_object_args) # The empty doc string and no doc string are distinguished by presence. The # most common case is going to be not present. if "doc" not in other_args: other_args["doc"] = None return cls( provider=provider, parameters=parameters, code_object=code_object, source_ref=source_ref, **other_args ) @staticmethod def isExpressionFunctionBody(): return True def getParent(self): assert False def getDoc(self): return self.doc def getParameters(self): return self.parameters def needsCreation(self): return self.needs_creation def markAsNeedsCreation(self): self.needs_creation = True def needsDirectCall(self): return self.needs_direct def markAsDirectlyCalled(self): self.needs_direct = True def isCrossModuleUsed(self): return self.cross_module_use def markAsCrossModuleUsed(self): self.cross_module_use = True def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): # TODO: Until we have something to re-order the arguments, we need to # skip this. For the immediate need, we avoid this complexity, as a # re-ordering will be needed. assert False, self @staticmethod def isCompileTimeConstant(): # TODO: It's actually pretty much compile time accessible maybe, but that # would require extra effort. return False # TODO: This is an overload that contradicts no side effects, this might be # used by outside code, not removed, but we should investigate this. def mayRaiseException(self, exception_type): body = self.subnode_body return body is not None and body.mayRaiseException(exception_type) def markAsExceptionReturnValue(self): self.return_exception = True def needsExceptionReturnValue(self): return self.return_exception def getConstantReturnValue(self): """Special function that checks if code generation allows to use common C code.""" body = self.subnode_body if body is None: return True, None first_statement = body.subnode_statements[0] if first_statement.isStatementReturnConstant(): constant_value = first_statement.getConstant() # TODO: For mutable constants, we could also have something, but it would require an indicator # flag to make a deep copy. if not isMutable(constant_value): return True, constant_value else: return False, False else: return False, False class ExpressionFunctionPureBody(ExpressionFunctionBody): kind = "EXPRESSION_FUNCTION_PURE_BODY" __slots__ = ( # These need only one optimization ever. "optimization_done", ) def __init__( self, provider, name, code_object, doc, parameters, flags, auto_release, source_ref, ): ExpressionFunctionBody.__init__( self, provider=provider, name=name, code_object=code_object, doc=doc, parameters=parameters, flags=flags, auto_release=auto_release, source_ref=source_ref, ) self.optimization_done = False def computeFunctionRaw(self, trace_collection): if self.optimization_done: for function_body in self.trace_collection.getUsedFunctions(): trace_collection.onUsedFunction(function_body) def mySignal(tag, source_ref, change_desc): if _is_verbose: optimization_logger.info( "{source_ref} : {tags} : {message}".format( source_ref=source_ref.getAsString(), tags=tag, message=change_desc() if inspect.isfunction(change_desc) else change_desc, ) ) tags.add(tag) tags = set() while 1: trace_collection = TraceCollectionPureFunction(function_body=self) old_collection = self.setTraceCollection(trace_collection) with withChangeIndicationsTo(mySignal): self.computeFunction(trace_collection) trace_collection.updateVariablesFromCollection( old_collection, self.source_ref ) if tags: tags.clear() else: break self.optimization_done = True class ExpressionFunctionPureInlineConstBody(ExpressionFunctionBody): kind = "EXPRESSION_FUNCTION_PURE_INLINE_CONST_BODY" def getFunctionInlineCost(self, values): return 0 def _convertNoneConstantOrEmptyDictToNone(node): if node is None: return None elif node.isExpressionConstantNoneRef(): return None elif node.isExpressionConstantDictEmptyRef(): return None else: return node # TODO: Function direct call node ought to be here too. class ExpressionFunctionCreation( SideEffectsFromChildrenMixin, ExpressionChildrenHavingBase ): kind = "EXPRESSION_FUNCTION_CREATION" __slots__ = ("variable_closure_traces",) # Note: The order of evaluation for these is a bit unexpected, but # true. Keyword defaults go first, then normal defaults, and annotations of # all kinds go last. # A bug of CPython3.x not fixed before version 3.4, see bugs.python.org/issue16967 kw_defaults_before_defaults = python_version < 0x340 if kw_defaults_before_defaults: named_children = ("kw_defaults", "defaults", "annotations", "function_ref") else: named_children = ("defaults", "kw_defaults", "annotations", "function_ref") checkers = {"kw_defaults": _convertNoneConstantOrEmptyDictToNone} def __init__(self, function_ref, defaults, kw_defaults, annotations, source_ref): assert kw_defaults is None or kw_defaults.isExpression() assert annotations is None or annotations.isExpression() assert function_ref.isExpressionFunctionRef() ExpressionChildrenHavingBase.__init__( self, values={ "function_ref": function_ref, "defaults": tuple(defaults), "kw_defaults": kw_defaults, "annotations": annotations, }, source_ref=source_ref, ) self.variable_closure_traces = None def getName(self): return self.subnode_function_ref.getName() @staticmethod def getTypeShape(): return tshape_function def computeExpression(self, trace_collection): self.variable_closure_traces = [] for ( closure_variable ) in self.subnode_function_ref.getFunctionBody().getClosureVariables(): trace = trace_collection.getVariableCurrentTrace(closure_variable) trace.addNameUsage() self.variable_closure_traces.append((closure_variable, trace)) kw_defaults = self.subnode_kw_defaults if kw_defaults is not None: kw_defaults.onContentEscapes(trace_collection) for default in self.subnode_defaults: default.onContentEscapes(trace_collection) # TODO: Function body may know something too. return self, None, None def mayRaiseException(self, exception_type): for default in self.subnode_defaults: if default.mayRaiseException(exception_type): return True kw_defaults = self.subnode_kw_defaults if kw_defaults is not None and kw_defaults.mayRaiseException(exception_type): return True annotations = self.subnode_annotations if annotations is not None and annotations.mayRaiseException(exception_type): return True return False def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Until we have something to re-order the keyword arguments, we # need to skip this. For the immediate need, we avoid this complexity, # as a re-ordering will be needed. if call_kw is not None and not call_kw.isExpressionConstantDictEmptyRef(): return call_node, None, None if call_args is None: args_tuple = () else: assert ( call_args.isExpressionConstantTupleRef() or call_args.isExpressionMakeTuple() ) args_tuple = call_args.getIterationValues() function_body = self.subnode_function_ref.getFunctionBody() # TODO: Actually the above disables it entirely, as it is at least # the empty dictionary node in any case. We will need some enhanced # interfaces for "matchCall" to work on. call_spec = function_body.getParameters() try: args_dict = matchCall( func_name=self.getName(), args=call_spec.getArgumentNames(), kw_only_args=call_spec.getKwOnlyParameterNames(), star_list_arg=call_spec.getStarListArgumentName(), star_dict_arg=call_spec.getStarDictArgumentName(), star_list_single_arg=False, num_defaults=call_spec.getDefaultCount(), num_posonly=call_spec.getPosOnlyParameterCount(), positional=args_tuple, pairs=(), ) values = [args_dict[name] for name in call_spec.getParameterNames()] # TODO: Not handling default values either yet. if None in values: return call_node, None, None # TODO: This is probably something that the matchCall ought to do # for us, but that will need cleanups. Also these functions and # nodes ought to work with # ordered dictionaries maybe. if call_spec.getStarDictArgumentName(): values[-1] = makeDictCreationOrConstant2( keys=[value[0] for value in values[-1]], values=[value[1] for value in values[-1]], source_ref=call_node.source_ref, ) result = ExpressionFunctionCall( function=self, values=values, source_ref=call_node.source_ref ) return ( result, "new_statements", # TODO: More appropriate tag maybe. """\ Replaced call to created function body '%s' with direct \ function call.""" % self.getName(), ) except TooManyArguments as e: result = wrapExpressionWithSideEffects( new_node=makeRaiseExceptionReplacementExpressionFromInstance( expression=call_node, exception=e.getRealException() ), old_node=call_node, side_effects=call_node.extractSideEffectsPreCall(), ) return ( result, "new_raise", # TODO: More appropriate tag maybe. """Replaced call to created function body '%s' to argument \ error""" % self.getName(), ) def getClosureVariableVersions(self): return self.variable_closure_traces class ExpressionFunctionRef(ExpressionNoSideEffectsMixin, ExpressionBase): kind = "EXPRESSION_FUNCTION_REF" __slots__ = "function_body", "code_name" def __init__(self, source_ref, function_body=None, code_name=None): assert function_body is not None or code_name is not None assert code_name != "None" ExpressionBase.__init__(self, source_ref=source_ref) self.function_body = function_body self.code_name = code_name def finalize(self): del self.parent del self.function_body def getName(self): return self.function_body.getName() def getDetails(self): return {"function_body": self.function_body} def getDetailsForDisplay(self): return {"code_name": self.getFunctionBody().getCodeName()} def getFunctionBody(self): if self.function_body is None: module_code_name, _ = self.code_name.split("$$$", 1) from nuitka.ModuleRegistry import getModuleFromCodeName module = getModuleFromCodeName(module_code_name) self.function_body = module.getFunctionFromCodeName(self.code_name) return self.function_body def computeExpressionRaw(self, trace_collection): trace_collection.onUsedFunction(self.getFunctionBody()) # TODO: Function after collection may now know something. return self, None, None class ExpressionFunctionCall(ExpressionChildrenHavingBase): """Shared function call. This is for calling created function bodies with multiple users. Not clear if such a thing should exist. But what this will do is to have respect for the fact that there are multiple such calls. """ kind = "EXPRESSION_FUNCTION_CALL" __slots__ = ("variable_closure_traces",) named_children = ("function", "values") def __init__(self, function, values, source_ref): assert function.isExpressionFunctionCreation() ExpressionChildrenHavingBase.__init__( self, values={"function": function, "values": tuple(values)}, source_ref=source_ref, ) self.variable_closure_traces = None def computeExpression(self, trace_collection): function = self.subnode_function function_body = function.subnode_function_ref.getFunctionBody() if function_body.mayRaiseException(BaseException): trace_collection.onExceptionRaiseExit(BaseException) values = self.subnode_values # Ask for function for its cost. cost = function_body.getFunctionInlineCost(values) if cost is not None and cost < 50: from nuitka.optimizations.FunctionInlining import ( convertFunctionCallToOutline, ) result = convertFunctionCallToOutline( provider=self.getParentVariableProvider(), function_body=function_body, values=values, call_source_ref=self.source_ref, ) return ( result, "new_statements", lambda: "Function call to '%s' in-lined." % function_body.getCodeName(), ) self.variable_closure_traces = [] for closure_variable in function_body.getClosureVariables(): trace = trace_collection.getVariableCurrentTrace(closure_variable) trace.addNameUsage() self.variable_closure_traces.append((closure_variable, trace)) return self, None, None def mayRaiseException(self, exception_type): function = self.subnode_function if function.subnode_function_ref.getFunctionBody().mayRaiseException( exception_type ): return True values = self.subnode_values for value in values: if value.mayRaiseException(exception_type): return True return False def getClosureVariableVersions(self): return self.variable_closure_traces Nuitka-0.6.19.1/nuitka/nodes/IterationHandles.py0000600000372100037210000002573414166627112026514 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Batakrishna Sahu, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Node for Iteration Handles. """ import math from abc import abstractmethod from nuitka.__past__ import getMetaClassBase, xrange class IterationHandleBase(getMetaClassBase("IterationHandle")): """Base class for Iteration Handles.""" @abstractmethod def getNextValueExpression(self): """Abstract method to get next iteration value.""" @abstractmethod def getIterationValueWithIndex(self, value_index): # TODO: Have one doc string, and it applies to all derived methods. """Abstract method for random access of the expression.""" def getNextValueTruth(self): """Returns truth value of the next expression or Stops the iteration handle if end is reached. """ iteration_value = self.getNextValueExpression() if iteration_value is None: return StopIteration return iteration_value.getTruthValue() def getAllElementTruthValue(self): """Returns truth value for 'all' on 'lists'. It returns True: if all the elements of the list are True, False: if any element in the list is False, None: if number of elements in the list is greater than 256 or any element is Unknown. """ all_true = True count = 0 while True: truth_value = self.getNextValueTruth() if truth_value is StopIteration: break if count > 256: return None if truth_value is False: return False if truth_value is None: all_true = None count += 1 return all_true class ConstantIterationHandleBase(IterationHandleBase): """Base class for the Constant Iteration Handles. Attributes ---------- constant_node : node_object Instance of the calling node. Methods ------- __repr__() Prints representation of the ConstantIterationHandleBase and it's children objects getNextValueExpression() Returns the next iteration value getNextValueTruth() Returns the boolean value of the next handle """ def __init__(self, constant_node): assert constant_node.isIterableConstant() self.constant_node = constant_node self.iter = iter(self.constant_node.constant) def __repr__(self): return "<%s of %r>" % (self.__class__.__name__, self.constant_node) def getNextValueExpression(self): # TODO: Better doc string. """Returns truth value of the next expression or Stops the iteration handle and returns None if end is reached. """ try: from .ConstantRefNodes import makeConstantRefNode return makeConstantRefNode( constant=next(self.iter), source_ref=self.constant_node.source_ref ) except StopIteration: return None def getNextValueTruth(self): """Return the truth value of the next iteration value or StopIteration.""" try: iteration_value = next(self.iter) except StopIteration: return StopIteration return bool(iteration_value) def getIterationValueWithIndex(self, value_index): return None class ConstantIndexableIterationHandle(ConstantIterationHandleBase): """Class for the constants that are indexable. Attributes ---------- constant_node : node_object Instance of the calling node. Methods ------- getIterationValueWithIndex(value_index) Sequential access of the constants """ def __init__(self, constant_node): ConstantIterationHandleBase.__init__(self, constant_node) def getIterationValueWithIndex(self, value_index): """Tries to return constant value at the given index. Parameters ---------- value_index : int Index value of the element to be returned """ try: from .ConstantRefNodes import makeConstantRefNode return makeConstantRefNode( constant=self.constant_node.constant[value_index], source_ref=self.constant_node.source_ref, ) except IndexError: return None class ConstantTupleIterationHandle(ConstantIndexableIterationHandle): pass class ConstantListIterationHandle(ConstantIndexableIterationHandle): pass class ConstantStrIterationHandle(ConstantIndexableIterationHandle): pass class ConstantUnicodeIterationHandle(ConstantIndexableIterationHandle): pass class ConstantBytesIterationHandle(ConstantIndexableIterationHandle): pass class ConstantBytearrayIterationHandle(ConstantIndexableIterationHandle): pass class ConstantRangeIterationHandle(ConstantIndexableIterationHandle): pass class ConstantSetAndDictIterationHandleBase(ConstantIterationHandleBase): """Class for the set and dictionary constants.""" def __init__(self, constant_node): ConstantIterationHandleBase.__init__(self, constant_node) class ConstantSetIterationHandle(ConstantSetAndDictIterationHandleBase): pass class ConstantFrozensetIterationHandle(ConstantSetAndDictIterationHandleBase): pass class ConstantDictIterationHandle(ConstantSetAndDictIterationHandleBase): pass class ListAndTupleContainerMakingIterationHandle(IterationHandleBase): """Class for list and tuple container making expression Attributes ---------- constant_node : node_object Instance of the calling node. Methods ------- __repr__() Prints representation of the ListAndTupleContainerMakingIterationHandle object getNextValueExpression() Returns the next iteration value getNextValueTruth() Returns the boolean value of the next handle getIterationValueWithIndex(value_index) Sequential access of the expression """ def __init__(self, elements): self.elements = elements self.iter = iter(self.elements) def __repr__(self): return "<%s of %r>" % (self.__class__.__name__, self.elements) def getNextValueExpression(self): """Return the next iteration value or StopIteration exception if the iteration has reached the end """ try: return next(self.iter) except StopIteration: return None def getIterationValueWithIndex(self, value_index): """Tries to return constant value at the given index. Parameters ---------- value_index : int Index value of the element to be returned """ try: return self.elements[value_index] except IndexError: return None class RangeIterationHandleBase(IterationHandleBase): """Iteration handle class for range nodes Attributes ---------- low : int Optional. An integer number specifying at which position to start. Default is 0 high : int Optional. An integer number specifying at which position to end. step : int Optional. An integer number specifying the incrementation. Default is 1 """ step = 1 def __init__(self, low_value, range_value, source_ref): self.low = low_value self.iter = iter(range_value) self.source_ref = source_ref def getNextValueExpression(self): """Return the next iteration value or StopIteration exception if the iteration has reached the end """ try: from .ConstantRefNodes import makeConstantRefNode return makeConstantRefNode( constant=next(self.iter), source_ref=self.source_ref ) except StopIteration: return None @abstractmethod def getIterationLength(self): """return length""" def getIterationValueWithIndex(self, value_index): """Tries to return constant value at the given index. Parameters ---------- value_index : int Index value of the element to be returned """ if value_index < self.getIterationLength(): from .ConstantRefNodes import makeConstantRefNode return makeConstantRefNode( constant=value_index * self.step + self.low, source_ref=self.source_ref ) else: return IndexError def getNextValueTruth(self): """Return the boolean value of the next iteration handle.""" try: iteration_value = next(self.iter) except StopIteration: return StopIteration return bool(iteration_value) @staticmethod def getAllElementTruthValue(): return True class IterationHandleRange1(RangeIterationHandleBase): """Iteration handle for range(low,)""" def __init__(self, low_value, source_ref): RangeIterationHandleBase.__init__( self, low_value, xrange(low_value), source_ref ) def getIterationLength(self): return max(0, self.low) @staticmethod def getAllElementTruthValue(): return False class IterationHandleRange2(RangeIterationHandleBase): """Iteration handle for ranges(low, high)""" def __init__(self, low_value, high_value, source_ref): RangeIterationHandleBase.__init__( self, low_value, xrange(low_value, high_value), source_ref ) self.high = high_value def getIterationLength(self): return max(0, self.high - self.low) class IterationHandleRange3(RangeIterationHandleBase): """Iteration handle for ranges(low, high, step)""" def __init__(self, low_value, high_value, step_value, source_ref): RangeIterationHandleBase.__init__( self, low_value, xrange(low_value, high_value, step_value), source_ref ) self.high = high_value self.step = step_value def getIterationLength(self): if self.low < self.high: if self.step < 0: estimate = 0 else: estimate = math.ceil(float(self.high - self.low) / self.step) else: if self.step > 0: estimate = 0 else: estimate = math.ceil(float(self.high - self.low) / self.step) assert estimate >= 0 return int(estimate) Nuitka-0.6.19.1/nuitka/nodes/LocalsDictNodes.py0000600000372100037210000005130414166627112026261 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nodes that deal with locals, as dict or mapping. The mapping types can be optimized into dict types, and the ones with fallback can be optimized to no fallback variants. """ from nuitka.optimizations.TraceCollections import TraceCollectionBranch from nuitka.PythonVersions import python_version from nuitka.tree.TreeHelpers import makeStatementsSequence from .AssignNodes import ( StatementAssignmentVariable, StatementDelVariable, StatementReleaseVariable, ) from .ConditionalNodes import ExpressionConditional from .ConstantRefNodes import ExpressionConstantDictEmptyRef from .ExpressionBases import ExpressionBase, ExpressionChildHavingBase from .NodeBases import StatementBase, StatementChildHavingBase from .VariableRefNodes import ExpressionTempVariableRef class ExpressionLocalsVariableRefOrFallback(ExpressionChildHavingBase): kind = "EXPRESSION_LOCALS_VARIABLE_REF_OR_FALLBACK" named_child = "fallback" __slots__ = ("locals_scope", "variable", "variable_trace") def __init__(self, locals_scope, variable_name, fallback, source_ref): ExpressionChildHavingBase.__init__(self, value=fallback, source_ref=source_ref) assert locals_scope is not None self.locals_scope = locals_scope self.variable = locals_scope.getLocalsDictVariable(variable_name) self.variable_trace = None def getDetails(self): return { "locals_scope": self.locals_scope, "variable_name": self.getVariableName(), } def getVariableName(self): return self.variable.getName() def getLocalsDictScope(self): return self.locals_scope def computeExpressionRaw(self, trace_collection): self.variable_trace = trace_collection.getVariableCurrentTrace( variable=self.variable ) replacement = self.variable_trace.getReplacementNode(self) if replacement is not None: trace_collection.signalChange( "new_expression", self.source_ref, "Value propagated for '%s' from '%s'." % ( self.variable.getName(), replacement.getSourceReference().getAsString(), ), ) # Need to compute the replacement still. return replacement.computeExpressionRaw(trace_collection) no_exec = not self.locals_scope.isUnoptimizedFunctionScope() # if we can be sure if doesn't have a value set, go to the fallback directly. if no_exec and self.variable_trace.mustNotHaveValue(): return trace_collection.computedExpressionResultRaw( self.subnode_fallback, "new_expression", "Name '%s' cannot be in locals dict." % self.variable.getName(), ) # If we cannot be sure if the value is set, then we need the fallback, # otherwise we could remove it simply. if no_exec and self.variable_trace.mustHaveValue(): trace_collection.signalChange( "new_expression", self.source_ref, "Name '%s' must be in locals dict." % self.variable.getName(), ) result = ExpressionLocalsVariableRef( locals_scope=self.locals_scope, variable_name=self.variable.getName(), source_ref=self.source_ref, ) # Need to compute the replacement still. return result.computeExpressionRaw(trace_collection) else: trace_collection.onExceptionRaiseExit(BaseException) branch_fallback = TraceCollectionBranch( parent=trace_collection, name="fallback node usage" ) branch_fallback.computeBranch(self.subnode_fallback) trace_collection.mergeBranches(branch_fallback, None) return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) trace_collection.onControlFlowEscape(self) if ( self.variable.getName() in ("dir", "eval", "exec", "execfile", "locals", "vars") and self.subnode_fallback.isExpressionVariableRef() and self.subnode_fallback.getVariable().isIncompleteModuleVariable() ): # Just inform the collection that all escaped. trace_collection.onLocalsUsage(self.getLocalsDictScope()) if ( self.subnode_fallback.isExpressionBuiltinRef() or self.subnode_fallback.isExpressionConstantTypeRef() ): variable_name = self.variable.getName() # Create a cloned node with the locals variable. call_node_clone = call_node.makeClone() call_node_clone.setChild( "called", ExpressionLocalsVariableRef( locals_scope=self.locals_scope, variable_name=variable_name, source_ref=self.source_ref, ), ) # Make the original one for the fallback call_node = call_node.makeCloneShallow() call_node.setChild("called", self.subnode_fallback) result = ExpressionConditional( condition=ExpressionLocalsVariableCheck( locals_scope=self.locals_scope, variable_name=variable_name, source_ref=self.source_ref, ), expression_yes=call_node_clone, expression_no=call_node, source_ref=self.source_ref, ) return ( result, "new_expression", "Moved call of uncertain dict variable '%s' to inside." % variable_name, ) return call_node, None, None # TODO: Specialize for Python3 maybe to save attribute for Python2. may_raise_access = python_version >= 0x300 def mayRaiseException(self, exception_type): if self.may_raise_access and self.locals_scope.hasShapeDictionaryExact(): return True return self.subnode_fallback.mayRaiseException(exception_type) # TODO: Why is this unused. class ExpressionLocalsMappingVariableRefOrFallback( ExpressionLocalsVariableRefOrFallback ): kind = "EXPRESSION_LOCALS_MAPPING_VARIABLE_REF_OR_FALLBACK" class ExpressionLocalsVariableRef(ExpressionBase): kind = "EXPRESSION_LOCALS_VARIABLE_REF" __slots__ = "variable", "locals_scope", "variable_trace" def __init__(self, locals_scope, variable_name, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.locals_scope = locals_scope self.variable = locals_scope.getLocalsDictVariable(variable_name) self.variable_trace = None def finalize(self): del self.parent del self.locals_scope del self.variable def getDetails(self): return { "variable_name": self.getVariableName(), "locals_scope": self.locals_scope, } def getDetailsForDisplay(self): return {"variable_name": self.getVariableName()} def getVariableName(self): return self.variable.getName() def getLocalsDictScope(self): return self.locals_scope def computeExpressionRaw(self, trace_collection): if self.locals_scope.isMarkedForPropagation(): variable_name = self.getVariableName() variable = self.locals_scope.allocateTempReplacementVariable( trace_collection=trace_collection, variable_name=variable_name ) result = ExpressionTempVariableRef( variable=variable, source_ref=self.source_ref ) result.parent = self.parent self.finalize() new_result = result.computeExpressionRaw(trace_collection) if new_result[0] is not result: assert False, (new_result, result) return ( result, "new_expression", "Replaced dictionary ref with temporary variable.", ) self.variable_trace = trace_collection.getVariableCurrentTrace( variable=self.variable ) replacement = self.variable_trace.getReplacementNode(self) if replacement is not None: trace_collection.signalChange( "new_expression", self.source_ref, "Value propagated for '%s' from '%s'." % ( self.variable.getName(), replacement.getSourceReference().getAsString(), ), ) # Need to compute the replacement still. return replacement.computeExpressionRaw(trace_collection) if not self.variable_trace.mustHaveValue(): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def computeExpressionCall(self, call_node, call_args, call_kw, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) trace_collection.onControlFlowEscape(self) return call_node, None, None def mayRaiseException(self, exception_type): return self.variable_trace is None or not self.variable_trace.mustHaveValue() class ExpressionLocalsVariableCheck(ExpressionBase): kind = "EXPRESSION_LOCALS_VARIABLE_CHECK" __slots__ = "variable_name", "locals_scope" def __init__(self, locals_scope, variable_name, source_ref): self.variable_name = variable_name ExpressionBase.__init__(self, source_ref=source_ref) self.locals_scope = locals_scope def finalize(self): del self.parent del self.locals_scope def getDetails(self): return {"locals_scope": self.locals_scope, "variable_name": self.variable_name} def getVariableName(self): return self.variable_name def getLocalsDictScope(self): return self.locals_scope def computeExpressionRaw(self, trace_collection): assert not self.locals_scope.isMarkedForPropagation() return self, None, None class StatementLocalsDictOperationSet(StatementChildHavingBase): kind = "STATEMENT_LOCALS_DICT_OPERATION_SET" named_child = "source" __slots__ = ("variable", "variable_version", "variable_trace", "locals_scope") # TODO: Specialize for Python3 maybe to save attribute for Python2. may_raise_set = python_version >= 0x300 def __init__(self, locals_scope, variable_name, value, source_ref): assert type(variable_name) is str assert value is not None StatementChildHavingBase.__init__(self, value=value, source_ref=source_ref) assert locals_scope is not None self.variable = locals_scope.getLocalsDictVariable(variable_name=variable_name) self.variable_version = self.variable.allocateTargetNumber() self.variable_trace = None self.locals_scope = locals_scope def finalize(self): del self.parent del self.locals_scope del self.variable_trace def getDetails(self): return { "locals_scope": self.locals_scope, "variable_name": self.getVariableName(), } def getVariableName(self): return self.variable.getName() def getLocalsDictScope(self): return self.locals_scope def getTypeShape(self): return self.locals_scope.getMappingValueShape(self.variable) def computeStatement(self, trace_collection): if self.locals_scope.isMarkedForPropagation(): variable_name = self.getVariableName() variable = self.locals_scope.allocateTempReplacementVariable( trace_collection=trace_collection, variable_name=variable_name ) result = StatementAssignmentVariable( source=self.subnode_source, variable=variable, source_ref=self.source_ref, ) result.parent = self.parent new_result = result.computeStatement(trace_collection) if new_result[0] is not result: assert False, (new_result, result) self.finalize() return ( result, "new_statements", "Replaced dictionary assignment with temporary variable.", ) result, change_tags, change_desc = self.computeStatementSubExpressions( trace_collection=trace_collection ) if result is not self: return result, change_tags, change_desc self.variable_trace = trace_collection.onVariableSet( variable=self.variable, version=self.variable_version, assign_node=self ) if self.may_raise_set: trace_collection.onExceptionRaiseExit(BaseException) return self, None, None def mayRaiseException(self, exception_type): return self.may_raise_set or self.subnode_source.mayRaiseException( exception_type ) @staticmethod def getStatementNiceName(): return "locals dictionary value set statement" class StatementLocalsDictOperationDel(StatementBase): kind = "STATEMENT_LOCALS_DICT_OPERATION_DEL" __slots__ = ( "variable", "variable_version", "previous_trace", "locals_scope", "tolerant", ) # TODO: Specialize for Python3 maybe to save attribute for Python2. may_raise_del = python_version >= 0x300 def __init__(self, locals_scope, variable_name, tolerant, source_ref): assert type(variable_name) is str StatementBase.__init__(self, source_ref=source_ref) assert locals_scope is not None self.locals_scope = locals_scope self.variable = locals_scope.getLocalsDictVariable(variable_name) self.variable_version = self.variable.allocateTargetNumber() self.tolerant = tolerant self.previous_trace = None def finalize(self): del self.parent del self.locals_scope del self.variable del self.previous_trace def getDetails(self): return { "variable_name": self.getVariableName(), "locals_scope": self.locals_scope, } def getVariableName(self): return self.variable.getName() def getLocalsDictScope(self): return self.locals_scope def computeStatement(self, trace_collection): # Conversion from dictionary to normal nodes is done here. if self.locals_scope.isMarkedForPropagation(): variable_name = self.getVariableName() variable = self.locals_scope.allocateTempReplacementVariable( trace_collection=trace_collection, variable_name=variable_name ) result = StatementDelVariable( variable=variable, tolerant=False, source_ref=self.source_ref ) result.parent = self.parent new_result = result.computeStatement(trace_collection) if new_result[0] is not result: assert False, (new_result, result) return ( result, "new_statements", "Replaced dictionary del with temporary variable.", ) self.previous_trace = trace_collection.getVariableCurrentTrace(self.variable) # Deleting is usage of the value, and may call code on it. This is to inhibit # just removing it. self.previous_trace.addUsage() # We may not exception exit now during the __del__ unless there is no value. # TODO: In which case, there is doing to be a NameError or UnboundLocalError. if not self.previous_trace.mustHaveValue(): trace_collection.onExceptionRaiseExit(BaseException) # Record the deletion, needs to start a new version then. _variable_trace = trace_collection.onVariableDel( variable=self.variable, version=self.variable_version, del_node=self ) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) return self, None, None def mayRaiseException(self, exception_type): return self.may_raise_del and not self.tolerant @staticmethod def getStatementNiceName(): return "locals dictionary value del statement" class StatementSetLocals(StatementChildHavingBase): kind = "STATEMENT_SET_LOCALS" named_child = "new_locals" __slots__ = ("locals_scope",) def __init__(self, locals_scope, new_locals, source_ref): StatementChildHavingBase.__init__(self, value=new_locals, source_ref=source_ref) self.locals_scope = locals_scope def finalize(self): del self.parent del self.locals_scope del self.subnode_new_locals def getDetailsForDisplay(self): return {"locals_scope": self.locals_scope.getCodeName()} def getDetails(self): return {"locals_scope": self.locals_scope} def getLocalsScope(self): return self.locals_scope def mayRaiseException(self, exception_type): return self.subnode_new_locals.mayRaiseException(exception_type) def computeStatement(self, trace_collection): new_locals = trace_collection.onExpression(self.subnode_new_locals) if new_locals.willRaiseException(BaseException): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=new_locals, node=self ) return ( result, "new_raise", """\ Setting locals already raises implicitly building new locals.""", ) if self.locals_scope.isMarkedForPropagation(): self.finalize() return ( None, "new_statements", """\ Forward propagating locals.""", ) return self, None, None @staticmethod def getStatementNiceName(): return "locals mapping init statement" class StatementSetLocalsDictionary(StatementSetLocals): kind = "STATEMENT_SET_LOCALS_DICTIONARY" def __init__(self, locals_scope, source_ref): StatementSetLocals.__init__( self, locals_scope=locals_scope, new_locals=ExpressionConstantDictEmptyRef( source_ref=source_ref, user_provided=True ), source_ref=source_ref, ) @staticmethod def mayRaiseException(exception_type): return False @staticmethod def getStatementNiceName(): return "locals dictionary init statement" class StatementReleaseLocals(StatementBase): kind = "STATEMENT_RELEASE_LOCALS" __slots__ = ("locals_scope",) def __init__(self, locals_scope, source_ref): StatementBase.__init__(self, source_ref=source_ref) self.locals_scope = locals_scope def finalize(self): del self.parent del self.locals_scope def computeStatement(self, trace_collection): if self.locals_scope.isMarkedForPropagation(): statements = [ StatementReleaseVariable(variable=variable, source_ref=self.source_ref) for variable in self.locals_scope.getPropagationVariables().values() ] result = makeStatementsSequence( statements=statements, allow_none=False, source_ref=self.source_ref ) self.finalize() return ( result, "new_statements", "Releasing temp variables instead of locals dict.", ) return self, None, None def getDetails(self): return {"locals_scope": self.locals_scope} def getLocalsScope(self): return self.locals_scope @staticmethod def mayRaiseException(exception_type): return False @staticmethod def getStatementNiceName(): return "locals dictionary release statement" Nuitka-0.6.19.1/nuitka/nodes/TypeNodes.py0000600000372100037210000002111014166627112025151 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ The type1 node. This one just determines types. It's great for optimization. We may be able to predict its value, but knowing it. In that case, we have a built-in name reference for that type to convert to, or when checking the result of it, we will then know it's limited after the fact. """ from nuitka.Builtins import builtin_names from .BuiltinRefNodes import ( ExpressionBuiltinAnonymousRef, ExpressionBuiltinRef, makeExpressionBuiltinRef, ) from .ExpressionBases import ( ExpressionBuiltinSingleArgBase, ExpressionChildHavingBase, ExpressionChildrenHavingBase, ) from .ExpressionShapeMixins import ExpressionBoolShapeExactMixin from .NodeBases import SideEffectsFromChildrenMixin from .NodeMakingHelpers import wrapExpressionWithNodeSideEffects from .shapes.BuiltinTypeShapes import tshape_type class ExpressionBuiltinType1(ExpressionBuiltinSingleArgBase): kind = "EXPRESSION_BUILTIN_TYPE1" def computeExpression(self, trace_collection): value = self.subnode_value type_shape = value.getTypeShape() if type_shape is not None: type_name = type_shape.getTypeName() if type_name is not None and type_name in __builtins__: result = ExpressionBuiltinRef( builtin_name=type_name, source_ref=value.getSourceReference() ) result = wrapExpressionWithNodeSideEffects( new_node=result, old_node=value ) return ( result, "new_builtin", "Replaced predictable type lookup with builtin type '%s'." % (type_name), ) if value.isCompileTimeConstant(): # The above code is supposed to catch these in a better way. value = value.getCompileTimeConstant() type_name = value.__class__.__name__ if type_name in builtin_names: new_node = makeExpressionBuiltinRef( builtin_name=type_name, locals_scope=None, source_ref=self.source_ref, ) else: new_node = ExpressionBuiltinAnonymousRef( builtin_name=type_name, source_ref=self.source_ref ) return ( new_node, "new_builtin", "Replaced predictable type lookup with builtin type '%s'." % (type_name), ) return self, None, None @staticmethod def getTypeShape(): return tshape_type def computeExpressionDrop(self, statement, trace_collection): from .NodeMakingHelpers import ( makeStatementExpressionOnlyReplacementNode, ) result = makeStatementExpressionOnlyReplacementNode( expression=self.subnode_value, node=statement ) return ( result, "new_statements", """\ Removed type taking for unused result.""", ) def mayRaiseException(self, exception_type): return self.subnode_value.mayRaiseException(exception_type) def mayHaveSideEffects(self): return self.subnode_value.mayHaveSideEffects() class ExpressionBuiltinSuper2(ExpressionChildrenHavingBase): """Two arguments form of super.""" kind = "EXPRESSION_BUILTIN_SUPER2" named_children = ("type_arg", "object_arg") def __init__(self, type_arg, object_arg, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"type_arg": type_arg, "object_arg": object_arg}, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Quite some cases should be possible to predict. return self, None, None class ExpressionBuiltinSuper0(ExpressionChildrenHavingBase): """Python3 form of super, arguments determined from cells and function arguments.""" kind = "EXPRESSION_BUILTIN_SUPER0" named_children = ("type_arg", "object_arg") def __init__(self, type_arg, object_arg, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"type_arg": type_arg, "object_arg": object_arg}, source_ref=source_ref, ) def computeExpression(self, trace_collection): trace_collection.onExceptionRaiseExit(BaseException) # TODO: Quite some cases should be possible to predict. return self, None, None class ExpressionBuiltinIsinstance(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_ISINSTANCE" named_children = ("instance", "classes") def __init__(self, instance, classes, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"instance": instance, "classes": classes}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict. instance = self.subnode_instance # TODO: Should be possible to query run time type instead, but we don't # have that method yet. Later this will be essential. if not instance.isCompileTimeConstant(): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None classes = self.subnode_classes if not classes.isCompileTimeConstant(): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None # So if both are compile time constant, we are able to compute it. return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: isinstance( instance.getCompileTimeConstant(), classes.getCompileTimeConstant() ), description="Built-in call to 'isinstance' computed.", ) class ExpressionBuiltinIssubclass(ExpressionChildrenHavingBase): kind = "EXPRESSION_BUILTIN_ISSUBCLASS" named_children = ("cls", "classes") def __init__(self, cls, classes, source_ref): ExpressionChildrenHavingBase.__init__( self, values={"cls": cls, "classes": classes}, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict. cls = self.subnode_cls # TODO: Should be possible to query run time type instead, but we don't # have that method yet. Later this will be essential. if not cls.isCompileTimeConstant(): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None classes = self.subnode_classes if not classes.isCompileTimeConstant(): trace_collection.onExceptionRaiseExit(BaseException) return self, None, None # So if both are compile time constant, we are able to compute it. return trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: issubclass( cls.getCompileTimeConstant(), classes.getCompileTimeConstant() ), description="Built-in call to 'issubclass' computed.", ) class ExpressionTypeCheck( ExpressionBoolShapeExactMixin, SideEffectsFromChildrenMixin, ExpressionChildHavingBase, ): kind = "EXPRESSION_TYPE_CHECK" named_child = "cls" def __init__(self, cls, source_ref): ExpressionChildHavingBase.__init__( self, value=cls, source_ref=source_ref, ) def computeExpression(self, trace_collection): # TODO: Quite some cases should be possible to predict, but I am not aware of # 100% true Python equivalent at this time. return self, None, None Nuitka-0.6.19.1/nuitka/PythonVersions.py0000600000372100037210000002230214166627112025145 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Python version specifics. This abstracts the Python version decisions. This makes decisions based on the numbers, and attempts to give them meaningful names. Where possible it should attempt to make run time detections. """ import __future__ import os import re import sys from nuitka.__past__ import WindowsError # pylint: disable=I0021,redefined-builtin def getSupportedPythonVersions(): """Officially supported Python versions for Nuitka.""" return ("2.6", "2.7", "3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10") def getPartiallySupportedPythonVersions(): """Partially supported Python versions for Nuitka.""" return () def getSupportedPythonVersionStr(): supported_python_versions = getSupportedPythonVersions() supported_python_versions_str = repr(supported_python_versions)[1:-1] supported_python_versions_str = re.sub( r"(.*),(.*)$", r"\1, or\2", supported_python_versions_str ) return supported_python_versions_str def _getPythonVersion(): big, major, minor = sys.version_info[0:3] return big * 256 + major * 16 + min(15, minor) python_version = _getPythonVersion() python_version_full_str = ".".join(str(s) for s in sys.version_info[0:3]) python_version_str = ".".join(str(s) for s in sys.version_info[0:2]) def getErrorMessageExecWithNestedFunction(): """Error message of the concrete Python in case an exec occurs in a function that takes a closure variable. """ assert python_version < 0x300 # Need to use "exec" to detect the syntax error, pylint: disable=W0122 try: exec( """ def f(): exec "" def nested(): return closure""" ) except SyntaxError as e: return e.message.replace("'f'", "'%s'") def getComplexCallSequenceErrorTemplate(): if not hasattr(getComplexCallSequenceErrorTemplate, "result"): try: # We are doing this on purpose, to get the exception. # pylint: disable=not-an-iterable,not-callable f = None f(*None) except TypeError as e: result = ( e.args[0] .replace("NoneType object", "%s") .replace("NoneType", "%s") .replace("None ", "%s ") ) getComplexCallSequenceErrorTemplate.result = result else: sys.exit("Error, cannot detect expected error message.") return getComplexCallSequenceErrorTemplate.result _needs_set_literal_reverse_insertion = None def needsSetLiteralReverseInsertion(): """For Python3, until Python3.5 ca. the order of set literals was reversed.""" # Cached result, pylint: disable=global-statement global _needs_set_literal_reverse_insertion if _needs_set_literal_reverse_insertion is None: try: value = eval("{1,1.0}.pop()") # pylint: disable=eval-used except SyntaxError: _needs_set_literal_reverse_insertion = False else: _needs_set_literal_reverse_insertion = type(value) is float return _needs_set_literal_reverse_insertion def needsDuplicateArgumentColOffset(): if python_version < 0x353: return False else: return True def getRunningPythonDLLPath(): import ctypes.wintypes MAX_PATH = 4096 buf = ctypes.create_unicode_buffer(MAX_PATH) GetModuleFileName = ctypes.windll.kernel32.GetModuleFileNameW GetModuleFileName.argtypes = ( ctypes.wintypes.HANDLE, ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD, ) GetModuleFileName.restype = ctypes.wintypes.DWORD # We trust ctypes internals here, pylint: disable=protected-access res = GetModuleFileName(ctypes.pythonapi._handle, buf, MAX_PATH) if res == 0: # Windows only code, pylint: disable=I0021,undefined-variable raise WindowsError( ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError()) ) dll_path = os.path.normcase(buf.value) assert os.path.exists(dll_path), dll_path return dll_path def getTargetPythonDLLPath(): dll_path = getRunningPythonDLLPath() from nuitka.Options import isPythonDebug if dll_path.endswith("_d.dll"): if not isPythonDebug(): dll_path = dll_path[:-6] + ".dll" if not os.path.exists(dll_path): sys.exit("Error, cannot switch to non-debug Python, not installed.") else: if isPythonDebug(): dll_path = dll_path[:-4] + "_d.dll" if not os.path.exists(dll_path): sys.exit("Error, cannot switch to debug Python, not installed.") return dll_path def isStaticallyLinkedPython(): # On Windows, there is no way to detect this from syconfig. if os.name == "nt": import ctypes return ctypes.pythonapi is None try: import sysconfig except ImportError: # Cannot detect this properly for Python 2.6, but we don't care much # about that anyway. return False result = sysconfig.get_config_var("Py_ENABLE_SHARED") == 0 return result def getPythonABI(): if hasattr(sys, "abiflags"): abiflags = sys.abiflags # Cyclic dependency here. from nuitka.Options import isPythonDebug if isPythonDebug() or hasattr(sys, "getobjects"): if not abiflags.startswith("d"): abiflags = "d" + abiflags else: abiflags = "" return abiflags _the_sys_prefix = None def getSystemPrefixPath(): """Return real sys.prefix as an absolute path breaking out of virtualenv. Note: For Nuitka, it often is OK to break out of the virtualenv, and use the original install. Mind you, this is not about executing anything, this is about building, and finding the headers to compile against that Python, we do not care about any site packages, and so on. Returns: str - path to system prefix """ global _the_sys_prefix # Cached result, pylint: disable=global-statement if _the_sys_prefix is None: sys_prefix = getattr( sys, "real_prefix", getattr(sys, "base_prefix", sys.prefix) ) sys_prefix = os.path.abspath(sys_prefix) # Some virtualenv contain the "orig-prefix.txt" as a textual link to the # target, this is often on Windows with virtualenv. There are two places to # look for. for candidate in ( "Lib/orig-prefix.txt", "lib/python%s/orig-prefix.txt" % python_version_str, ): candidate = os.path.join(sys_prefix, candidate) if os.path.exists(candidate): # Cannot use FileOperations.getFileContents() here, because of circular dependency. # pylint: disable=unspecified-encoding with open(candidate) as f: sys_prefix = f.read() # Trailing spaces in the python prefix, please not. assert sys_prefix == sys_prefix.strip() # This is another for of virtualenv references: if os.name != "nt" and os.path.islink(os.path.join(sys_prefix, ".Python")): sys_prefix = os.path.normpath( os.path.join(os.readlink(os.path.join(sys_prefix, ".Python")), "..") ) # Some virtualenv created by "venv" seem to have a different structure, where # library and include files are outside of it. if ( os.name != "nt" and python_version >= 0x330 and os.path.exists(os.path.join(sys_prefix, "bin/activate")) ): python_binary = os.path.join(sys_prefix, "bin", "python") python_binary = os.path.realpath(python_binary) sys_prefix = os.path.normpath(os.path.join(python_binary, "..", "..")) _the_sys_prefix = sys_prefix return _the_sys_prefix def getFutureModuleKeys(): result = [ "unicode_literals", "absolute_import", "division", "print_function", "generator_stop", "nested_scopes", "generators", "with_statement", ] if hasattr(__future__, "barry_as_FLUFL"): result.append("barry_as_FLUFL") if hasattr(__future__, "annotations"): result.append("annotations") return result def getImportlibSubPackages(): result = [] if python_version >= 0x270: import importlib import pkgutil for module_info in pkgutil.walk_packages(importlib.__path__): result.append(module_info[1]) return result Nuitka-0.6.19.1/nuitka/Tracing.py0000600000372100037210000001712314166627112023527 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Outputs to the user. Printing with intends or plain, mostly a compensation for the print strangeness. We want to avoid "from __future__ import print_function" in every file out there, which makes adding another debug print rather tedious. This should cover all calls/uses of "print" we have to do, and the make it easy to simply to "print for_debug" without much hassle (braces). """ from __future__ import print_function import os import sys import traceback # Written by Options module. is_quiet = False # We have to interact with displayed progress bars when doing out trace outputs. progress = None def setQuiet(): # singleton, pylint: disable=global-statement global is_quiet is_quiet = True def printIndented(level, *what): print(" " * level, *what) def printSeparator(level=0): print(" " * level, "*" * 10) def printLine(*what): print(*what) def printError(message): print(message, file=sys.stderr) def flushStandardOutputs(): sys.stdout.flush() sys.stderr.flush() def getEnableStyleCode(style): if style == "pink": style = "\033[95m" elif style == "blue": style = "\033[94m" elif style == "green": style = "\033[92m" elif style == "yellow": style = "\033[93m" elif style == "red": style = "\033[91m" elif style == "bold": style = "\033[1m" elif style == "underline": style = "\033[4m" else: style = None return style _enabled_ansi = False def _enableAnsi(): # singleton, pylint: disable=global-statement global _enabled_ansi if not _enabled_ansi: # Only necessary on Windows, as a side effect of this, ANSI colors get enabled # for the terminal and never deactivated, so we are free to use them after # this. if os.name == "nt": os.system("") _enabled_ansi = True def getDisableStyleCode(): return "\033[0m" def _my_print(file_output, is_atty, args, kwargs): if "style" in kwargs: style = kwargs["style"] del kwargs["style"] if "end" in kwargs: end = kwargs["end"] del kwargs["end"] else: end = "\n" if style is not None and is_atty: enable_style = getEnableStyleCode(style) if enable_style is None: raise ValueError( "%r is an invalid value for keyword argument style" % style ) _enableAnsi() print(enable_style, end="", **kwargs) print(*args, end=end, **kwargs) if style is not None and is_atty: print(getDisableStyleCode(), end="", **kwargs) else: print(*args, **kwargs) # Flush the output. file_output.flush() def my_print(*args, **kwargs): """Make sure we flush after every print. Not even the "-u" option does more than that and this is easy enough. Use kwarg style=[option] to print in a style listed below """ file_output = kwargs.get("file", sys.stdout) is_atty = file_output.isatty() if progress and is_atty: with progress.withExternalWritingPause(): _my_print(file_output, is_atty, args, kwargs) else: _my_print(file_output, is_atty, args, kwargs) class OurLogger(object): def __init__(self, name, quiet=False, base_style=None): self.name = name self.base_style = base_style self.is_quiet = quiet # Can disable warnings, we do that for options parsing during re-execution. self.is_no_warnings = False def my_print(self, message, **kwargs): # For overload, pylint: disable=no-self-use my_print(message, **kwargs) def warning(self, message, style="red"): if not self.is_no_warnings: if self.name: message = "%s:WARNING: %s" % (self.name, message) else: message = "WARNING: %s" % message style = style or self.base_style self.my_print(message, style=style, file=sys.stderr) def sysexit(self, message, exit_code=1): from nuitka.Progress import closeProgressBar closeProgressBar() self.my_print("FATAL: %s" % message, style="red", file=sys.stderr) sys.exit(exit_code) def sysexit_exception(self, message, exception, exit_code=1): self.my_print("FATAL: %s" % message, style="red", file=sys.stderr) traceback.print_exc() self.sysexit("FATAL:" + repr(exception), exit_code=exit_code) def isQuiet(self): return is_quiet or self.is_quiet def info(self, message, style=None): if not self.isQuiet(): if self.name: message = "%s:INFO: %s" % (self.name, message) style = style or self.base_style self.my_print(message, style=style) class FileLogger(OurLogger): def __init__(self, name, quiet=False, base_style=None, file_handle=None): OurLogger.__init__(self, name=name, quiet=quiet, base_style=base_style) self.file_handle = file_handle def my_print(self, message, **kwargs): if "file" not in kwargs: kwargs["file"] = self.file_handle or sys.stdout my_print(message, **kwargs) kwargs["file"].flush() def setFileHandle(self, file_handle): self.file_handle = file_handle def info(self, message, style=None): if not self.isQuiet() or self.file_handle: message = "%s:INFO: %s" % (self.name, message) style = style or self.base_style self.my_print(message, style=style) def debug(self, message, style=None): if self.file_handle: message = "%s:DEBUG: %s" % (self.name, message) style = style or self.base_style self.my_print(message, style=style) def info_fileoutput(self, message, other_logger, style=None): if self.file_handle: self.info(message, style=style) else: other_logger.info(message, style=style) general = OurLogger("Nuitka") plugins_logger = OurLogger("Nuitka-Plugins") recursion_logger = OurLogger("Nuitka-Recursion") progress_logger = OurLogger("Nuitka-Progress", quiet=True) memory_logger = OurLogger("Nuitka-Memory") dependencies_logger = OurLogger("Nuitka-Dependencies") optimization_logger = FileLogger("Nuitka-Optimization") pgo_logger = FileLogger("Nuitka-PGO") codegen_logger = OurLogger("Nuitka-Codegen") inclusion_logger = FileLogger("Nuitka-Inclusion") scons_logger = OurLogger("Nuitka-Scons") scons_details_logger = OurLogger("Nuitka-Scons") postprocessing_logger = OurLogger("Nuitka-Postprocessing") options_logger = OurLogger("Nuitka-Options") unusual_logger = OurLogger("Nuitka-Unusual") datacomposer_logger = OurLogger("Nuitka-Datacomposer") onefile_logger = OurLogger("Nuitka-Onefile") tools_logger = OurLogger("Nuitka-Tools") wheel_logger = OurLogger("Nuitka-Wheel") Nuitka-0.6.19.1/nuitka/distutils/0000700000372100037210000000000014167275622023612 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/distutils/Build.py0000600000372100037210000000340314166627112025217 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nuitka python -m build integration """ import contextlib import setuptools.build_meta if not hasattr(setuptools.build_meta, "suppress_known_deprecation"): @contextlib.contextmanager def suppress_known_deprecation(): yield else: suppress_known_deprecation = setuptools.build_meta.suppress_known_deprecation class NuitkaBuildMetaBackend(setuptools.build_meta._BuildMetaBackend): def build_wheel( self, wheel_directory, config_settings=None, metadata_directory=None ): with suppress_known_deprecation(): return self._build_with_temp_dir( ["bdist_nuitka"], ".whl", wheel_directory, config_settings ) _BACKEND = NuitkaBuildMetaBackend() get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel build_wheel = _BACKEND.build_wheel build_sdist = _BACKEND.build_sdist Nuitka-0.6.19.1/nuitka/distutils/DistutilCommands.py0000600000372100037210000002462414166627112027453 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nuitka distutils integration. """ import distutils.command.build # pylint: disable=I0021,import-error,no-name-in-module import distutils.command.install # pylint: disable=I0021,import-error,no-name-in-module import os import sys import wheel.bdist_wheel # pylint: disable=I0021,import-error,no-name-in-module from nuitka.__past__ import Iterable, unicode from nuitka.containers.oset import OrderedSet from nuitka.importing.Importing import ( decideModuleSourceRef, locateModule, setMainScriptDirectory, ) from nuitka.Tracing import wheel_logger from nuitka.utils.Execution import check_call from nuitka.utils.ModuleNames import ModuleName def setupNuitkaDistutilsCommands(dist, keyword, value): # If the user project setup.py includes the key "build_with_nuitka=True" all # build operations (build, bdist_wheel, install etc) will run via Nuitka. # pylint: disable=unused-argument if not value: return dist.cmdclass = dist.cmdclass or {} # Ensure is a dict dist.cmdclass["build"] = build dist.cmdclass["install"] = install dist.cmdclass["bdist_wheel"] = bdist_nuitka # Class name enforced by distutils, must match the command name. # Required by distutils, used as command name, pylint: disable=invalid-name class build(distutils.command.build.build): # pylint: disable=attribute-defined-outside-init def run(self): wheel_logger.info( "Specified packages: %s." % self.distribution.packages, style="blue" ) wheel_logger.info( "Specified modules: %s." % self.distribution.py_modules, style="blue" ) self.compile_packages = self.distribution.packages or [] self.py_modules = self.distribution.py_modules or [] # Determine self.script_module_names = OrderedSet() if self.distribution.entry_points is not None: for group, script_specs in self.distribution.entry_points.items(): for script_spec in script_specs: try: script_module_name = ( script_spec.split("=", 1)[1].strip().split(":")[0] ) except Exception as e: # Catch all the things, pylint: disable=broad-except wheel_logger.info( "Problem parsing '%s' script specification in '%s' due to %s" % (script_spec, group, e) ) self.script_module_names.add(ModuleName(script_module_name)) if not self.compile_packages and not self.py_modules: wheel_logger.sysexit( "No modules or packages specified, aborting. Did you provide packages in 'setup.cfg' or 'setup.py'?" ) # Python2 does not allow super on this old style class. distutils.command.build.build.run(self) self._build(os.path.abspath(self.build_lib)) def _find_to_build(self): """ Helper for _build Returns list containing bool (is_package) and module_names Algorithm for finding distinct packages: 1) Take minimum package 2) Find related packages that start with this name 3) Add this to the list to return, then repeat steps 1 & 2 until no more packages exist """ builds = [] # Namespace packages can use / rather than dots. py_packages = [ ModuleName(m.replace("/", ".")) for m in sorted(set(self.compile_packages)) ] py_modules = [ModuleName(m) for m in sorted(set(self.py_modules))] for script_module_name in self.script_module_names: script_module_filename = locateModule( module_name=script_module_name, parent_package=None, level=0 )[1] # Decide package or module. ( _main_added, is_package, _is_namespace, _source_ref, _source_filename, ) = decideModuleSourceRef( filename=script_module_filename, module_name=script_module_name, is_main=False, is_fake=False, logger=wheel_logger, ) if is_package: py_packages.append(script_module_name) else: py_modules.append(script_module_name) # Plain modules if they are not in packages to build. builds.extend( (False, current_module) for current_module in py_modules if not current_module.hasOneOfNamespaces(py_packages) ) while py_packages: current_package = min(py_packages) py_packages = [ p for p in py_packages if not p.hasNamespace(current_package) ] builds.append((True, current_package)) return builds def _build(self, build_lib): # High complexity, pylint: disable=too-many-branches,too-many-locals # Nuitka wants the main package by filename, probably we should stop # needing that. old_dir = os.getcwd() os.chdir(build_lib) # Search in the build directory preferably. setMainScriptDirectory(os.path.abspath(old_dir)) for is_package, module_name in self._find_to_build(): module_name, main_filename, finding = locateModule( module_name=module_name, parent_package=None, level=0, ) package = module_name.getPackageName() # Check expectations, e.g. do not compile built-in modules. assert finding == "absolute", finding if package is not None: output_dir = os.path.join(build_lib, package.asPath()) else: output_dir = build_lib command = [ sys.executable, "-m", "nuitka", "--module", "--enable-plugin=pylint-warnings", "--output-dir=%s" % output_dir, "--nofollow-import-to=*.tests", "--remove-output", ] if is_package: command.append("--include-package=%s" % module_name) else: command.append("--include-module=%s" % module_name) # Process any extra options from setuptools if "nuitka" in self.distribution.command_options: for option, value in self.distribution.command_options[ "nuitka" ].items(): option = "--" + option.lstrip("-") if ( type(value) is tuple and len(value) == 2 and value[0] == "setup.py" ): value = value[1] if value is None: command.append(option) elif isinstance(value, bool): option = "--" + ("no" if not value else "") + option.lstrip("-") command.append(option) elif isinstance(value, Iterable) and not isinstance( value, (unicode, bytes, str) ): for val in value: command.append("%s=%s" % (option, val)) else: command.append("%s=%s" % (option, value)) command.append(main_filename) # Adding traces for clarity wheel_logger.info( "Building: '%s' with command %r" % (module_name.asString(), command), style="blue", ) check_call(command, cwd=build_lib) wheel_logger.info( "Finished compilation of '%s'." % module_name.asString(), style="green" ) for root, _, filenames in os.walk(build_lib): for filename in filenames: fullpath = os.path.join(root, filename) if fullpath.lower().endswith((".py", ".pyw", ".pyc", ".pyo")): os.unlink(fullpath) self.build_lib = build_lib os.chdir(old_dir) # Required by distutils, used as command name, pylint: disable=invalid-name class install(distutils.command.install.install): # pylint: disable=attribute-defined-outside-init def finalize_options(self): distutils.command.install.install.finalize_options(self) # Ensure the purelib folder is not used self.install_lib = self.install_platlib # Required by distutils, used as command name, pylint: disable=invalid-name class bdist_nuitka(wheel.bdist_wheel.bdist_wheel): def initialize_options(self): # Register the command class overrides above dist = self.distribution dist.cmdclass = dist.cmdclass or {} # Ensure is a dict dist.cmdclass["build"] = build dist.cmdclass["install"] = install wheel.bdist_wheel.bdist_wheel.initialize_options(self) # pylint: disable=attribute-defined-outside-init def finalize_options(self): wheel.bdist_wheel.bdist_wheel.finalize_options(self) # Force module to use correct platform in name self.root_is_pure = False self.plat_name_supplied = self.plat_name is not None def write_wheelfile(self, wheelfile_base, generator=None): if generator is None: from nuitka.Version import getNuitkaVersion generator = "Nuitka (%s)" % getNuitkaVersion() wheel.bdist_wheel.bdist_wheel.write_wheelfile( self, wheelfile_base=wheelfile_base, generator=generator ) Nuitka-0.6.19.1/nuitka/distutils/__init__.py0000600000372100037210000000150114166627112025714 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/plugins/0000700000372100037210000000000014167275622023247 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/plugins/standard/0000700000372100037210000000000014167275622025047 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/plugins/standard/AntiBloat.py0000600000372100037210000002756014166627112027304 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to avoid bloat at compile time. Nuitka hard codes stupid monkey patching normally not needed here and avoids that to be done and causing massive degradations. * cffi importing setuptools is not needed, workaround that with --noinclude-setuptools-mode=nofollow if warned about including it. Setuptools includes massive amounts of build tools which use other things optionally. """ import ast from nuitka.containers.odict import OrderedDict from nuitka.Errors import NuitkaForbiddenImportEncounter from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.Yaml import parsePackageYaml class NuitkaPluginAntiBloat(NuitkaPluginBase): plugin_name = "anti-bloat" plugin_desc = ( "Patch stupid imports out of widely used library modules source codes." ) def __init__( self, noinclude_setuptools_mode, noinclude_pytest_mode, noinclude_ipython_mode, noinclude_default_mode, custom_choices, ): # Default manually to default argument value: if noinclude_setuptools_mode is None: noinclude_setuptools_mode = noinclude_default_mode if noinclude_pytest_mode is None: noinclude_pytest_mode = noinclude_default_mode if noinclude_ipython_mode is None: noinclude_ipython_mode = noinclude_default_mode self.config = parsePackageYaml(__package__, "anti-bloat.yml") self.handled_modules = OrderedDict() # These should be checked, to allow disabling anti-bloat contents. self.control_tags = set() if noinclude_setuptools_mode != "allow": self.handled_modules["setuptools"] = noinclude_setuptools_mode else: self.control_tags.add("allow_setuptools") if noinclude_pytest_mode != "allow": self.handled_modules["pytest"] = noinclude_pytest_mode else: self.control_tags.add("allow_pytest") if noinclude_ipython_mode != "allow": self.handled_modules["IPython"] = noinclude_ipython_mode else: self.control_tags.add("allow_ipython") for custom_choice in custom_choices: if ":" not in custom_choice: self.sysexit( "Error, malformed value '%s' for '--noinclude-custom-mode' used." % custom_choice ) module_name, mode = custom_choice.rsplit(":", 1) if mode not in ("error", "warning", "nofollow", "allow", "bytecode"): self.sysexit( "Error, illegal mode given '%s' in '--noinclude-custom-mode=%s'" % (mode, custom_choice) ) self.handled_modules[ModuleName(module_name)] = mode @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--noinclude-setuptools-mode", action="store", dest="noinclude_setuptools_mode", choices=("error", "warning", "nofollow", "allow"), default=None, help="""\ What to do if a setuptools import is encountered. This package can be big with dependencies, and should definitely be avoided.""", ) group.add_option( "--noinclude-pytest-mode", action="store", dest="noinclude_pytest_mode", choices=("error", "warning", "nofollow", "allow"), default=None, help="""\ What to do if a pytest import is encountered. This package can be big with dependencies, and should definitely be avoided.""", ) group.add_option( "--noinclude-IPython-mode", action="store", dest="noinclude_ipython_mode", choices=("error", "warning", "nofollow", "allow"), default=None, help="""\ What to do if a IPython import is encountered. This package can be big with dependencies, and should definitely be avoided.""", ) group.add_option( "--noinclude-default-mode", action="store", dest="noinclude_default_mode", choices=("error", "warning", "nofollow", "allow"), default="warning", help="""\ This actually provides the default "warning" value for above options, and can be used to turn all of these on.""", ) group.add_option( "--noinclude-custom-mode", action="append", dest="custom_choices", default=[], help="""\ What to do if a specific import is encountered. Format is module name, which can and should be a top level package and then one choice, "error", "warning", "nofollow", e.g. PyQt5:error.""", ) def onModuleSourceCode(self, module_name, source_code): # Complex dealing with many cases, pylint: disable=too-many-branches,too-many-locals,too-many-statements config = self.config.get(module_name) if not config: return source_code # Allow disabling config for a module with matching control tags. for control_tag in config.get("control_tags", ()): if control_tag in self.control_tags: return source_code description = config.get("description", "description not given") # To allow detection if it did anything. change_count = 0 context = {} context_code = config.get("context", "") if type(context_code) in (tuple, list): context_code = "\n".join(context_code) # We trust the yaml files, pylint: disable=eval-used,exec-used context_ready = not bool(context_code) for replace_src, replace_code in config.get("replacements", {}).items(): # Avoid the eval, if the replace doesn't hit. if replace_src not in source_code: continue if replace_code: if not context_ready: try: exec(context_code, context) except Exception as e: # pylint: disable=broad-except self.sysexit( "Error, cannot execute context code '%s' due to: %s" % (context_code, e) ) context_ready = True try: replace_dst = eval(replace_code, context) except Exception as e: # pylint: disable=broad-except self.sysexit( "Error, cannot evaluate code '%s' in '%s' due to: %s" % (replace_code, context_code, e) ) else: replace_dst = "" if type(replace_dst) is not str: self.sysexit( "Error, expression needs to generate string, not %s" % type(replace_dst) ) old = source_code source_code = source_code.replace(replace_src, replace_dst) if old != source_code: change_count += 1 append_code = config.get("append_result", "") if type(append_code) in (tuple, list): append_code = "\n".join(append_code) if append_code: if not context_ready: exec(context_code, context) context_ready = True try: append_result = eval(append_code, context) except Exception as e: # pylint: disable=broad-except self.sysexit( "Error, cannot evaluate code '%s' in '%s' due to: %s" % (append_code, context_code, e) ) source_code += "\n" + append_result change_count += 1 if change_count > 0: self.info( "Handling module '%s' with %d change(s) for: %s." % (module_name.asString(), change_count, description) ) module_code = config.get("module_code", None) if module_code is not None: assert not change_count self.info( "Handling module '%s' with full replacement : %s." % (module_name.asString(), description) ) source_code = module_code return source_code def onFunctionBodyParsing(self, module_name, function_name, body): config = self.config.get(module_name) if not config: return context = {} context_code = config.get("context", "") if type(context_code) in (tuple, list): context_code = "\n".join(context_code) # We trust the yaml files, pylint: disable=eval-used,exec-used context_ready = not bool(context_code) for change_function_name, replace_code in config.get( "change_function", {} ).items(): if function_name != change_function_name: continue if not context_ready: exec(context_code, context) context_ready = True try: replacement = eval(replace_code, context) except Exception as e: # pylint: disable=broad-except self.sysexit( "Error, cannot evaluate code '%s' in '%s' due to: %s" % (replace_code, context_code, e) ) # Single node is required, extrace the generated module body with # single expression only statement value or a function body. replacement = ast.parse(replacement).body[0] if type(replacement) is ast.Expr: body[:] = [ast.Return(replacement.value)] else: body[:] = replacement.body self.info( "Updated '%s' function '%s'." % (module_name.asString(), function_name) ) def onModuleEncounter(self, module_filename, module_name, module_kind): for handled_module_name, mode in self.handled_modules.items(): if module_name.hasNamespace(handled_module_name): # Make sure the compilation abrts. if mode == "error": raise NuitkaForbiddenImportEncounter(module_name) # Either issue a warning, or pretend the module doesn't exist for standalone or # at least will not be included. if mode == "warning": self.warning("Unwanted import of '%s' encountered." % module_name) elif mode == "nofollow": self.info( "Forcing import of '%s' to not be followed." % module_name ) return ( False, "user requested to not follow '%s' import" % module_name, ) # Do not provide an opinion about it. return None def decideCompilation(self, module_name): for handled_module_name, mode in self.handled_modules.items(): if mode != "bytecode": continue if module_name.hasNamespace(handled_module_name): return "bytecode" Nuitka-0.6.19.1/nuitka/plugins/standard/DataFileCollectorPlugin.py0000600000372100037210000001640614166627112032123 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to find data files. """ import os from nuitka import Options from nuitka.containers.oset import OrderedSet from nuitka.freezer.IncludedDataFiles import ( makeIncludedDataDirectory, makeIncludedDataFile, makeIncludedEmptyDirectories, ) from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.FileOperations import ( getFileList, resolveShellPatternToFilenames, ) from nuitka.utils.Yaml import parsePackageYaml def _getSubDirectoryFolders(module, subdirs): """Get dirnames in given subdirs of the module. Notes: All dirnames in folders below one of the subdirs are recursively retrieved and returned shortened to begin with the string of subdir. Args: module: module object subdirs: sub folder name(s) - tuple Returns: makeIncludedEmptyDirectories of found dirnames. """ module_dir = module.getCompileTimeDirectory() file_list = [] data_dirs = [os.path.join(module_dir, subdir) for subdir in subdirs] # Gather the full file list, probably makes no sense to include bytecode files file_list = sum( ( getFileList( data_dir, ignore_dirs=("__pycache__",), ignore_suffixes=(".pyc",) ) for data_dir in data_dirs ), [], ) if not file_list: msg = "No files or folders found for '%s' in subfolder(s) %r (%r)." % ( module.getFullName(), subdirs, data_dirs, ) NuitkaPluginDataFileCollector.warning(msg) is_package = module.isCompiledPythonPackage() or module.isUncompiledPythonPackage() # We need to preserve the package target path in the dist folder. if is_package: package_part = module.getFullName().asPath() else: package = module.getFullName().getPackageName() if package is None: package_part = "" else: package_part = package.asPath() item_set = OrderedSet() for f in file_list: target = os.path.join(package_part, os.path.relpath(f, module_dir)) dir_name = os.path.dirname(target) item_set.add(dir_name) return makeIncludedEmptyDirectories( source_path=module_dir, dest_paths=item_set, reason="Subdirectories of module %s" % module.getFullName(), ) class NuitkaPluginDataFileCollector(NuitkaPluginBase): plugin_name = "data-files" def __init__(self): self.config = parsePackageYaml(__package__, "data-files.yml") @classmethod def isRelevant(cls): return Options.isStandaloneMode() @staticmethod def isAlwaysEnabled(): return True def considerDataFiles(self, module): # Many cases to deal with, pylint: disable=too-many-branches module_name = module.getFullName() module_folder = module.getCompileTimeDirectory() config = self.config.get(module_name) if config: target_dir = config.get("dest_path") # Default to near module or inside package folder. if target_dir is None: if ( module.isCompiledPythonPackage() or module.isUncompiledPythonPackage() ): target_dir = module_name.asPath() else: package_name = module_name.getPackageName() if package_name is not None: target_dir = module_name.getPackageName().asPath() else: target_dir = "." patterns = config.get("patterns") if patterns is not None: if type(patterns) is not list or not patterns: self.sysexit( "Error, requiring list below 'pattern' entry for '%s' entry." % module_name ) # TODO: Pattern should be data file kind potentially. for pattern in patterns: pattern = os.path.join(module_folder, pattern) for filename in resolveShellPatternToFilenames(pattern): yield makeIncludedDataFile( source_path=filename, dest_path=os.path.normpath( os.path.join(target_dir, os.path.basename(filename)) ), reason="package data for %r" % module_name.asString(), ) empty_dirs = config.get("empty_dirs") if empty_dirs is not None: if type(empty_dirs) is not list or not empty_dirs: self.sysexit( "Error, requiring list below 'empty_dirs' entry for '%s' entry." % module_name ) yield makeIncludedEmptyDirectories( source_path=target_dir, dest_paths=tuple( os.path.join(target_dir, empty_dir) for empty_dir in empty_dirs ), reason="empty dir needed for %r" % module_name.asString(), ) empty_dir_structures = config.get("empty_dir_structures") if empty_dir_structures is not None: if type(empty_dir_structures) is not list or not empty_dir_structures: self.sysexit( "Error, requiring list below 'empty_dirs_structure' entry for '%s' entry." % module_name ) # TODO: This ignored dest_path, which is unused, but not consistent. yield _getSubDirectoryFolders(module, empty_dir_structures) dirs = config.get("dirs") if dirs is not None: if type(dirs) is not list or not dirs: self.sysexit( "Error, requiring list below 'empty_dirs_structure' entry for '%s' entry." % module_name ) for data_dir in dirs: source_path = os.path.join(module_folder, data_dir) if os.path.isdir(source_path): yield makeIncludedDataDirectory( source_path=source_path, dest_path=os.path.join(target_dir, data_dir), reason="package data directory for %r" % module_name.asString(), ) Nuitka-0.6.19.1/nuitka/plugins/standard/ConsiderPyLintAnnotationsPlugin.py0000600000372100037210000000660314166627112033725 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to take advantage of pylint or PyDev annotations. Nuitka can detect some things that PyLint and PyDev will complain about too, and sometimes it's a false alarm, so people add disable markers into their source code. Nuitka does it itself. This tries to parse the code for these markers and uses hooks to prevent Nuitka from warning about things, disabled to PyLint or Eclipse. The idea is that we won't have another mechanism for Nuitka, but use existing ones instead. The code for this is very incomplete, barely good enough to cover Nuitka's own usage of PyLint markers. PyDev is still largely to be started. You are welcome to grow both. """ import re from nuitka.__past__ import intern from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginPylintEclipseAnnotations(NuitkaPluginBase): plugin_name = "pylint-warnings" plugin_desc = "Support PyLint / PyDev linting source markers" def __init__(self): self.line_annotations = {} def checkModuleSourceCode(self, module_name, source_code): annotations = {} for count, line in enumerate(source_code.split("\n"), 1): match = re.search(r"#.*pylint:\s*disable=\s*([\w,-]+)", line) if match: comment_only = line[: line.find("#") - 1].strip() == "" if comment_only: # TODO: Parse block wide annotations too. pass else: annotations[count] = set( intern(match.strip()) for match in match.group(1).split(",") ) # Only remember them if there were any. if annotations: self.line_annotations[module_name] = annotations def suppressUnknownImportWarning(self, importing, module_name, source_ref): annotations = self.line_annotations.get(importing.getFullName(), {}) line_annotations = annotations.get(source_ref.getLineNumber(), ()) if "F0401" in line_annotations or "import-error" in line_annotations: return True return False # Disabled until it will be actually really useful, pylint: disable=using-constant-test if False: class NuitkaPluginDetectorPylintEclipseAnnotations(NuitkaPluginBase): detector_for = NuitkaPluginPylintEclipseAnnotations def onModuleSourceCode(self, module_name, source_code): if re.search(r"#\s*pylint:\s*disable=\s*(\w+)", source_code): self.warnUnusedPlugin( "Understand PyLint/PyDev annotations for warnings." ) # Do nothing to it. return source_code Nuitka-0.6.19.1/nuitka/plugins/standard/MultiprocessingPlugin.py0000600000372100037210000001572714166627112031777 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to make multiprocessing work well on Windows. On Windows, the multiprocessing modules forks new processes which then have to start from scratch. This won't work if there is no "sys.executable" to point to a "Python.exe" and won't use compiled code by default. The issue applies to accelerated and standalone mode alike. """ from nuitka import Options from nuitka.ModuleRegistry import getRootTopModule from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.PythonVersions import python_version from nuitka.tree.SourceReading import readSourceCodeFromFilename from nuitka.utils.ModuleNames import ModuleName class NuitkaPluginMultiprocessingWorkarounds(NuitkaPluginBase): """This is to make multiprocessing work with Nuitka and use compiled code. When running in accelerated mode, it's not good to fork a new Python instance to run other code, as that won't be accelerated. And when run in standalone mode, there may not even be a Python, but it's the same principle. So by default, this module is on and works around the behavior of the "multiprocessing.forking/multiprocessing.spawn/multiprocessing.manager" expectations. """ plugin_name = "multiprocessing" plugin_desc = "Required by Python's multiprocessing module" @classmethod def isRelevant(cls): return not Options.shallMakeModule() @staticmethod def getPreprocessorSymbols(): return {"_NUITKA_PLUGIN_MULTIPROCESSING_ENABLED": "1"} @staticmethod def createPreModuleLoadCode(module): full_name = module.getFullName() # TODO: Replace the setting of "sys.frozen" with a change to the source code of the # modules we want to affect from this plugin, it's a huge impact on compatibility # with other things potentially. We should do it, once the anti-bloat engine is # re-usable or supports conditional replacements based on plugin activity and is # always on. if full_name == "multiprocessing": code = """\ import sys, os sys.frozen = 1 if sys.platform == "win32" and not os.path.exists(sys.argv[0]) and not sys.argv[0].endswith(".exe"): sys.executable = sys.argv[0] + ".exe" else: sys.executable = sys.argv[0] """ return ( code, """\ Monkey patching "multiprocessing" load environment.""", ) @staticmethod def createPostModuleLoadCode(module): full_name = module.getFullName() if full_name == "multiprocessing": code = """\ try: from multiprocessing.forking import ForkingPickler except ImportError: from multiprocessing.reduction import ForkingPickler class C: def f(): pass def _reduce_compiled_method(m): if m.im_self is None: return getattr, (m.im_class, m.im_func.__name__) else: return getattr, (m.im_self, m.im_func.__name__) ForkingPickler.register(type(C().f), _reduce_compiled_method) if str is bytes: ForkingPickler.register(type(C.f), _reduce_compiled_method) """ return ( code, """\ Monkey patching "multiprocessing" for compiled methods.""", ) def onModuleInitialSet(self): from nuitka.tree.Building import buildModule # First, build the module node and then read again from the # source code. root_module = getRootTopModule() module_name = ModuleName("__parents_main__") source_code = readSourceCodeFromFilename(module_name, root_module.getFilename()) # For the call stack, this may look bad or different to what # CPython does. Using the "__import__" built-in to not spoil # or use the module namespace. The forking module was split up # into multiple modules in Python 3.4. if python_version >= 0x340: source_code += """ __import__("sys").modules["__main__"] = __import__("sys").modules[__name__] # Not needed, and can crash from minor __file__ differences, depending on invocation __import__("multiprocessing.spawn").spawn._fixup_main_from_path = lambda mod_name : None __import__("multiprocessing.spawn").spawn.freeze_support()""" else: source_code += """ __import__("sys").modules["__main__"] = __import__("sys").modules[__name__] __import__("multiprocessing.forking").forking.freeze_support()""" multiprocessing_main_module, _added = buildModule( module_filename=root_module.getCompileTimeFilename(), module_name=module_name, source_code=source_code, is_top=False, is_main=False, is_shlib=False, is_fake=module_name, hide_syntax_error=False, ) if multiprocessing_main_module.getCompilationMode() == "bytecode": multiprocessing_main_module.setSourceCode(source_code) yield multiprocessing_main_module def onModuleEncounter(self, module_filename, module_name, module_kind): # Enforce recursion in to multiprocessing for accelerated mode, which # would normally avoid this. if module_name.hasNamespace("multiprocessing"): return True, "Multiprocessing plugin needs this to monkey patch it." def decideCompilation(self, module_name): if module_name.hasNamespace("multiprocessing"): return "bytecode" # TODO: Make this demotable too. # or module_name in( "multiprocessing-preLoad", "multiprocessing-postLoad"): def onFrozenModuleSourceCode(self, module_name, is_package, source_code): if module_name == "multiprocessing.resource_tracker": source_code = source_code.replace( "args += ['-c', cmd % r]", "args += ['--multiprocessing-resource-tracker', str(r)]", ) return source_code class NuitkaPluginDetectorMultiprocessingWorkarounds(NuitkaPluginBase): detector_for = NuitkaPluginMultiprocessingWorkarounds @classmethod def isRelevant(cls): return not Options.shallMakeModule() def checkModuleSourceCode(self, module_name, source_code): if module_name == "__main__": if "multiprocessing" in source_code: self.warnUnusedPlugin("Multiprocessing workarounds for compiled code.") Nuitka-0.6.19.1/nuitka/plugins/standard/TensorflowPlugin.py0000600000372100037210000001051514166627112030740 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginTensorflow(NuitkaPluginBase): """This class represents the main logic of the plugin. This is a plugin to ensure tensorflow scripts compile and work well in standalone mode. This plugin copies any files required by tensorflow installations. """ plugin_name = "tensorflow" plugin_desc = "Required by the tensorflow package" def __init__(self): """Maintain switch to ensure once-only copy of tensorflow files.""" self.files_copied = False return None @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def onModuleEncounter(self, module_filename, module_name, module_kind): for candidate in ("tensor", "google"): if module_name.hasNamespace(candidate): return True, "Accept everything from %s" % candidate def onModuleSourceCode(self, module_name, source_code): """Neutralize some path magic in tensorflow. Notes: Make sure tensorflow understands, we are not running as a PIP installed application. """ if module_name != "tensorflow": return source_code source_lines = source_code.splitlines() found_insert = False for i, l in enumerate(source_lines): if l.startswith("def ") and "_running_from_pip_package():" in l: source_lines.insert(i, "_site_packages_dirs = []") source_lines.insert(i, "from tensorflow.python import keras") found_insert = True break if found_insert is True: self.info("Patched 'running-from-pip' path magic.") else: self.sysexit("Did not find path magic code.") return "\n".join(source_lines) def decideCompilation(self, module_name): """Include major packages as bytecode. Notes: Tensorflow is a very large package and mainly used to interactively create the actual application. Therefore, compilation makes no sense for it and the packages it references. """ if module_name.getTopLevelPackageName() in ( "tensor", "boto", "google", "keras", "sklearn", "pandas", "matplotlib", ): return "bytecode" class NuitkaPluginDetectorTensorflow(NuitkaPluginBase): """Only used if plugin is NOT activated. Notes: We are given the chance to issue a warning if we think we may be required. """ detector_for = NuitkaPluginTensorflow @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def onModuleDiscovered(self, module): """This method checks whether a tensorflow module is imported. Notes: For this we check whether its full name contains the string "tensorflow". Args: module: the module object Returns: None """ if module.getFullName().hasNamespace("tensorflow"): self.warnUnusedPlugin("tensorflow support.") Nuitka-0.6.19.1/nuitka/plugins/standard/ZmqPlugin.py0000600000372100037210000001034514166627112027346 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Support for pyzmq, details in below class definitions. """ import os import re import shutil from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.FileOperations import getFileList from nuitka.utils.Importing import getSharedLibrarySuffix from nuitka.utils.Utils import isWin32Windows class NuitkaPluginZmq(NuitkaPluginBase): """This class represents the main logic of the pyzmq plugin. This is a plugin to ensure that gldw platform specific backends are loading properly. This need to include the correct DLL and make sure it's used by setting an environment variable. """ plugin_name = "pyzmq" # Nuitka knows us by this name plugin_desc = "Required for pyzmq in standalone mode" def __init__(self): # Special DLL directory if detected. self.dll_directory = None @staticmethod def isAlwaysEnabled(): return True @staticmethod def getImplicitImports(module): module_name = module.getFullName() if module_name == "zmq.backend": yield "zmq.backend.cython" def considerExtraDlls(self, dist_dir, module): module_name = module.getFullName() if module_name == "zmq.libzmq" and isWin32Windows(): # TODO: Very strange thing for zmq on Windows, needs the .pyd file in wrong dir too. Have # this done in a dedicated form somewhere. shutil.copyfile( os.path.join(dist_dir, "zmq\\libzmq.pyd"), os.path.join( dist_dir, "libzmq" + getSharedLibrarySuffix(preferred=True) ), ) return NuitkaPluginBase.considerExtraDlls( self, dist_dir=dist_dir, module=module ) def _add_dll_directory(self, arg): self.dll_directory = arg def onModuleSourceCode(self, module_name, source_code): if module_name == "zmq" and Options.isStandaloneMode(): # TODO: Make the anti-bloat engine to this. if "_delvewheel_init_patch" in source_code: match = re.search( r"(def _delvewheel_init_patch_(.*?)\(\):\n.*?_delvewheel_init_patch_\2\(\))", source_code, re.S, ) delvewheel_version = match.group(2).replace("_", ".") self.info( "Detected usage of 'delvewheel' version %r." % delvewheel_version ) code = match.group(1) code = code.replace("os.add_dll_directory", "add_dll_directory") code = code.replace("sys.version_info[:2] >= (3, 8)", "True") # Fake the __file__ to the proper value. exec_globals = { "__file__": self.locateModule(module_name) + "\\__init__.py", "add_dll_directory": self._add_dll_directory, } # We believe this should be the easiest, pylint: disable=exec-used exec(code, exec_globals) def getExtraDlls(self, module): if module.getFullName() == "zmq" and self.dll_directory is not None: for dll_filename in getFileList(self.dll_directory): yield self.makeDllEntryPoint( source_path=dll_filename, dest_path=os.path.join( "pyzmq.libs", os.path.basename(dll_filename) ), package_name="zmq", ) Nuitka-0.6.19.1/nuitka/plugins/standard/PkgResourcesPlugin.py0000600000372100037210000002005214166627112031207 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to resolve pkg_resource actions at compile time rather than runtime. Nuitka can detect some things that pkg_resouces may not even be able to during runtime, e.g. right now checking pip installed versions, is not a thing, while some packages in their code, e.g. derive their __version__ value from that. """ import re from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.Utils import withNoDeprecationWarning class NuitkaPluginResources(NuitkaPluginBase): plugin_name = "pkg-resources" plugin_desc = "Resolve version numbers at compile time." def __init__(self): with withNoDeprecationWarning(): try: import pkg_resources except (ImportError, RuntimeError): self.pkg_resources = None else: self.pkg_resources = pkg_resources try: import importlib_metadata except (ImportError, SyntaxError, RuntimeError): self.metadata = None else: self.metadata = importlib_metadata # Note: This one is overriding above import, but doesn't need to initialize # the value, since it will already be set in case of a problem. try: from importlib import metadata self.metadata = metadata except ImportError: pass @staticmethod def isAlwaysEnabled(): return True def _handleEasyInstallEntryScript(self, dist, group, name): module_name = None main_name = None # First try metadata, which is what the runner also does first. if self.metadata: dist = self.metadata.distribution(dist.partition("==")[0]) for entry_point in dist.entry_points: if entry_point.group == group and entry_point.name == name: module_name = entry_point.module main_name = entry_point.attr break if module_name is None and self.pkg_resources: with withNoDeprecationWarning(): entry_point = self.pkg_resources.get_entry_info(dist, group, name) module_name = entry_point.module_name main_name = entry_point.name if module_name is None: self.sysexit( "Error, failed to resolve easy install entry script, is the installation broken?" ) return r""" import sys, re sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) import %(module_name)s sys.exit(%(module_name)s.%(main_name)s) """ % { "module_name": module_name, "main_name": main_name, } def onModuleSourceCode(self, module_name, source_code): # Many cases to deal with, pylint: disable=too-many-branches,too-many-statements if module_name == "__main__": match = re.search( "\n# EASY-INSTALL-ENTRY-SCRIPT: '(.*?)','(.*?)','(.*?)'", source_code ) if match is not None: self.info( "Detected easy install entry script, compile time detecting entry point." ) return self._handleEasyInstallEntryScript(*match.groups()) # The importlib_resources backport has a problem with wanting source files # to exist, that won't be the case with standalone. if module_name == "importlib_resources._compat": return source_code.replace("path.exists()", "True") # This one has strings with false matches, don't attempt those. if module_name == "setuptools.command.easy_install": return source_code if self.pkg_resources: for match in re.findall( r"""\b(pkg_resources\.get_distribution\(\s*['"](.*?)['"]\s*\)\.((?:parsed_)?version))""", source_code, ): try: with withNoDeprecationWarning(): value = self.pkg_resources.get_distribution(match[1]).version except self.pkg_resources.DistributionNotFound: self.warning( "Cannot find distribution '%s' for '%s', expect potential run time problem." % (match[1], module_name) ) except Exception: # catch all, pylint: disable=broad-except self.sysexit( "Error, failed to find distribution '%s', probably a plugin parsing bug for '%s' code." % (match[1], module_name) ) else: if match[2] == "version": value = repr(value) elif match[2] == "parsed_version": value = ( "pkg_resources.extern.packaging.version.Version(%r)" % value ) else: assert False source_code = source_code.replace(match[0], value) for match in re.findall( r"""\b(pkg_resources\.require\(\s*['"](.*?)['"]\s*\))""", source_code, ): # Explicitly call the require function at Nuitka compile time. try: with withNoDeprecationWarning(): self.pkg_resources.require(match[1]) except self.pkg_resources.ResolutionError: self.warning( "Cannot find requirement '%s' for '%s', expect potential run time problem." % (match[1], module_name) ) except Exception: # catch all, pylint: disable=broad-except self.sysexit( "Error, failed to resolve '%s', probably a plugin parsing bug for '%s' code." % (match[1], module_name) ) else: source_code = source_code.replace(match[0], "") if self.metadata: for total, quote1, name, quote2 in re.findall( r"""\b((?:importlib[_.])?metadata\.version\(\s*(['"]?)(.*?)(['"]?)\s*\))""", source_code, ): if name == "__name__": name = module_name.asString() quote1 = quote2 = "'" if quote1 == quote2: if quote1: try: value = self.metadata.version(name) except self.metadata.PackageNotFoundError: self.warning( "Cannot find requirement '%s' for '%s', expect potential run time problem." % (name, module_name) ) continue except Exception: # catch all, pylint: disable=broad-except self.sysexit( "Error, failed to resolve '%s', probably a plugin parsing bug for '%s' code." % (name, module_name) ) else: value = repr(value) source_code = source_code.replace(total, value) return source_code Nuitka-0.6.19.1/nuitka/plugins/standard/MatplotlibPlugin.py0000600000372100037210000001573214166627112030713 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Matplotlib standard plugin module. """ import os from nuitka.freezer.IncludedDataFiles import ( makeIncludedDataDirectory, makeIncludedGeneratedDataFile, ) from nuitka.Options import isStandaloneMode from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.plugins.Plugins import getActiveQtPlugin, hasActivePlugin from nuitka.utils.FileOperations import getFileContentByLine class NuitkaPluginMatplotlib(NuitkaPluginBase): """This class represents the main logic of the plugin. This is a plugin to ensure scripts using numpy, scipy, matplotlib, pandas, scikit-learn, etc. work well in standalone mode. While there already are relevant entries in the "ImplicitImports.py" plugin, this plugin copies any additional binary or data files required by many installations. """ plugin_name = "matplotlib" # Nuitka knows us by this name plugin_desc = "Required for matplotlib module" @staticmethod def isAlwaysEnabled(): """Request to be always enabled.""" return True @classmethod def isRelevant(cls): """Check whether plugin might be required. Returns: True if this is a standalone compilation. """ return isStandaloneMode() def _getMatplotlibInfo(self): """Determine the filename of matplotlibrc and the default backend, etc. Notes: There might exist a local version outside 'matplotlib/mpl-data' which we then must use instead. Determine its name by aksing matplotlib. """ return self.queryRuntimeInformationMultiple( info_name="matplotlib_info", setup_codes=""" from matplotlib import matplotlib_fname, get_backend, __version__ try: from matplotlib import get_data_path except ImportError: from matplotlib import _get_data_path as get_data_path from inspect import getsource """, values=( ("matplotlibrc_filename", "matplotlib_fname()"), ("backend", "get_backend()"), ("data_path", "get_data_path()"), ("matplotlib_version", "__version__"), ( "needs_matplotlibdata_env", "'MATPLOTLIBDATA' in getsource(get_data_path)", ), ), ) def considerDataFiles(self, module): if module.getFullName() != "matplotlib": return matplotlib_info = self._getMatplotlibInfo() if not os.path.isdir(matplotlib_info.data_path): self.sysexit( "mpl-data missing, matplotlib installation appears to be broken" ) # Include the "mpl-data" files. yield makeIncludedDataDirectory( source_path=matplotlib_info.data_path, dest_path=os.path.join("matplotlib", "mpl-data"), ignore_dirs=("sample_data",), ignore_filenames=("matplotlibrc",), reason="package data for 'matplotlib", ) # Handle the config file with an update. new_lines = [] # new config file lines found = False # checks whether backend definition encountered for line in getFileContentByLine(matplotlib_info.matplotlibrc_filename): line = line.rstrip() # omit meaningless lines if line.startswith("#") and matplotlib_info.matplotlib_version < "3": continue new_lines.append(line) if line.startswith(("backend ", "backend:")): # old config file has a backend definition found = True if not found and matplotlib_info.matplotlib_version < "3": # Set the backend, so even if it was run time determined, we now enforce it. new_lines.append("backend: %s" % matplotlib_info.backend) yield makeIncludedGeneratedDataFile( data=new_lines, dest_path=os.path.join("matplotlib", "mpl-data", "matplotlibrc"), reason="Updated matplotlib config file with backend to use.", ) def onModuleEncounter(self, module_filename, module_name, module_kind): if module_name.hasNamespace("mpl_toolkits"): return True, "Needed by matplotlib" # some special handling for matplotlib: # depending on whether 'tk-inter' resp. 'qt-plugins' are enabled, # their matplotlib backends are included. if hasActivePlugin("tk-inter"): if module_name in ( "matplotlib.backends.backend_tk", "matplotlib.backends.backend_tkagg", "matplotlib.backend.tkagg", ): return True, "Needed for tkinter matplotplib backend" if getActiveQtPlugin() is not None: # Note, their code tries everything behind that name, the qt5 is # misleading therefore, PySide will work there too. if module_name in ( "matplotlib.backends.backend_qt5", "matplotlib.backends.backend_qt5.py", "matplotlib.backends.backend_qt5cairo.py", "matplotlib.backend.backend_qt5.py", ): return True, "Needed for Qt matplotplib backend" if module_name == "matplotlib.backends.backend_agg": return True, "Needed as standard matplotplib backend" def createPreModuleLoadCode(self, module): """Method called when a module is being imported. Notes: If full name equals "matplotlib" we insert code to set the environment variable that e.g. Debian versions of matplotlib use. Args: module: the module object Returns: Code to insert and descriptive text (tuple), or (None, None). """ # Matplotlib might be off, or the version may not need the environment variable. if ( module.getFullName() == "matplotlib" and self._getMatplotlibInfo().needs_matplotlibdata_env ): code = r""" import os os.environ["MATPLOTLIBDATA"] = os.path.join(__nuitka_binary_dir, "matplotlib", "mpl-data") """ return ( code, "Setting 'MATPLOTLIBDATA' environment variable for matplotlib to find package data.", ) Nuitka-0.6.19.1/nuitka/plugins/standard/anti-bloat.yml0000600000372100037210000003143514166627112027626 0ustar nuitka-buildslavenuitka-buildslave00000000000000--- # yamllint disable rule:line-length psutil: description: "resolve platform specific imports at compile time" context: - "import psutil" replacements: "from ._common import AIX": "'AIX = %r' % psutil.AIX" "from ._common import BSD": "'BSD = %r' % psutil.BSD" "from ._common import FREEBSD": "'FREEBSD = %r' % + psutil.FREEBSD" "from ._common import LINUX": "'LINUX = %r' % + psutil.LINUX" "from ._common import MACOS": "'MACOS = %r' % + psutil.MACOS" "from ._common import NETBSD": "'NETBSD = %r' % + psutil.NETBSD" "from ._common import OPENBSD": "'OPENBSD = %r' % + psutil.OPENBSD" "from ._common import OSX": "'OSX = %r' % psutil.OSX" "from ._common import POSIX": "'POSIX = %r' % psutil.POSIX" "from ._common import SUNOS": "'SUNOS = %r' % psutil.SUNOS" "from ._common import WINDOWS": "'WINDOWS = %r' % psutil.WINDOWS" cffi.ffiplatform: description: "disable distutils hacks" replacements: "import setuptools": "'pass'" skimage: description: "remove pytest testing framework" replacements: "imp.find_module('pytest')": "'None'" change_function: "_test": "'(lambda: None)'" sklearn.random_projection: description: "remove numpy testing framework" replacements: "from numpy.testing import assert_equal": "r'assert_equal = (lambda actual, desired, err_msg=None, verbose=True: True)'" sklearn.utils._testing: description: "remove pytest testing framework" replacements: "import pytest": "'raise ImportError'" matplotlib: description: "remove pytest testing framework" replacements: "test.__test__ = False": "" change_function: "_init_tests": "'None'" "test": "'None'" control_tags: - "allow_ipython" matplotlib.backend_bases: description: "remove IPython reference" change_function: "_fix_ipython_backend2gui": "'(lambda cls: None)'" control_tags: - "allow_ipython" matplotlib.pyplot: description: "remove IPython reference" change_function: "install_repl_displayhook": "'(lambda: None)'" "uninstall_repl_displayhook": "'(lambda: None)'" control_tags: - "allow_ipython" PIL.ImageShow: description: "remove IPython reference" replacements: "from IPython.display import display as ipython_display": "'raise ImportError'" jinja2.defaults: description: "remove jinja2 testing framework" replacements: "from .tests import TESTS as DEFAULT_TESTS": "" numpy.ctypeslib: description: "remove numpy.distutils references" context: - "import numpy.distutils.misc_util" replacements: "from numpy.distutils.misc_util import get_shared_lib_extension": "" "get_shared_lib_extension()": "repr(numpy.distutils.misc_util.get_shared_lib_extension())" "get_shared_lib_extension(is_python_ext=True)": "repr(numpy.distutils.misc_util.get_shared_lib_extension(is_python_ext=True))" numpy.testing: description: "remove numpy testing framework" module_code: | from contextlib import contextmanager class Tester: test = None bench = None def assert_allclose(*args, **kwargs): return True @contextmanager def suppress_warnings(forwarding_rule="always"): yield @contextmanager def _assert_warns_context(warning_class, name=None): yield def assert_warns(warning_class, *args, **kwargs): if not args: return _assert_warns_context(warning_class) func = args[0] args = args[1:] with _assert_warns_context(warning_class, name=func.__name__): return func(*args, **kwargs) numpy._pytesttester: description: "remove numpy testing framework" module_code: | class PytestTester: def __init__(self, name): pass numpy.testing._private.pytesttester: description: "remove numpy testing framework" module_code: | class PytestTester: def __init__(self, name): pass numpy.core.overrides: # see #1189, apparently an upstream problem hard to grasp description: "workaround numpy issue with python flag 'no_docstrings' if used" replacements: "add_docstring(implementation, dispatcher.__doc__)": "'''add_docstring(implementation, dispatcher.__doc__ or '')'''" scipy.stats.morestats: description: "remove numpy testing framework" replacements: "from numpy.testing.decorators import setastest": "" "@setastest(False)": "" scipy.lib.numpy_compat: description: "remove numpy testing framework" replacements: "from numpy.testing import suppress_warnings": 'r''suppress_warnings = __import__("contextmanager").contextmanager(lambda : (yield))''' "NumpyVersion(np.__version__) > '1.7.0.dev'": "'0'" scipy._lib._numpy_compat: description: "remove numpy testing framework" replacements: "from numpy.testing import suppress_warnings": 'r''suppress_warnings = __import__("contextmanager").contextmanager(lambda : (yield))''' "NumpyVersion(np.__version__) > '1.7.0.dev'": "'0'" scipy._lib._testutils: description: "remove numpy testing framework" module_code: | class PytestTester: def __init__(self, name): pass # TODO: Move required stuff like this to separate file and apply it always. tensorflow.python.ops.distributions.distribution: description: "remove useless function copying" change_function: "_copy_fn": "'(lambda fn: fn)'" replacements: "class_attr_value.__doc__ = _update_docstring": "'class_attr_value___doc__ = _update_docstring'" gevent._util: description: "remove gevent release framework" change_function: "prereleaser_middle": "'(lambda data: None)'" "postreleaser_before": "'(lambda data: None)'" inspect: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" sysconfig: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" ensurepip: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" ensurepip._uninstall: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" pyclbr: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" mimetypes: description: "remove module ability to run as a binary" change_function: "_main": "'(lambda: None)'" tarfile: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" quopri: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" zipfile: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" gzip: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" "_test": "'(lambda: None)'" base64: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" "test": "'(lambda: None)'" ast: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" tokenize: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" keyword: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" tabnanny: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" trace: description: "remove module ability to run as a binary" change_function: "main": "'(lambda: None)'" uu: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" xmllib: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" mhlib: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" sgmllib: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" imghdr: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" audiodev: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" BaseHTTPServer: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" sndhdr: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" ftplib: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" mailcap: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" lib2to3.pgen2.literals: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" rexec: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" modulefinder: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" StringIO: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" fpformat: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" telnetlib: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" ctypes.util: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" formatter: description: "remove module ability to run as a binary" change_function: "test": "'(lambda: None)'" pickletools: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" random: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" dis: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" threading: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" xml.sax.xmlreader.py: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" doctest: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" difflib: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" Cookie: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" locale: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" binhex: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" copy: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" pickle: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" Bastion: description: "remove module ability to run as a binary" change_function: "_test": "'(lambda: None)'" h5py: description: "remove h5py testing framework" change_function: "run_tests": "'(lambda args=None: None)'" pandas: description: "remove pandas testing framework" replacements: "import pandas.testing": "" "from pandas.util._tester import test": "" pandas._testing: description: "remove pytest testing framework" change_function: "external_error_raised": "'(lambda: None)'" pandas._testing._io: description: "remove pytest testing framework" change_function: # TODO: Actually it would be nice to specify "uncallable" rather than wrong signature # for cases, where the function is not usable afterwards. That will make sure we have # a nice error exit in case, some test code is run an attempts to use it. "network": "'(lambda: None)'" "round_trip_pathlib": "'(lambda: None)'" "round_trip_localpath": "'(lambda: None)'" distributed.scheduler: # TODO: We should replace this with a nuitkarize in Cython maybe. description: "remove cython support" replacements: "from cython import compiled": "'raise ImportError'" "if compiled:": "'if False:'" pywt._pytesttester: description: "remove pywt testing framework" module_code: | class PytestTester: def __init__(self, name): pass feedparser.html: context: - "import inspect" - "import textwrap" - "import sgmllib" change_function: "goahead": "textwrap.dedent(inspect.getsource(sgmllib.SGMLParser.goahead))" "__parse_starttag": "textwrap.dedent(inspect.getsource(sgmllib.SGMLParser.parse_starttag))" replacements: "def goahead(self, i):": "'def goahead(self, end):'" "goahead.__code__ = sgmllib.SGMLParser.goahead.__code__": "'pass'" "__parse_starttag.__code__ = sgmllib.SGMLParser.parse_starttag.__code__": "'pass'" Nuitka-0.6.19.1/nuitka/plugins/standard/DillPlugin.py0000600000372100037210000001304614166627112027464 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to make dill module work for compiled stuff. """ from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginDillWorkarounds(NuitkaPluginBase): """This is to make dill module work with compiled methods.""" plugin_name = "dill-compat" @staticmethod def isAlwaysEnabled(): return False @staticmethod def createPostModuleLoadCode(module): full_name = module.getFullName() if full_name == "dill": code = r"""\ import dill._dill # Compiled methods need to be created. @dill.register(compiled_method) def save_compiled_method(pickler, obj): if str is not bytes: pickler.save_reduce(compiled_method, (obj.__func__, obj.__self__), obj=obj) else: pickler.save_reduce(compiled_method, (obj.im_func, obj.im_self, obj.im_class), obj=obj) def _create_compiled_function2(module_name, func_values, func_dict, func_defaults): if module_name not in compiled_function_tables: __import__(module_name) func = compiled_function_tables[module_name][1](*func_values) if func_dict: for key, value in func_dict.items(): func[key] = value func.__defaults__ = func_defaults return func def _create_compiled_function3(module_name, func_values, func_dict, func_defaults, func_kwdefaults): if module_name not in compiled_function_tables: __import__(module_name) func = compiled_function_tables[module_name][1](*func_values) if func_dict: for key, value in func_dict.items(): func[key] = value func.__defaults__ = func_defaults func.__kwdefaults__ = func_kwdefaults return func # Compiled methods might have to be created or not. @dill.register(compiled_function) def save_compiled_function(pickler, obj): if not dill._dill._locate_function(obj): stack = dill._dill.stack if getattr(pickler, '_recurse', False): from dill.detect import globalvars globs = globalvars(obj, recurse=True, builtin=True) if id(obj) in stack: globs = obj.__globals__ if str is not bytes else obj.func_globals else: globs = obj.__globals__ if str is not bytes else obj.func_globals _byref = getattr(pickler, '_byref', None) _recurse = getattr(pickler, '_recurse', None) _memo = (id(obj) in stack) and (_recurse is not None) stack[id(obj)] = len(stack), obj if str is not bytes: # Python3 _super = ('super' in getattr(obj.__code__,'co_names',())) and (_byref is not None) if _super: pickler._byref = True if _memo: pickler._recurse = False pickler.save_reduce( _create_compiled_function3, ( obj.__module__, compiled_function_tables[obj.__module__][0](obj), obj.__dict__, obj.__defaults__, obj.__kwdefaults__ ) ) else: # Python2 _super = ('super' in getattr(obj.__code__,'co_names',())) and (_byref is not None) and getattr(pickler, '_recurse', False) if _super: pickler._byref = True if _memo: pickler._recurse = False pickler.save_reduce( _create_compiled_function2, ( obj.__module__, compiled_function_tables[obj.__module__][0](obj), obj.__dict__, obj.__defaults__ ) ) if _super: pickler._byref = _byref if _memo: pickler._recurse = _recurse else: dill._dill.StockPickler.save_global(pickler, obj) """ return ( code, """\ Extending "dill" for compiled types to be pickable as well.""", ) @staticmethod def getPreprocessorSymbols(): return {"_NUITKA_PLUGIN_DILL_ENABLED": "1"} def getExtraCodeFiles(self): return {"DillPlugin.c": extra_code} extra_code = r""" #include "nuitka/prelude.h" void registerDillPluginTables(char const *module_name, PyMethodDef *reduce_compiled_function, PyMethodDef *create_compiled_function) { PyObject *function_tables = PyObject_GetAttrString((PyObject *)builtin_module, "compiled_function_tables"); if (function_tables == NULL) { DROP_ERROR_OCCURRED(); function_tables = PyDict_New(); PyObject_SetAttrString((PyObject *)builtin_module, "compiled_function_tables", function_tables); } PyObject *funcs = PyTuple_New(2); PyTuple_SET_ITEM(funcs, 0, PyCFunction_New(reduce_compiled_function, NULL)); PyTuple_SET_ITEM(funcs, 1, PyCFunction_New(create_compiled_function, NULL)); PyDict_SetItemString(function_tables, module_name, funcs); } """ Nuitka-0.6.19.1/nuitka/plugins/standard/PbrPlugin.py0000600000372100037210000000346614166627112027330 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to make pbr module work when compiled. The pbr module needs to find a version number in compiled mode. The value itself seems less important than the fact that some value does exist. """ from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginPbrWorkarounds(NuitkaPluginBase): """This is to make pbr module work when compiled with Nuitka.""" plugin_name = "pbr-compat" @classmethod def isRelevant(cls): return Options.isStandaloneMode() @staticmethod def isAlwaysEnabled(): return True @staticmethod def createPreModuleLoadCode(module): full_name = module.getFullName() if full_name == "pbr.packaging": code = """\ import os version = os.environ.get( "PBR_VERSION", os.environ.get("OSLO_PACKAGE_VERSION")) if not version: os.environ["OSLO_PACKAGE_VERSION"] = "1.0" """ return ( code, """\ Monkey patching "pbr" version number.""", ) Nuitka-0.6.19.1/nuitka/plugins/standard/PywebViewPlugin.py0000600000372100037210000001251614166627112030522 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ import os from nuitka.freezer.IncludedDataFiles import makeIncludedDataFile from nuitka.Options import isStandaloneMode from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.plugins.Plugins import getActiveQtPlugin from nuitka.utils.FileOperations import getFileList, hasFilenameExtension from nuitka.utils.Utils import getArchitecture, getOS, isMacOS, isWin32Windows class NuitkaPluginPywebview(NuitkaPluginBase): """This class represents the main logic of the plugin.""" plugin_name = "pywebview" plugin_desc = "Required by the webview package (pywebview on PyPI)" @staticmethod def isAlwaysEnabled(): return True @classmethod def isRelevant(cls): """One time only check: may this plugin be required? Returns: True if this is a standalone compilation. """ return isStandaloneMode() @staticmethod def _getWebviewFiles(module, dlls): # TODO: Clarify non-Windows needs. if not isWin32Windows(): return webview_libdir = os.path.join(module.getCompileTimeDirectory(), "lib") for filename in getFileList(webview_libdir): filename_relative = os.path.relpath(filename, webview_libdir) if getArchitecture() == "x86": if "x64" in filename_relative: continue else: if "x86" in filename_relative: continue is_dll = hasFilenameExtension(filename_relative, ".dll") if dlls and not is_dll or not dlls and is_dll: continue yield filename, filename_relative def getExtraDlls(self, module): if module.getFullName() == "webview": for filename, filename_relative in self._getWebviewFiles(module, dlls=True): yield self.makeDllEntryPoint( source_path=filename, dest_path=os.path.normpath( os.path.join( "webview/lib", filename_relative, ) ), package_name=module.getFullName(), ) # TODO: Not sure where this pointing to "site-packages" comes from. if isWin32Windows(): yield self.makeDllEntryPoint( source_path=os.path.abspath( os.path.join( module.getCompileTimeDirectory(), "..", "Python.Runtime.dll" ) ), dest_path="Python.Runtime.dll", package_name=module.getFullName(), ) def considerDataFiles(self, module): if module.getFullName() == "webview": for filename, filename_relative in self._getWebviewFiles( module, dlls=False ): yield makeIncludedDataFile( source_path=filename, dest_path=os.path.normpath( os.path.join( "webview/lib", filename_relative, ) ), reason="Package 'webview' datafile", ) def onModuleEncounter(self, module_filename, module_name, module_kind): # Make sure if module_name.isBelowNamespace("webview.platforms"): if isWin32Windows(): result = module_name in ( "webview.platforms.winforms", "webview.platforms.edgechromium", "webview.platforms.edgehtml", "webview.platforms.mshtml", "webview.platforms.cef", ) reason = "Platforms package of webview used on '%s'." % getOS() elif isMacOS(): result = module_name == "webview.platforms.cocoa" reason = "Platforms package of webview used on '%s'." % getOS() elif getActiveQtPlugin() is not None: result = module_name = "webview.platforms.qt" reason = ( "Platforms package of webview used due to '%s'." % getActiveQtPlugin() ) else: result = module_name = "webview.platforms.gtk" reason = ( "Platforms package of webview used on '%s' without Qt plugin enabled." % getOS() ) return result, reason Nuitka-0.6.19.1/nuitka/plugins/standard/TrioPlugin.py0000600000372100037210000000606414166627112027517 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Trio plugin module.""" from nuitka.plugins.PluginBase import NuitkaPluginBase _trio_patches = { "trio._core._ki": ( """\ enable_ki_protection = _ki_protection_decorator(True) # type: Callable[[F], F] enable_ki_protection.__name__ = "enable_ki_protection" disable_ki_protection = _ki_protection_decorator(False) # type: Callable[[F], F] disable_ki_protection.__name__ = "disable_ki_protection" """, """\ def enable_ki_protection(fn): return fn def disable_ki_protection(fn): return fn """, ), "trio._core._run": ( "coro.cr_frame.f_locals.setdefault(LOCALS_KEY_KI_PROTECTION_ENABLED, system_task)", "# coro.cr_frame.f_locals.setdefault(LOCALS_KEY_KI_PROTECTION_ENABLED, system_task)", ), } class NuitkaPluginTrio(NuitkaPluginBase): """Plugin for compatibility with Trio. The only incompatibility in Trio is the way it handles KeyboardInterrupt exceptions (ctrl+C): https://github.com/Nuitka/Nuitka/issues/561 https://github.com/python-trio/trio/issues/1752 It does this to ensure that Trio's internal data structures stay consistent and that the `finally` blocks in suspended coroutines are all run: https://vorpus.org/blog/control-c-handling-in-python-and-trio/ So, be warned, when this plugin is enabled, your Trio code may not behave as expected when the user hits CTRL+C. One option to cope with this is to run your Trio code in a separate thread, listen for it in the main thread (with a try/except block), then notify the Trio thread to shutdown (e.g. with `trio_token.run_sync_soon(cancel_scope.cancel())`). """ plugin_name = "trio" plugin_desc = "Required for Trio package" def __init__(self): self.shown_warning = False def onModuleSourceCode(self, module_name, source_code): if module_name not in _trio_patches: return if not self.shown_warning: self.info("Disabling careful handling of KeyboardInterrupt in Trio") self.shown_warning = True code_before, code_after = _trio_patches[module_name] if code_before not in source_code: self.sysexit( "Could not find code to patch in " + module_name + ":\n" + code_before ) return source_code.replace(code_before, code_after) Nuitka-0.6.19.1/nuitka/plugins/standard/TkinterPlugin.py0000600000372100037210000002056614166627112030225 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ import os import sys from nuitka import Options from nuitka.freezer.IncludedDataFiles import makeIncludedDataDirectory from nuitka.plugins.PluginBase import NuitkaPluginBase def _isTkInterModule(module): full_name = module.getFullName() return full_name in ("Tkinter", "tkinter", "PySimpleGUI", "PySimpleGUI27") class NuitkaPluginTkinter(NuitkaPluginBase): """This class represents the main logic of the TkInter plugin. This is a plug-in to make programs work well in standalone mode which are using tkinter. These programs require the presence of certain libraries written in the TCL language. On Windows platforms, and even on Linux, the existence of these libraries cannot be assumed. We therefore 1. Copy the TCL libraries as sub-folders to the program's dist folder 2. Redirect the program's tkinter requests to these library copies. This is done by setting appropriate variables in the os.environ dictionary. Tkinter will use these variable value to locate the library locations. Each time before the program issues an import to a tkinter module, we make sure, that the TCL environment variables are correctly set. Notes: You can enforce using a specific TCL folder by using TCL_LIBRARY and a Tk folder by using TK_LIBRARY, but that ought to normally not be necessary. """ plugin_name = "tk-inter" # Nuitka knows us by this name plugin_desc = "Required by Python's Tk modules" def __init__(self, tcl_library_dir, tk_library_dir): self.tcl_library_dir = tcl_library_dir self.tk_library_dir = tk_library_dir self.files_copied = False # ensure one-time action return None @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone, else False. """ return Options.isStandaloneMode() @staticmethod def createPreModuleLoadCode(module): """This method is called with a module that will be imported. Notes: If the word "tkinter" occurs in its full name, we know that the correct setting of the TCL environment must be ensured before this happens. Args: module: the module object Returns: Code to insert and None (tuple) """ # only insert code for tkinter related modules if _isTkInterModule(module): # The following code will be executed before importing the module. # If required we set the respective environment values. code = r""" import os os.environ["TCL_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tcl") os.environ["TK_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tk")""" return code, "Need to make sure we set environment variables for TCL." @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--tk-library-dir", action="store", dest="tk_library_dir", default=None, help="""\ The Tk library dir. Nuitka is supposed to automatically detect it, but you can override it here. Default is automatic detection.""", ) group.add_option( "--tcl-library-dir", action="store", dest="tcl_library_dir", default=None, help="""\ The Tcl library dir. See comments for Tk library dir.""", ) def considerDataFiles(self, module): """Provide TCL libraries to the dist folder. Notes: We will provide the copy the TCL/TK directories to the program's root directory, that might be shiftable with some work. Args: module: the module in question, maybe ours Yields: IncludedDataFile objects. """ if not _isTkInterModule(module): return # Check typical locations of the dirs candidates_tcl = ( os.environ.get("TCL_LIBRARY"), os.path.join(sys.prefix, "tcl", "tcl8.5"), os.path.join(sys.prefix, "tcl", "tcl8.6"), os.path.join(sys.prefix, "lib", "tcl8.5"), os.path.join(sys.prefix, "lib", "tcl8.6"), "/usr/share/tcltk/tcl8.6", "/usr/share/tcltk/tcl8.5", "/usr/share/tcl8.6", "/usr/share/tcl8.5", "/usr/lib64/tcl/tcl8.5", "/usr/lib64/tcl/tcl8.6", ) candidates_tk = ( os.environ.get("TK_LIBRARY"), os.path.join(sys.prefix, "tcl", "tk8.5"), os.path.join(sys.prefix, "tcl", "tk8.6"), os.path.join(sys.prefix, "lib", "tk8.5"), os.path.join(sys.prefix, "lib", "tk8.6"), "/usr/share/tcltk/tk8.6", "/usr/share/tcltk/tk8.5", "/usr/share/tk8.6", "/usr/share/tk8.5", "/usr/lib64/tcl/tk8.5", "/usr/lib64/tcl/tk8.6", ) tcl = self.tcl_library_dir if tcl is None: for tcl in candidates_tcl: if tcl is not None and os.path.exists(tcl): break if tcl is None or not os.path.exists(tcl): self.sysexit( "Could not find Tcl, you might need to set 'TCL_LIBRARY' and if that works, report a bug." ) tk = self.tk_library_dir if tk is None: for tk in candidates_tk: if tk is not None and os.path.exists(tk): break if tk is None or not os.path.exists(tk): self.sysexit( "Could not find Tk, you might need to set 'TK_LIBRARY' and if that works, report a bug." ) # survived the above, now do provide the locations yield makeIncludedDataDirectory( source_path=tk, dest_path="tk", reason="Tk copy needed for standalone Tcl", ignore_dirs=("demos",), ) yield makeIncludedDataDirectory( source_path=tcl, dest_path="tcl", reason="Tcl needed for tkinter usage", ) class NuitkaPluginDetectorTkinter(NuitkaPluginBase): """Used only if plugin is not activated. Notes: We are given the chance to issue a warning if we think we may be required. """ detector_for = NuitkaPluginTkinter @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation on Windows, else False. """ return Options.isStandaloneMode() def checkModuleSourceCode(self, module_name, source_code): """This method checks the source code Notes: We only use it to check whether this is the main module, and whether it contains the keyword "tkinter". We assume that the main program determines whether tkinter is used. References by dependent or imported modules are assumed irrelevant. Args: module_name: the name of the module source_code: the module's source code Returns: None """ if module_name == "__main__": for line in source_code.splitlines(): # Ignore comments. if "#" in line: line = line[: line.find("#")] if "tkinter" in line or "Tkinter" in line: self.warnUnusedPlugin("Tkinter needs TCL included.") break Nuitka-0.6.19.1/nuitka/plugins/standard/GlfwPlugin.py0000600000372100037210000001114614166627112027476 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Support for glfw, details in below class definitions. """ import os from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.FileOperations import getFileContentByLine from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.Utils import getOS, isLinux, isMacOS class NuitkaPluginGlfw(NuitkaPluginBase): """This class represents the main logic of the glfw plugin. This is a plugin to ensure that glfw platform specific backends are loading properly. This need to include the correct DLL and make sure it's used by setting an environment variable. """ # TODO: Maybe rename to opengl plugin_name = "glfw" # Nuitka knows us by this name plugin_desc = "Required for OpenGL and glfw in standalone mode" @staticmethod def isAlwaysEnabled(): return True @classmethod def isRelevant(cls): """Check whether plugin might be required. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def getImplicitImports(self, module): # Dealing with OpenGL is a bit detailed, pylint: disable=too-many-branches if module.getFullName() == "OpenGL": opengl_infos = self.queryRuntimeInformationSingle( setup_codes="import OpenGL.plugins", value="[(f.name, f.import_path) for f in OpenGL.plugins.FormatHandler.all()]", ) # TODO: Filter by name. for _name, import_path in opengl_infos: yield ModuleName(import_path).getPackageName() for line in getFileContentByLine(module.getCompileTimeFilename()): if line.startswith("PlatformPlugin("): os_part, plugin_name_part = line[15:-1].split(",") os_part = os_part.strip("' ") plugin_name_part = plugin_name_part.strip(") '") plugin_name_part = plugin_name_part[: plugin_name_part.rfind(".")] if os_part == "nt": if getOS() == "Windows": yield plugin_name_part elif os_part.startswith("linux"): if isLinux(): yield plugin_name_part elif os_part.startswith("darwin"): if isMacOS(): yield plugin_name_part elif os_part.startswith(("posix", "osmesa", "egl")): if getOS() != "Windows": yield plugin_name_part else: self.sysexit( "Undetected OS, please report bug for '%s'." % os_part ) def _getDLLFilename(self): glfw_info = self.queryRuntimeInformationMultiple( info_name="glfw_info", setup_codes="import glfw.library", values=(("dll_filename", "glfw.library.glfw._name"),), ) return glfw_info.dll_filename def getExtraDlls(self, module): if module.getFullName() == "glfw": dll_filename = self._getDLLFilename() yield self.makeDllEntryPoint( source_path=dll_filename, dest_path=os.path.join("glfw", os.path.basename(dll_filename)), package_name="glfw.library", ) def createPreModuleLoadCode(self, module): if module.getFullName() == "glfw": dll_filename = self._getDLLFilename() code = r""" import os os.environ["PYGLFW_LIBRARY"] = os.path.join(__nuitka_binary_dir, "glfw", %r) """ % os.path.basename( dll_filename ) return ( code, "Setting 'PYGLFW_LIBRARY' environment variable for glfw to find platform DLL.", ) Nuitka-0.6.19.1/nuitka/plugins/standard/EventletPlugin.py0000600000372100037210000000350014166627112030360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginEventlet(NuitkaPluginBase): """This class represents the main logic of the plugin.""" plugin_name = "eventlet" plugin_desc = "Support for including 'eventlet' dependencies and its need for 'dns' package monkey patching" @staticmethod def isAlwaysEnabled(): return True def getImplicitImports(self, module): full_name = module.getFullName() if full_name == "eventlet": yield self.locateModules("dns") yield "eventlet.hubs" elif full_name == "eventlet.hubs": yield "eventlet.hubs.epolls" yield "eventlet.hubs.hub" yield "eventlet.hubs.kqueue" yield "eventlet.hubs.poll" yield "eventlet.hubs.pyevent" yield "eventlet.hubs.selects" yield "eventlet.hubs.timer" def decideCompilation(self, module_name): if module_name.hasNamespace("dns"): return "bytecode" Nuitka-0.6.19.1/nuitka/plugins/standard/GeventPlugin.py0000600000372100037210000000344514166627112030032 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginGevent(NuitkaPluginBase): """This class represents the main logic of the plugin.""" plugin_name = "gevent" plugin_desc = "Required by the gevent package" @staticmethod def isAlwaysEnabled(): return True @classmethod def isRelevant(cls): """One time only check: may this plugin be required? Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() @staticmethod def createPostModuleLoadCode(module): """Make sure greentlet tree tracking is switched off.""" full_name = module.getFullName() if full_name == "gevent": code = r"""\ import gevent._config gevent._config.config.track_greenlet_tree = False """ return ( code, """\ Disabling 'gevent' greenlet tree tracking.""", ) Nuitka-0.6.19.1/nuitka/plugins/standard/EnumPlugin.py0000600000372100037210000000372014166627112027502 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to make enum module work when compiled. The enum module provides a free function __new__ in class dictionaries to manual metaclass calls. These become then unbound methods instead of static methods, due to CPython only checking for plain uncompiled functions. """ from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.PythonVersions import python_version class NuitkaPluginEnumWorkarounds(NuitkaPluginBase): """This is to make enum module work when compiled with Nuitka.""" plugin_name = "enum-compat" @classmethod def isRelevant(cls): return python_version < 0x300 @staticmethod def isAlwaysEnabled(): return True @staticmethod def createPostModuleLoadCode(module): full_name = module.getFullName() if full_name == "enum": code = """\ from __future__ import absolute_import import enum try: enum.Enum.__new__ = staticmethod(enum.Enum.__new__.__func__) enum.IntEnum.__new__ = staticmethod(enum.IntEnum.__new__.__func__) except AttributeError: pass """ return ( code, """\ Monkey patching "enum" for compiled '__new__' methods.""", ) Nuitka-0.6.19.1/nuitka/plugins/standard/implicit-imports.yml0000600000372100037210000000063414166627112031076 0ustar nuitka-buildslavenuitka-buildslave00000000000000--- # TODO: Seems too much lxml: depends: - ".builder" - ".etree" - ".objectify" - ".sax" - "._elementpath" lxml.etree: depends: - "._elementpath" lxml.html: depends: - ".html.clean" - ".html.diff" - ".etree" pendulum.locales: depends: - ".*.locale" phonenumbers.data: depends: - ".region_*" srsly.msgpack._packer: depends: - "srsly.msgpack.util" Nuitka-0.6.19.1/nuitka/plugins/standard/TorchPlugin.py0000600000372100037210000001230414166627112027653 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Jorj McKie, mailto: # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ import os import shutil from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase def getTorchCoreFiles(module): """Return required files from the torch folders. Notes: So far only tested for Windows. Requirements for other platforms are unknown. """ binaries = [] torch_dir = module.getCompileTimeDirectory() extras = os.path.join(torch_dir, "lib") if os.path.isdir(extras): for f in os.listdir(extras): # apart from shared libs, also the C header files are required! if f.endswith((".dll", ".so", ".h")) or ".so." in f: item = os.path.join(extras, f) if os.path.isfile(item): binaries.append((item, ".")) # this folder exists in the Linux version extras = os.path.join(torch_dir, "bin") if os.path.isdir(extras): for f in os.listdir(extras): item = os.path.join(extras, f) if os.path.isfile(item): binaries.append((item, ".")) # this folder exists in the Linux version extras = os.path.join(torch_dir, "include") if os.path.isdir(extras): for root, _, files in os.walk(extras): for f in files: item = os.path.join(root, f) if os.path.isfile(item): binaries.append((item, ".")) return binaries class NuitkaPluginTorch(NuitkaPluginBase): """This class represents the main logic of the plugin. This is a plugin to ensure torch scripts compile and work well in standalone mode. This plugin copies any files required by torch installations. """ plugin_name = "torch" plugin_desc = "Required by the torch / torchvision packages" def __init__(self): """Maintain switch to ensure once-only copy of torch/lib files.""" self.files_copied = False return None @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def considerExtraDlls(self, dist_dir, module): """Copy extra files from torch/lib. Args: dist_dir: the name of the script's dist folder module: module object Returns: empty tuple """ if self.files_copied: # not the first time here return () if module.getFullName() == "torch": self.files_copied = True # fall through next time binaries = getTorchCoreFiles(module) bin_total = len(binaries) if bin_total == 0: return () self.info("Copying files from 'torch' installation:") for f in binaries: bin_file = f[0] # full binary file name idx = bin_file.find("torch") # this will always work (idx > 0) back_end = bin_file[idx:] # tail of the string tar_file = os.path.join(dist_dir, back_end) # create any missing intermediate folders if not os.path.exists(os.path.dirname(tar_file)): os.makedirs(os.path.dirname(tar_file)) shutil.copy(bin_file, tar_file) self.info( "Copied %i %s." % (bin_total, "file" if bin_total < 2 else "files") ) return () class NuitkaPluginDetectorTorch(NuitkaPluginBase): """Only used if plugin is NOT activated. Notes: We are given the chance to issue a warning if we think we may be required. """ detector_for = NuitkaPluginTorch @classmethod def isRelevant(cls): """This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def onModuleDiscovered(self, module): """This method checks whether a torch module is imported. Notes: For this we check whether its full name contains the string "torch". Args: module: the module object Returns: None """ full_name = module.getFullName() if "torch" in full_name or "torchvision" in full_name: self.warnUnusedPlugin("torch support.") Nuitka-0.6.19.1/nuitka/plugins/standard/ImplicitImports.py0000600000372100037210000015372414166627112030561 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to tell Nuitka about implicit imports. When C extension modules import other modules, we cannot see this and need to be told that. This encodes the knowledge we have for various modules. Feel free to add to this and submit patches to make it more complete. """ import fnmatch import os import sys from nuitka.__past__ import iter_modules from nuitka.containers.oset import OrderedSet from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.PythonVersions import python_version from nuitka.utils.FileOperations import getFileContentByLine from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.SharedLibraries import getPyWin32Dir from nuitka.utils.Utils import getOS, isLinux, isMacOS, isWin32Windows from nuitka.utils.Yaml import parsePackageYaml class NuitkaPluginPopularImplicitImports(NuitkaPluginBase): plugin_name = "implicit-imports" def __init__(self): self.config = parsePackageYaml(__package__, "implicit-imports.yml") @staticmethod def isAlwaysEnabled(): return True def _resolveModulePattern(self, pattern): parts = pattern.split(".") current = None for count, part in enumerate(parts): if not part: self.sysexit( "Error, invalid pattern with empty parts used '%s'." % pattern ) if "." in part or "*" in part: if current is None: self.sysexit( "Error, cannot use patter for first part '%s'." % pattern ) module_filename = self.locateModule( module_name=ModuleName(current), ) for sub_module in iter_modules([module_filename]): if not fnmatch.fnmatch(sub_module.name, part): continue if count == len(parts) - 1: yield current.getChildNamed(sub_module.name) else: child_name = current.getChildNamed(sub_module.name).asString() for value in self._resolveModulePattern( child_name + "." + ".".join(parts[count + 1 :]) ): yield value return else: if current is None: current = ModuleName(part) else: current = current.getChildNamed(part) yield current def _getImportsByFullname(self, full_name): """Provides names of modules to imported implicitly. Notes: This methods works much like 'getImplicitImports', except that it accepts the search argument as a string. This allows callers to obtain results, which cannot provide a Nuitka module object. """ # Many variables, branches, due to the many cases, pylint: disable=too-many-branches,too-many-statements config = self.config.get(full_name) # Checking for config, but also allowing fall through. if config: dependencies = config.get("depends") if type(dependencies) is not list or not dependencies: self.sysexit( "Error, requiring list below 'depends' entry for '%s' entry." % full_name ) for dependency in dependencies: if dependency.startswith("."): dependency = full_name.getChildNamed(dependency[1:]).asString() if "*" in dependency or "?" in dependency: for resolved in self._resolveModulePattern(dependency): yield resolved else: yield dependency if full_name == "sip" and python_version < 0x300: yield "enum" elif full_name == "gtk._gtk": yield "pangocairo" yield "pango" yield "cairo" yield "gio" yield "atk" elif full_name == "atk": yield "gobject" elif full_name == "gtkunixprint": yield "gobject" yield "cairo" yield "gtk" elif full_name == "pango": yield "gobject" elif full_name == "pangocairo": yield "pango" yield "cairo" elif full_name == "reportlab.rl_config": yield "reportlab.rl_settings" elif full_name == "socket": yield "_socket" elif full_name == "ctypes": yield "_ctypes" elif full_name == "cairo._cairo": yield "gi._gobject" elif full_name in ("Tkinter", "tkinter"): yield "_tkinter" elif full_name == "cryptography": yield "_cffi_backend" elif full_name == "bcrypt._bcrypt": yield "_cffi_backend" elif full_name == "nacl._sodium": yield "_cffi_backend" elif full_name == "brotli._brotli": yield "_cffi_backend" elif full_name == "ipcqueue": yield "_cffi_backend" elif full_name == "_dbus_glib_bindings": yield "_dbus_bindings" elif full_name == "_mysql": yield "_mysql_exceptions" elif full_name == "lxml.objectify": yield "lxml.etree" elif full_name == "_yaml": yield "yaml" elif full_name == "apt_inst": yield "apt_pkg" elif full_name == "_ruamel_yaml": yield "ruamel.yaml.error" # start of engineio imports ------------------------------------------ elif full_name == "engineio": yield "engineio.async_drivers" elif full_name == "engineio.async_drivers": yield "engineio.async_drivers.aiohttp" yield "engineio.async_drivers.asgi" yield "engineio.async_drivers.eventlet" yield "engineio.async_drivers.gevent" yield "engineio.async_drivers.gevent_uwsgi" yield "engineio.async_drivers.sanic" yield "engineio.async_drivers.threading" yield "engineio.async_drivers.tornado" # start of gevent imports -------------------------------------------- elif full_name == "gevent": yield "_cffi_backend" yield "gevent._config" yield "gevent.core" yield "gevent.resolver_thread" yield "gevent.resolver_ares" yield "gevent.socket" yield "gevent.threadpool" yield "gevent.thread" yield "gevent.threading" yield "gevent.select" yield "gevent.hub" yield "gevent.greenlet" yield "gevent.local" yield "gevent.event" yield "gevent.queue" yield "gevent.resolver" yield "gevent.subprocess" if getOS() == "Windows": yield "gevent.libuv" else: yield "gevent.libev" elif full_name == "gevent.hub": yield "gevent._hub_primitives" yield "gevent._greenlet_primitives" yield "gevent._hub_local" yield "gevent._waiter" yield "gevent._util" yield "gevent._ident" yield "gevent.exceptions" elif full_name == "gevent.libev": yield "gevent.libev.corecext" yield "gevent.libev.corecffi" yield "gevent.libev.watcher" elif full_name == "gevent.libuv": yield "gevent._interfaces" yield "gevent._ffi" yield "gevent.libuv.loop" yield "gevent.libuv.watcher" elif full_name == "gevent.libuv.loop": yield "gevent.libuv._corecffi" yield "gevent._interfaces" elif full_name == "gevent._ffi": yield "gevent._ffi.loop" yield "gevent._ffi.callback" yield "gevent._ffi.watcher" elif full_name == "gevent._waiter": yield "gevent.__waiter" yield "gevent._gevent_c_waiter" elif full_name == "gevent._hub_local": yield "gevent.__hub_local" yield "gevent.__greenlet_primitives" yield "gevent._gevent_c_hub_local" elif full_name == "gevent._gevent_c_hub_local": yield "gevent._gevent_c_greenlet_primitives" elif full_name == "gevent._hub_primitives": yield "gevent.__hub_primitives" yield "gevent._gevent_cgreenlet" yield "gevent._gevent_c_hub_primitives" elif full_name == "gevent.greenlet": yield "gevent._hub_local" yield "gevent._greenlet" yield "gevent._gevent_c_ident" elif full_name == "gevent._greenlet": yield "gevent.__ident" elif full_name == "gevent.monkey": yield "gevent.builtins" yield "gevent.time" yield "gevent.local" yield "gevent.ssl" yield "gevent.events" elif full_name == "gevent.resolver": yield "gevent.resolver.blocking" yield "gevent.resolver.cares" yield "gevent.resolver.thread" elif full_name == "gevent._semaphore": yield "gevent._abstract_linkable" yield "gevent.__semaphore" yield "gevent._gevent_c_semaphore" elif full_name == "gevent._abstract_linkable": yield "gevent.__abstract_linkable" yield "gevent._gevent_c_abstract_linkable" elif full_name == "gevent.local": yield "gevent._local" yield "gevent._gevent_clocal" elif full_name == "gevent.event": yield "gevent._event" yield "gevent._gevent_cevent" elif full_name == "gevent.queue": yield "gevent._queue" yield "gevent._gevent_cqueue" elif full_name == "gevent.pool": yield "gevent._imap" elif full_name == "gevent._imap": yield "gevent.__imap" yield "gevent._gevent_c_imap" # end of gevent imports ---------------------------------------------- # start of tensorflow imports ---------------------------------------- elif full_name == "tensorflow": yield "tensorboard" yield "tensorflow_estimator" elif full_name == "tensorflow.python": yield "tensorflow.python._pywrap_tensorflow_internal" yield "tensorflow.python.ops" yield "tensorflow.python.ops.cond_v2" elif full_name == "tensorflow.lite.python.interpreter_wrapper": yield "tensorflow.lite.python.interpreter_wrapper._tensorflow_wrap_interpreter_wrapper" elif full_name == "tensorflow.lite.python.optimize": yield "tensorflow.lite.python.optimize._tensorflow_lite_wrap_calibration_wrapper" elif full_name == "tensorflow.lite.toco.python": yield "tensorflow.lite.toco.python._tensorflow_wrap_toco" # the remaining entries are relevant non-Windows platforms only elif full_name.hasNamespace("tensorflow") and getOS() != "Windows": if ( full_name == "tensorflow.include.external.protobuf_archive.python.google.protobuf.internal" ): yield "tensorflow.include.external.protobuf_archive.python.google.protobuf.internal._api_implementation" elif ( full_name == "tensorflow.include.external.protobuf_archive.python.google.protobuf.pyext" ): yield "tensorflow.include.external.protobuf_archive.python.google.protobuf.pyext._message" elif full_name == "tensorflow.python.framework": yield "tensorflow.python.framework.fast_tensor_util" elif full_name == "tensorflow.compiler.tf2tensorrt": yield "tensorflow.compiler.tf2tensorrt._wrap_py_utils" elif full_name == "tensorflow.compiler.tf2tensorrt.python.ops": yield "tensorflow.compiler.tf2tensorrt.python.ops.libtftrt" elif full_name == "tensorflow.compiler.tf2xla.ops": yield "tensorflow.compiler.tf2xla.ops._xla_ops" elif full_name == "tensorflow.contrib.tensor_forest": yield "tensorflow.contrib.tensor_forest.libforestprotos" elif full_name == "tensorflow.contrib.tensor_forest.python.ops": yield "tensorflow.contrib.tensor_forest.python.ops._model_ops" yield "tensorflow.contrib.tensor_forest.python.ops._stats_ops" yield "tensorflow.contrib.tensor_forest.python.ops._tensor_forest_ops" elif full_name == "tensorflow.contrib.tensor_forest.hybrid.python.ops": yield "tensorflow.contrib.tensor_forest.hybrid.python.ops._training.ops" elif full_name == "tensorflow.contrib.resampler.python.ops": yield "tensorflow.contrib.resampler.python.ops._resampler_ops" elif full_name == "tensorflow.contrib.nearest_neighbor.python.ops": yield "tensorflow.contrib.nearest_neighbor.python.ops._nearest_neighbor_ops" elif full_name == "tensorflow.contrib.ignite": yield "tensorflow.contrib.ignite._ignite_ops" elif full_name == "tensorflow.contrib.kinesis": yield "tensorflow.contrib.kinesis._dataset_ops" elif full_name == "tensorflow.contrib.ffmpeg": yield "tensorflow.contrib.ffmpeg.ffmpeg" elif full_name == "tensorflow.contrib.framework.python.ops": yield "tensorflow.contrib.framework.python.ops._variable_ops" elif full_name == "tensorflow.contrib.text.python.ops": yield "tensorflow.contrib.text.python.ops._skip_gram_ops" elif full_name == "tensorflow.contrib.reduce_slice_ops.python.ops": yield "tensorflow.contrib.reduce_slice_ops.python.ops._reduce_slice_ops" elif full_name == "tensorflow.contrib.periodic_resample.python.ops": yield "tensorflow.contrib.periodic_resample.python.ops._periodic_resample_op" elif full_name == "tensorflow.contrib.memory_stats.python.ops": yield "tensorflow.contrib.memory_stats.python.ops._memory_stats_ops" elif full_name == "tensorflow.contrib.libsvm.python.ops": yield "tensorflow.contrib.libsvm.python.ops._libsvm_ops" elif full_name == "tensorflow.contrib.fused_conv.python.ops": yield "tensorflow.contrib.fused_conv.python.ops._fused_conv2d_bias_activation_op" elif full_name == "tensorflow.contrib.kafka": yield "tensorflow.contrib.kafka._dataset_ops" elif full_name == "tensorflow.contrib.hadoop": yield "tensorflow.contrib.hadoop._dataset_ops" elif full_name == "tensorflow.contrib.seq2seq.python.ops": yield "tensorflow.contrib.seq2seq.python.ops._beam_search_ops" elif full_name == "tensorflow.contrib.rpc.python.kernel_tests": yield "tensorflow.contrib.rpc.python.kernel_tests.libtestexample" elif full_name == "tensorflow.contrib.boosted_trees.python.ops": yield "tensorflow.contrib.boosted_trees.python.ops._boosted_trees_ops" elif full_name == "tensorflow.contrib.layers.python.ops": yield "tensorflow.contrib.layers.python.ops._sparse_feature_cross_op" elif full_name == "tensorflow.contrib.image.python.ops": yield "tensorflow.contrib.image.python.ops._distort_image_ops" yield "tensorflow.contrib.image.python.ops._image_ops" yield "tensorflow.contrib.image.python.ops._single_image_random_dot_stereograms" elif full_name == "tensorflow.contrib.factorization.python.ops": yield "tensorflow.contrib.factorization.python.ops._factorization_ops" elif full_name == "tensorflow.contrib.input_pipeline.python.ops": yield "tensorflow.contrib.input_pipeline.python.ops._input_pipeline_ops" elif full_name == "tensorflow.contrib.rnn.python.ops": yield "tensorflow.contrib.rnn.python.ops._gru_ops" yield "tensorflow.contrib.rnn.python.ops._lstm_ops" elif full_name == "tensorflow.contrib.bigtable.python.ops": yield "tensorflow.contrib.bigtable.python.ops._bigtable" # end of tensorflow imports ------------------------------------------- # boto3 imports ------------------------------------------------------ elif full_name == "boto3": yield "boto3.ec2" yield "boto3.ec2.createtags" yield "boto3.ec2.deletetags" yield "boto3.dynamodb" yield "boto3.s3" yield "boto3.s3.inject" yield "boto3.s3.transfer" # GDAL imports ------------------------------------------------------ elif full_name == "osgeo": yield "osgeo._gdal" yield "osgeo._gdalconst" yield "osgeo._gdal_array" yield "osgeo._gnm" yield "osgeo._ogr" yield "osgeo._osr" # OpenCV imports ------------------------------------------------------ elif full_name == "cv2": yield "numpy" yield "numpy.core" # fastapi imports --------------------------------------------------- elif full_name == "fastapi": yield "fastapi.routing" # pydantic imports --------------------------------------------------- elif full_name == "pydantic": yield "pydantic.typing" yield "pydantic.fields" yield "pydantic.utils" yield "pydantic.schema" yield "pydantic.env_settings" yield "pydantic.main" yield "pydantic.error_wrappers" yield "pydantic.validators" yield "pydantic.mypy" yield "pydantic.version" yield "pydantic.types" yield "pydantic.color" yield "pydantic.parse" yield "pydantic.json" yield "pydantic.datetime_parse" yield "pydantic.dataclasses" yield "pydantic.class_validators" yield "pydantic.networks" yield "pydantic.errors" # uvicorn imports ----------------------------------------------------- elif full_name == "uvicorn": yield "uvicorn.loops" yield "uvicorn.lifespan" yield "uvicorn.protocols" elif full_name == "uvicorn.config": yield "uvicorn.logging" elif full_name == "uvicorn.lifespan": yield "uvicorn.lifespan.off" yield "uvicorn.lifespan.on" elif full_name == "uvicorn.loops": yield "uvicorn.loops.auto" yield "uvicorn.loops.uvloop" elif full_name == "uvicorn.protocols": yield "uvicorn.protocols.http" yield "uvicorn.protocols.websockets" elif full_name == "uvicorn.protocols.http": yield "uvicorn.protocols.http.auto" yield "uvicorn.protocols.http.h11_impl" yield "uvicorn.protocols.http.httptools_impl" elif full_name == "uvicorn.protocols.websockets": yield "uvicorn.protocols.websockets.auto" yield "uvicorn.protocols.websockets.websockets_impl" yield "uvicorn.protocols.websockets.wsproto_impl" # vtk imports ----------------------------------------------------- elif full_name == "vtkmodules": yield "vtkmodules.all" yield "vtkmodules.util" elif full_name == "vtkmodules.util": yield "vtkmodules.util.misc" yield "vtkmodules.util.numpy_support" yield "vtkmodules.util.vtkAlgorithm" yield "vtkmodules.util.vtkConstants" yield "vtkmodules.util.vtkImageExportToArray" yield "vtkmodules.util.vtkImageImportFromArray" yield "vtkmodules.util.vtkMethodParser" yield "vtkmodules.util.vtkVariant" elif full_name == "vtkmodules.qt": yield "vtkmodules.qt.QVTKRenderWindowInteractor" elif full_name == "vtkmodules.tk": yield "vtkmodules.tk.vtkLoadPythonTkWidgets" yield "vtkmodules.tk.vtkTkImageViewerWidget" yield "vtkmodules.tk.vtkTkPhotoImage" yield "vtkmodules.tk.vtkTkRenderWidget" yield "vtkmodules.tk.vtkTkRenderWindowInteractor" elif full_name == "vtkmodules.wx": yield "vtkmodules.wx.wxVTKRenderWindow" yield "vtkmodules.wx.wxVTKRenderWindowInteractor" # chainer imports ----------------------------------------------------- elif full_name == "chainer": yield "chainer.distributions" yield "chainer.distributions.utils" elif full_name == "chainer.distributions": yield "chainer.distributions.utils" # numpy imports ------------------------------------------------------- elif full_name == "numpy": yield "numpy._mklinit" yield "numpy.compat" yield "numpy.lib" yield "numpy.linalg" yield "numpy.fft" yield "numpy.polynomial" yield "numpy.random" yield "numpy.ctypeslib" yield "numpy.ma" yield "numpy.matrixlib" elif full_name == "numpy.core": yield "numpy.core._dtype_ctypes" yield "numpy.core._multiarray_tests" elif full_name == "numpy.random": # These are post-1.18 names. TODO: Once we detect versions of packages, be proper selective here. yield "numpy.random._bit_generator" yield "numpy.random._bounded_integers" yield "numpy.random._common" yield "numpy.random._generator" yield "numpy.random._mt19937" yield "numpy.random._pcg64" yield "numpy.random._philox" yield "numpy.random._sfc64" # These are pre-1.18 names yield "numpy.random.bit_generator" yield "numpy.random.bounded_integers" yield "numpy.random.common" yield "numpy.random.generator" yield "numpy.random.mt19937" yield "numpy.random.pcg64" yield "numpy.random.philox" yield "numpy.random.sfc64" # TODO: Clarify if entropy is needed for 1.18 or at all. yield "numpy.random.entropy" yield "numpy.random.mtrand" # matplotlib imports -------------------------------------------------- elif full_name == "matplotlib": yield "matplotlib.backend_managers" yield "matplotlib.backend_bases" yield "mpl_toolkits" elif full_name == "matplotlib.backends": yield "matplotlib.backends._backend_agg" yield "matplotlib.backends._tkagg" yield "matplotlib.backends.backend_tkagg" yield "matplotlib.backends.backend_agg" elif full_name.hasOneOfNamespaces( "matplotlib.backends.backend_wx", "matplotlib.backends.backend_wxagg" ): yield "matplotlib.backends.backend_wx" yield "matplotlib.backends.backend_wxagg" yield "wx" elif full_name == "matplotlib.backends.backend_cairo": yield "cairo" yield "cairocffi" elif full_name.hasOneOfNamespaces( "matplotlib.backends.backend_gtk3", "matplotlib.backends.backend_gtk3agg" ): yield "matplotlib.backends.backend_gtk3" yield "matplotlib.backends.backend_gtk3agg" yield "gi" elif full_name.hasOneOfNamespaces( "matplotlib.backends.backend_webagg", "matplotlib.backends.backend_webagg_core", ): yield "matplotlib.backends.backend_webagg" yield "matplotlib.backends.backend_webagg_core" yield "tornado" elif full_name.hasOneOfNamespaces( "matplotlib.backends.backend_qt5agg", "matplotlib.backends.backend_qt5" ): yield "matplotlib.backends.backend_qt5agg" yield "matplotlib.backends.backend_qt5" yield "PyQt5" # scipy imports ------------------------------------------------------- elif full_name == "scipy.stats._stats": yield "scipy.special.cython_special" elif full_name == "scipy.special": yield "scipy.special._ufuncs_cxx" elif full_name == "scipy.linalg": yield "scipy.linalg.cython_blas" yield "scipy.linalg.cython_lapack" elif full_name == "scipy.sparse.csgraph": yield "scipy.sparse.csgraph._validation" elif full_name == "scipy._lib": yield "scipy._lib.messagestream" elif full_name == "scipy.spatial": yield "scipy.spatial.transform" elif full_name == "scipy.spatial.transform": yield "scipy.spatial.transform._rotation_groups" # statsmodels imports ------------------------------------------------------- elif full_name == "statsmodels.nonparametric": yield "statsmodels.nonparametric.linbin" yield "statsmodels.nonparametric._smoothers_lowess" elif full_name == "statsmodels.tsa": yield "statsmodels.tsa._exponential_smoothers" elif full_name == "statsmodels.tsa.innovations": yield "statsmodels.tsa.innovations._arma_innovations" elif full_name == "statsmodels.tsa.kalmanf": yield "statsmodels.tsa.kalmanf.kalman_loglike" elif full_name == "statsmodels.tsa.regime_switching": yield "statsmodels.tsa.regime_switching._hamilton_filter" yield "statsmodels.tsa.regime_switching._kim_smoother" elif full_name == "statsmodels.tsa.statespace": yield "statsmodels.tsa.statespace._filters" yield "statsmodels.tsa.statespace._initialization" yield "statsmodels.tsa.statespace._kalman_filter" yield "statsmodels.tsa.statespace._kalman_smoother" yield "statsmodels.tsa.statespace._representation" yield "statsmodels.tsa.statespace._simulation_smoother" yield "statsmodels.tsa.statespace._smoothers" yield "statsmodels.tsa.statespace._tools" elif full_name == "statsmodels.tsa.statespace._filters": yield "statsmodels.tsa.statespace._filters._conventional" yield "statsmodels.tsa.statespace._filters._inversions" yield "statsmodels.tsa.statespace._filters._univariate" yield "statsmodels.tsa.statespace._filters._univariate_diffuse" elif full_name == "statsmodels.tsa.statespace._smoothers": yield "statsmodels.tsa.statespace._smoothers._alternative" yield "statsmodels.tsa.statespace._smoothers._classical" yield "statsmodels.tsa.statespace._smoothers._conventional" yield "statsmodels.tsa.statespace._smoothers._univariate" yield "statsmodels.tsa.statespace._smoothers._univariate_diffuse" # pywt imports ----------------------------------------------- elif full_name == "pywt": yield "pywt._extensions" elif full_name == "pywt._extensions": yield "pywt._extensions._cwt" yield "pywt._extensions._dwt" yield "pywt._extensions._pywt" yield "pywt._extensions._swt" # imageio imports ----------------------------------------------- elif full_name == "imageio": yield "PIL.BlpImagePlugin" yield "PIL.BmpImagePlugin" yield "PIL.BufrStubImagePlugin" yield "PIL.CurImagePlugin" yield "PIL.DcxImagePlugin" yield "PIL.DdsImagePlugin" yield "PIL.EpsImagePlugin" yield "PIL.FitsStubImagePlugin" yield "PIL.FliImagePlugin" yield "PIL.FpxImagePlugin" yield "PIL.FtexImagePlugin" yield "PIL.GbrImagePlugin" yield "PIL.GifImagePlugin" yield "PIL.GribStubImagePlugin" yield "PIL.Hdf5StubImagePlugin" yield "PIL.IcnsImagePlugin" yield "PIL.IcoImagePlugin" yield "PIL.ImImagePlugin" yield "PIL.ImtImagePlugin" yield "PIL.IptcImagePlugin" yield "PIL.Jpeg2KImagePlugin" yield "PIL.JpegImagePlugin" yield "PIL.McIdasImagePlugin" yield "PIL.MicImagePlugin" yield "PIL.MpegImagePlugin" yield "PIL.MpoImagePlugin" yield "PIL.MspImagePlugin" yield "PIL.PalmImagePlugin" yield "PIL.PcdImagePlugin" yield "PIL.PcxImagePlugin" yield "PIL.PdfImagePlugin" yield "PIL.PixarImagePlugin" yield "PIL.PngImagePlugin" yield "PIL.PpmImagePlugin" yield "PIL.PsdImagePlugin" yield "PIL.SgiImagePlugin" yield "PIL.SpiderImagePlugin" yield "PIL.SunImagePlugin" yield "PIL.TgaImagePlugin" yield "PIL.TiffImagePlugin" yield "PIL.WebPImagePlugin" yield "PIL.WmfImagePlugin" yield "PIL.XbmImagePlugin" yield "PIL.XpmImagePlugin" yield "PIL.XVThumbImagePlugin" # scikit-image imports ----------------------------------------------- elif full_name == "skimage.draw": yield "skimage.draw._draw" elif full_name == "skimage.external.tifffile": yield "skimage.external.tifffile._tifffile" elif full_name == "skimage.feature.orb_cy": yield "skimage.feature._orb_descriptor_positions" elif full_name == "skimage.feature": yield "skimage.feature.brief_cy" yield "skimage.feature.censure_cy" yield "skimage.feature.corner_cy" yield "skimage.feature.orb_cy" yield "skimage.feature._cascade" yield "skimage.feature._haar" yield "skimage.feature._hessian_det_appx" yield "skimage.feature._hoghistogram" yield "skimage.feature._texture" elif full_name == "skimage.filters.rank": yield "skimage.filters.rank.bilateral_cy" yield "skimage.filters.rank.core_cy" yield "skimage.filters.rank.core_cy_3d" yield "skimage.filters.rank.generic_cy" yield "skimage.filters.rank.percentile_cy" elif full_name == "skimage.future.graph": yield "skimage.future.graph._ncut_cy" elif full_name == "skimage.graph": yield "skimage.graph.heap" yield "skimage.graph._mcp" yield "skimage.graph._spath" elif full_name == "skimage.io": yield "skimage.io._plugins" elif full_name == "skimage.io._plugins": yield "skimage.io._plugins._colormixer" yield "skimage.io._plugins._histograms" yield "skimage.io._plugins.fits_plugin" yield "skimage.io._plugins.gdal_plugin" yield "skimage.io._plugins.gtk_plugin" yield "skimage.io._plugins.imageio_plugin" yield "skimage.io._plugins.imread_plugin" yield "skimage.io._plugins.matplotlib_plugin" yield "skimage.io._plugins.pil_plugin" yield "skimage.io._plugins.qt_plugin" yield "skimage.io._plugins.simpleitk_plugin" yield "skimage.io._plugins.skivi_plugin" yield "skimage.io._plugins.tifffile_plugin" yield "skimage.io._plugins.util" elif full_name == "skimage.measure": yield "skimage.measure._ccomp" yield "skimage.measure._find_contours_cy" yield "skimage.measure._marching_cubes_classic_cy" yield "skimage.measure._marching_cubes_lewiner_cy" yield "skimage.measure._moments_cy" yield "skimage.measure._pnpoly" elif full_name == "skimage.morphology": yield "skimage.morphology._convex_hull" yield "skimage.morphology._extrema_cy" yield "skimage.morphology._flood_fill_cy" yield "skimage.morphology._greyreconstruct" yield "skimage.morphology._max_tree" yield "skimage.morphology._skeletonize_3d_cy" yield "skimage.morphology._skeletonize_cy" yield "skimage.morphology._watershed" elif full_name == "skimage.restoration": yield "skimage.restoration._denoise_cy" yield "skimage.restoration._nl_means_denoising" yield "skimage.restoration._unwrap_1d" yield "skimage.restoration._unwrap_2d" yield "skimage.restoration._unwrap_3d" elif full_name == "skimage.segmentation": yield "skimage.segmentation._felzenszwalb_cy" yield "skimage.segmentation._quickshift_cy" yield "skimage.segmentation._slic" elif full_name == "skimage.transform": yield "skimage.transform._hough_transform" yield "skimage.transform._radon_transform" yield "skimage.transform._warps_cy" elif full_name == "skimage._shared": yield "skimage._shared.geometry" yield "skimage._shared.interpolation" yield "skimage._shared.transform" # scikit-learn imports ------------------------------------------------ elif full_name == "sklearn.cluster": yield "sklearn.cluster._dbscan_inner" yield "sklearn.cluster._hierarchical" yield "sklearn.cluster._k_means" yield "sklearn.cluster._k_means_elkan" elif full_name == "sklearn.datasets": yield "sklearn.datasets._svmlight_format" elif full_name == "sklearn.decomposition": yield "sklearn.decomposition.cdnmf_fast" yield "sklearn.decomposition._online_lda" elif full_name == "sklearn.ensemble": yield "sklearn.ensemble._gradient_boosting" elif full_name == "sklearn.externals": yield "sklearn.externals.joblib" elif full_name == "sklearn.externals.joblib": yield "sklearn.externals.joblib.numpy_pickle" elif full_name == "sklearn.ensemble._hist_gradient_boosting": yield "sklearn.ensemble._hist_gradient_boosting.histogram" yield "sklearn.ensemble._hist_gradient_boosting.splitting" yield "sklearn.ensemble._hist_gradient_boosting.types" yield "sklearn.ensemble._hist_gradient_boosting.utils" yield "sklearn.ensemble._hist_gradient_boosting._binning" yield "sklearn.ensemble._hist_gradient_boosting._gradient_boosting" yield "sklearn.ensemble._hist_gradient_boosting._loss" yield "sklearn.ensemble._hist_gradient_boosting._predictor" elif full_name == "sklearn.feature_extraction": yield "sklearn.feature_extraction._hashing" elif full_name == "sklearn.linear_model": yield "sklearn.linear_model.cd_fast" yield "sklearn.linear_model.sag_fast" yield "sklearn.linear_model.sgd_fast" elif full_name == "sklearn.manifold": yield "sklearn.manifold._barnes_hut_tsne" yield "sklearn.manifold._utils" elif full_name == "sklearn.metrics": yield "sklearn.metrics.pairwise_fast" elif full_name == "sklearn.metrics.cluster": yield "sklearn.metrics.cluster.expected_mutual_info_fast" elif full_name == "sklearn.neighbors": yield "sklearn.neighbors.ball_tree" yield "sklearn.neighbors.dist_metrics" yield "sklearn.neighbors.kd_tree" yield "sklearn.neighbors.quad_tree" yield "sklearn.neighbors.typedefs" elif full_name == "sklearn.preprocessing": yield "sklearn.preprocessing._csr_polynomial_expansion" elif full_name == "sklearn.svm": yield "sklearn.svm.liblinear" yield "sklearn.svm.libsvm" yield "sklearn.svm.libsvm_sparse" elif full_name == "sklearn.tree": yield "sklearn.tree._criterion" yield "sklearn.tree._splitter" yield "sklearn.tree._tree" yield "sklearn.tree._utils" elif full_name == "sklearn.utils": yield "sklearn.utils.arrayfuncs" yield "sklearn.utils.fast_dict" yield "sklearn.utils.graph_shortest_path" yield "sklearn.utils.lgamma" yield "sklearn.utils.murmurhash" yield "sklearn.utils.seq_dataset" yield "sklearn.utils.sparsefuncs_fast" yield "sklearn.utils.weight_vector" yield "sklearn.utils._cython_blas" yield "sklearn.utils._logistic_sigmoid" yield "sklearn.utils._random" elif full_name == "sklearn.utils.sparsetools": yield "sklearn.utils.sparsetools._graph_validation" yield "sklearn.utils.sparsetools._graph_tools" elif full_name == "sklearn.utils._hough_transform": yield "skimage.draw" # end of scikit-learn imports ----------------------------------------- elif full_name == "PIL._imagingtk": yield "PIL._tkinter_finder" elif full_name == "pkg_resources._vendor.packaging": yield "pkg_resources._vendor.packaging.version" yield "pkg_resources._vendor.packaging.specifiers" yield "pkg_resources._vendor.packaging.requirements" # TODO: Is this even true, or an artifact of how we handled requests.packages.urllib3 in the past. # urllib3 ------------------------------------------------------------- elif full_name in ("urllib3", "requests_toolbelt._compat"): yield "urllib3" yield "urllib3._collections" yield "urllib3.connection" yield "urllib3.connection.appengine" yield "urllib3.connectionpool" yield "urllib3.contrib" yield "urllib3.contrib.appengine" yield "urllib3.exceptions" yield "urllib3.fields" yield "urllib3.filepost" yield "urllib3.packages" yield "urllib3.packages.six" yield "urllib3.packages.ssl_match_hostname" yield "urllib3.poolmanager" yield "urllib3.request" yield "urllib3.response" yield "urllib3.util" yield "urllib3.util.connection" yield "urllib3.util.queue" yield "urllib3.util.request" yield "urllib3.util.response" yield "urllib3.util.retry" yield "urllib3.util.ssl_" yield "urllib3.util.timeout" yield "urllib3.util.url" yield "urllib3.util.wait" yield "urllib.error" yield "urllib.parse" yield "urllib.request" yield "urllib.response" elif full_name == "uvloop.loop": yield "uvloop._noop" elif full_name == "fitz.fitz": yield "fitz._fitz" elif full_name == "pandas._libs": yield "pandas._libs.tslibs.np_datetime" yield "pandas._libs.tslibs.nattype" yield "pandas._libs.tslibs.base" elif full_name == "pandas.core.window": yield "pandas._libs.window" yield "pandas._libs.skiplist" elif full_name == "pandas._libs.testing": yield "cmath" elif full_name == "flask.app": yield "jinja2.ext" yield "jinja2.ext.autoescape" yield "jinja2.ext.with_" # Support for both pycryotodome (module name Crypto) and pycyptodomex (module name Cryptodome) elif full_name.hasOneOfNamespaces("Crypto", "Cryptodome"): crypto_module_name = full_name.getTopLevelPackageName() if full_name == crypto_module_name + ".Cipher._mode_ofb": yield crypto_module_name + ".Cipher._raw_ofb" elif full_name == crypto_module_name + ".Cipher.CAST": yield crypto_module_name + ".Cipher._raw_cast" elif full_name == crypto_module_name + ".Cipher.DES3": yield crypto_module_name + ".Cipher._raw_des3" elif full_name == crypto_module_name + ".Cipher.DES": yield crypto_module_name + ".Cipher._raw_des" elif full_name == crypto_module_name + ".Cipher._mode_ecb": yield crypto_module_name + ".Cipher._raw_ecb" elif full_name == crypto_module_name + ".Cipher.AES": yield crypto_module_name + ".Cipher._raw_aes" yield crypto_module_name + ".Cipher._raw_aesni" elif full_name == crypto_module_name + ".Cipher._mode_cfb": yield crypto_module_name + ".Cipher._raw_cfb" elif full_name == crypto_module_name + ".Cipher.ARC2": yield crypto_module_name + ".Cipher._raw_arc2" elif full_name == crypto_module_name + ".Cipher.DES3": yield crypto_module_name + ".Cipher._raw_des3" elif full_name == crypto_module_name + ".Cipher._mode_ocb": yield crypto_module_name + ".Cipher._raw_ocb" elif full_name == crypto_module_name + ".Cipher._EKSBlowfish": yield crypto_module_name + ".Cipher._raw_eksblowfish" elif full_name == crypto_module_name + ".Cipher.Blowfish": yield crypto_module_name + ".Cipher._raw_blowfish" elif full_name == crypto_module_name + ".Cipher._mode_ctr": yield crypto_module_name + ".Cipher._raw_ctr" elif full_name == crypto_module_name + ".Cipher._mode_cbc": yield crypto_module_name + ".Cipher._raw_cbc" elif full_name == crypto_module_name + ".Util.strxor": yield crypto_module_name + ".Util._strxor" elif full_name == crypto_module_name + ".Util._cpu_features": yield crypto_module_name + ".Util._cpuid_c" elif full_name == crypto_module_name + ".Hash.BLAKE2s": yield crypto_module_name + ".Hash._BLAKE2s" elif full_name == crypto_module_name + ".Hash.BLAKE2b": yield crypto_module_name + ".Hash._BLAKE2b" elif full_name == crypto_module_name + ".Hash.SHA1": yield crypto_module_name + ".Hash._SHA1" elif full_name == crypto_module_name + ".Hash.SHA224": yield crypto_module_name + ".Hash._SHA224" elif full_name == crypto_module_name + ".Hash.SHA256": yield crypto_module_name + ".Hash._SHA256" elif full_name == crypto_module_name + ".Hash.SHA384": yield crypto_module_name + ".Hash._SHA384" elif full_name == crypto_module_name + ".Hash.SHA512": yield crypto_module_name + ".Hash._SHA512" elif full_name == crypto_module_name + ".Hash.MD2": yield crypto_module_name + ".Hash._MD2" elif full_name == crypto_module_name + ".Hash.MD4": yield crypto_module_name + ".Hash._MD4" elif full_name == crypto_module_name + ".Hash.MD5": yield crypto_module_name + ".Hash._MD5" elif full_name == crypto_module_name + ".Hash.keccak": yield crypto_module_name + ".Hash._keccak" elif full_name == crypto_module_name + ".Hash.RIPEMD160": yield crypto_module_name + ".Hash._RIPEMD160" elif full_name == crypto_module_name + ".Hash.Poly1305": yield crypto_module_name + ".Hash._poly1305" elif full_name == crypto_module_name + ".Protocol.KDF": yield crypto_module_name + ".Cipher._Salsa20" yield crypto_module_name + ".Protocol._scrypt" elif full_name == crypto_module_name + ".Cipher._mode_gcm": yield crypto_module_name + ".Hash._ghash_clmul" yield crypto_module_name + ".Hash._ghash_portable" elif full_name == crypto_module_name + ".Cipher.Salsa20": yield crypto_module_name + ".Cipher._Salsa20" elif full_name == crypto_module_name + ".Cipher.ChaCha20": yield crypto_module_name + ".Cipher._chacha20" elif full_name == crypto_module_name + ".PublicKey.ECC": yield crypto_module_name + ".PublicKey._ec_ws" elif full_name == crypto_module_name + ".Cipher.ARC4": yield crypto_module_name + ".Cipher._ARC4" elif full_name == crypto_module_name + ".Math._IntegerCustom": yield crypto_module_name + ".Math._modexp" elif full_name == "pycparser.c_parser": yield "pycparser.yacctab" yield "pycparser.lextab" elif full_name == "passlib.hash": yield "passlib.handlers.sha2_crypt" elif full_name == "pyglet": yield "pyglet.app" yield "pyglet.canvas" yield "pyglet.clock" yield "pyglet.com" yield "pyglet.event" yield "pyglet.font" yield "pyglet.gl" yield "pyglet.graphics" yield "pyglet.input" yield "pyglet.image" yield "pyglet.lib" yield "pyglet.media" yield "pyglet.model" yield "pyglet.resource" yield "pyglet.sprite" yield "pyglet.shapes" yield "pyglet.text" yield "pyglet.window" elif full_name in ("pynput.keyboard", "pynput.mouse"): if isMacOS(): yield full_name.getChildNamed("_darwin") elif isWin32Windows(): yield full_name.getChildNamed("_win32") else: yield full_name.getChildNamed("xorg") elif full_name == "_pytest._code.code": yield "py._path.local" elif full_name == "pyreadstat._readstat_parser": yield "pandas" elif full_name == "pyreadstat.pyreadstat": yield "pyreadstat._readstat_writer" yield "pyreadstat.worker" elif full_name == "cytoolz.itertoolz": yield "cytoolz.utils" elif full_name == "cytoolz.functoolz": yield "cytoolz._signatures" elif full_name == "exchangelib": yield "tzdata" elif full_name == "curses": yield "_curses" elif full_name == "h5py.h5": yield "h5py.defs" elif full_name == "h5py.h5s": yield "h5py.utils" elif full_name == "h5py.h5p": yield "h5py.h5ac" elif full_name == "h5py.h5a": yield "h5py._proxy" elif full_name == "kivy._clock": yield "kivy.weakmethod" elif full_name == "kivy.graphics.instructions": yield "kivy.graphics.buffer" yield "kivy.graphics.vertex" yield "kivy.graphics.vbo" elif full_name == "kivy.graphics.vbo": yield "kivy.graphics.compiler" elif full_name == "kivy.graphics.compiler": yield "kivy.graphics.shader" elif full_name == "mercurial.encoding": yield "mercurial.charencode" yield "mercurial.cext.parsers" def getImportsByFullname(self, full_name): """Recursively create a set of imports for a fullname. Notes: If an imported item has imported kids, call again with each new item, resulting in a leaf-only set (no more consequential kids). """ result = OrderedSet() def checkImportsRecursive(module_name): for item in self._getImportsByFullname(module_name): item = ModuleName(item) if item not in result: result.add(item) checkImportsRecursive(item) checkImportsRecursive(full_name) if full_name in result: result.remove(full_name) return result def getImplicitImports(self, module): full_name = module.getFullName() if module.isPythonShlibModule(): for used_module in module.getUsedModules(): yield used_module[0] if full_name == "pkg_resources.extern": for line in getFileContentByLine(module.getCompileTimeFilename()): if line.startswith("names"): line = line.split("=")[-1].strip() parts = line.split(",") for part in parts: yield "pkg_resources._vendor." + part.strip("' ") else: # create a flattened import set for full_name and yield from it for item in self.getImportsByFullname(full_name): yield item def onModuleSourceCode(self, module_name, source_code): if module_name == "numexpr.cpuinfo": # We cannot intercept "is" tests, but need it to be "isinstance", # so we patch it on the file. TODO: This is only temporary, in # the future, we may use optimization that understands the right # hand size of the "is" argument well enough to allow for our # type too. return source_code.replace( "type(attr) is types.MethodType", "isinstance(attr, types.MethodType)" ) # Do nothing by default. return source_code def getExtraDlls(self, module): full_name = module.getFullName() if full_name == "uuid" and isLinux(): uuid_dll_path = self.locateDLL("uuid") if uuid_dll_path is not None: yield self.makeDllEntryPoint( uuid_dll_path, os.path.basename(uuid_dll_path), None ) elif full_name == "iptc" and isLinux(): import iptc.util # pylint: disable=I0021,import-error xtwrapper_dll = iptc.util.find_library("xtwrapper")[0] xtwrapper_dll_path = xtwrapper_dll._name # pylint: disable=protected-access yield self.makeDllEntryPoint( xtwrapper_dll_path, os.path.basename(xtwrapper_dll_path), None ) elif full_name == "coincurve._libsecp256k1" and isWin32Windows(): yield self.makeDllEntryPoint( os.path.join(module.getCompileTimeDirectory(), "libsecp256k1.dll"), os.path.join(full_name.getPackageName(), "libsecp256k1.dll"), full_name.getPackageName(), ) # TODO: This should be its own plugin. elif ( full_name in ( "pythoncom", "win32api", "win32clipboard", "win32console", "win32cred", "win32crypt", "win32event", "win32evtlog", "win32file", "win32gui", "win32help", "win32inet", "win32job", "win32lz", "win32net", "win32pdh", "win32pipe", "win32print", "win32process", "win32profile", "win32ras", "win32security", "win32service", "win32trace", "win32transaction", "win32ts", "win32wnet", ) and isWin32Windows() ): pywin_dir = getPyWin32Dir() if pywin_dir is not None: for dll_name in "pythoncom", "pywintypes": pythoncom_filename = "%s%d%d.dll" % ( dll_name, sys.version_info[0], sys.version_info[1], ) pythoncom_dll_path = os.path.join(pywin_dir, pythoncom_filename) if os.path.exists(pythoncom_dll_path): yield self.makeDllEntryPoint( pythoncom_dll_path, pythoncom_filename, None ) unworthy_namespaces = ( "setuptools", # Not performance relevant. "distutils", # Not performance relevant. "wheel", # Not performance relevant. "pkg_resources", # Not performance relevant. "pycparser", # Not performance relevant. # "cffi", # Not performance relevant. "numpy.distutils", # Largely unused, and a lot of modules. "numpy.f2py", # Mostly unused, only numpy.distutils import it. "numpy.testing", # Useless. "nose", # Not performance relevant. "coverage", # Not performance relevant. "docutils", # Not performance relevant. "pytest", # Not performance relevant. "_pytest", # Not performance relevant. "unittest", # Not performance relevant. "pexpect", # Not performance relevant. "Cython", # Mostly unused, and a lot of modules. "cython", "pyximport", "IPython", # Mostly unused, and a lot of modules. "wx._core", # Too large generated code "pyVmomi.ServerObjects", # Too large generated code "pyglet.gl", # Too large generated code "telethon.tl.types", # Not performance relevant and slow C compile "importlib_metadata", # Not performance relevant and slow C compile "comtypes.gen", # Not performance relevant and slow C compile "phonenumbers.geodata", # Not performance relevant and slow C compile "site", # Not performance relevant and problems with .pth files ) def decideCompilation(self, module_name): if module_name.hasOneOfNamespaces(self.unworthy_namespaces): return "bytecode" Nuitka-0.6.19.1/nuitka/plugins/standard/KivyPlugin.py0000600000372100037210000001144214166627112027520 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ from nuitka.Options import isStandaloneMode from nuitka.plugins.PluginBase import NuitkaPluginBase class NuitkaPluginKivy(NuitkaPluginBase): """This class represents the main logic of the plugin.""" plugin_name = "kivy" plugin_desc = "Required by kivy package" @staticmethod def isAlwaysEnabled(): return True @classmethod def isRelevant(cls): """One time only check: may this plugin be required? Returns: True if this is a standalone compilation. """ return isStandaloneMode() def _getKivyInformation(self): setup_codes = r""" import kivy.core.image import kivy.core.text # Prevent Window from being created at compile time. kivy.core.core_select_lib=(lambda *args, **kwargs: None) import kivy.core.window # Kivy has packages designed to provide these on Windows try: from kivy_deps.sdl2 import dep_bins as sdl2_dep_bins except ImportError: sdl2_dep_bins = [] try: from kivy_deps.glew import dep_bins as glew_dep_bins except ImportError: glew_dep_bins = [] """ info = self.queryRuntimeInformationMultiple( info_name="kivy_info", setup_codes=setup_codes, values=( ("libs_loaded", "kivy.core.image.libs_loaded"), ("window_impl", "kivy.core.window.window_impl"), ("label_libs", "kivy.core.text.label_libs"), ("sdl2_dep_bins", "sdl2_dep_bins"), ("glew_dep_bins", "glew_dep_bins"), ), ) if info is None: self.sysexit("Error, it seems Kivy is not installed.") return info def getImplicitImports(self, module): # Using branches to dispatch, pylint: disable=too-many-branches full_name = module.getFullName() if full_name == "kivy.core.image": for module_name in self._getKivyInformation().libs_loaded: yield full_name.getChildNamed(module_name) elif full_name == "kivy.core.window": # TODO: It seems only one is actually picked, so this could be made # to also reflect decision making. for _, module_name, _ in self._getKivyInformation().window_impl: yield full_name.getChildNamed(module_name) elif full_name == "kivy.core.text": for _, module_name, _ in self._getKivyInformation().label_libs: yield full_name.getChildNamed(module_name) elif full_name == "kivy.core.window.window_sdl2": yield "kivy.core.window._window_sdl2" elif full_name == "kivy.core.window._window_sdl2": yield "kivy.core.window.window_info" elif full_name == "kivy.core.window.window_x11": yield "kivy.core.window.window_info" elif full_name == "kivy.graphics.cgl": yield "kivy.graphics.cgl_backend" elif full_name == "kivy.graphics.cgl_backend": yield "kivy.graphics.cgl_backend.cgl_glew" elif full_name == "kivy.graphics.cgl_backend.cgl_glew": yield "kivy.graphics.cgl_backend.cgl_gl" elif full_name == "kivymd.app": yield self.locateModules("kivymd.uix") def getExtraDlls(self, module): """Copy extra shared libraries or data for this installation. Args: module: module object Yields: DLL entry point objects """ full_name = module.getFullName() if full_name == "kivy": kivy_info = self._getKivyInformation() kivy_dlls = [] for dll_folder in kivy_info.sdl2_dep_bins + kivy_info.glew_dep_bins: kivy_dlls.extend(self.locateDLLsInDirectory(dll_folder)) for full_path, target_filename, _dll_extension in kivy_dlls: yield self.makeDllEntryPoint( source_path=full_path, dest_path=target_filename, package_name=full_name, ) self.reportFileCount(full_name, len(kivy_dlls)) Nuitka-0.6.19.1/nuitka/plugins/standard/PySidePyQtPlugin.py0000600000372100037210000011730714166627112030620 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Standard plug-in to make PyQt and PySide work well in standalone mode. To run properly, these need the Qt plugins copied along, which have their own dependencies. """ import os from nuitka.containers.oset import OrderedSet from nuitka.freezer.IncludedDataFiles import ( makeIncludedDataFile, makeIncludedGeneratedDataFile, ) from nuitka.freezer.IncludedEntryPoints import makeExeEntryPoint from nuitka.Options import isStandaloneMode from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.plugins.Plugins import getActiveQtPlugin from nuitka.PythonVersions import python_version from nuitka.utils.FileOperations import getFileList, listDir from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.Utils import isMacOS, isWin32Windows # Use to detect the Qt plugin that is active and check for conflicts. _qt_binding_names = ("PySide", "PySide2", "PySide6", "PyQt4", "PyQt5", "PyQt6") # Detect usage of "wx" and warn/exclude that as well. Add more here as # necessary. _other_gui_binding_names = ("wx",) def getQtPluginNames(): return tuple(qt_binding_name.lower() for qt_binding_name in _qt_binding_names) class NuitkaPluginQtBindingsPluginBase(NuitkaPluginBase): # For overload in the derived bindings plugin. binding_name = None def __init__(self, qt_plugins, no_qt_translations): self.qt_plugins = OrderedSet(x.strip().lower() for x in qt_plugins.split(",")) self.no_qt_translations = no_qt_translations self.webengine_done_binaries = False self.webengine_done_data = False self.qt_plugins_dirs = None self.binding_package_name = ModuleName(self.binding_name) # Allow to specify none. if self.qt_plugins == set(["none"]): self.qt_plugins = set() # Prevent the list of binding names from being incomplete, it's used for conflicts. assert self.binding_name in _qt_binding_names, self.binding_name # Also lets have consistency in naming. assert self.plugin_name in getQtPluginNames() active_qt_plugin_name = getActiveQtPlugin() if active_qt_plugin_name is not None: self.sysexit( "Error, confliciting plugin '%s', you can only have one enabled." % active_qt_plugin_name ) self.warned_about = set() @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--include-qt-plugins", action="store", dest="qt_plugins", default="sensible", help="""\ Which Qt plugins to include. These can be big with dependencies, so by default only the sensible ones are included, but you can also put "all" or list them individually. If you specify something that does not exist, a list of all available will be given.""", ) group.add_option( "--noinclude-qt-translations", action="store", dest="no_qt_translations", default=False, help="""\ Include Qt translations with QtWebEngine if used. These can be a lot of files that you may not want to be included.""", ) def _getQmlTargetDir(self): """Where does the Qt bindings package expect the QML files.""" return os.path.join(self.binding_name, "qml") def _getResourcesTargetDir(self): """Where does the Qt bindings package expect the resources files.""" if isMacOS(): return "Content/Resources" elif isWin32Windows(): if self.binding_name in ("PySide2", "PyQt5"): return "resources" else: # While PyQt6/PySide6 complains about these, they are not working # return os.path.join(self.binding_name, "resources") return "." else: if self.binding_name in ("PySide2", "PySide6", "PyQt6"): return "." elif self.binding_name == "PyQt5": return "resources" else: assert False def _getTranslationsTargetDir(self): """Where does the Qt bindings package expect the translation files.""" if isMacOS(): return "Content/Resources" elif isWin32Windows(): if self.binding_name in ("PySide2", "PyQt5"): return "translations" elif self.binding_name == "PyQt6": # TODO: PyQt6 is complaining about not being in "translations", but ignores it there. return "." else: return os.path.join(self.binding_name, "translations") else: if self.binding_name in ("PySide2", "PySide6", "PyQt6"): return "." elif self.binding_name == "PyQt5": return "translations" else: assert False @staticmethod def _getWebEngineTargetDir(): """Where does the Qt bindings package expect the web process executable.""" return "Helpers" if isMacOS() else "." def getQtPluginsSelected(self): # Resolve "sensible on first use" if "sensible" in self.qt_plugins: # Most used ones with low dependencies. self.qt_plugins.update( tuple( family for family in ( "imageformats", "iconengines", "mediaservice", "printsupport", "platforms", "platformthemes", "styles", # Wayland on Linux needs these "wayland-shell-integration", "wayland-decoration-client", "wayland-graphics-integration-client", "egldeviceintegrations", # OpenGL rendering, maybe should be something separate. "xcbglintegrations", ) if self.hasPluginFamily(family) ) ) self.qt_plugins.remove("sensible") # Make sure the above didn't detect nothing, which would be # indicating the check to be bad. assert self.qt_plugins return self.qt_plugins def hasQtPluginSelected(self, plugin_name): selected = self.getQtPluginsSelected() return "all" in selected or plugin_name in selected def _getQtInformation(self): # This is generic, and therefore needs to apply this to a lot of strings. def applyBindingName(template): return template % {"binding_name": self.binding_name} def getLocationQueryCode(path_name): if self.binding_name == "PyQt6": template = """\ %(binding_name)s.QtCore.QLibraryInfo.path(%(binding_name)s.QtCore.QLibraryInfo.LibraryPath.%(path_name)s)""" else: template = """\ %(binding_name)s.QtCore.QLibraryInfo.location(%(binding_name)s.QtCore.QLibraryInfo.%(path_name)s)""" return template % { "binding_name": self.binding_name, "path_name": path_name, } setup_codes = applyBindingName( r""" import os import %(binding_name)s.QtCore """ ) info = self.queryRuntimeInformationMultiple( info_name=applyBindingName("%(binding_name)s_info"), setup_codes=setup_codes, values=( ( "library_paths", applyBindingName( "%(binding_name)s.QtCore.QCoreApplication.libraryPaths()" ), ), ( "guess_path1", applyBindingName( "os.path.join(os.path.dirname(%(binding_name)s.__file__), 'plugins')" ), ), ( "guess_path2", applyBindingName( "os.path.join(os.path.dirname(%(binding_name)s.__file__), '..', '..', '..', 'Library', 'plugins')" ), ), ( "version", applyBindingName( "%(binding_name)s.__version_info__" if "PySide" in self.binding_name else "%(binding_name)s.QtCore.PYQT_VERSION_STR" ), ), ( "nuitka_patch_level", applyBindingName( "getattr(%(binding_name)s, '_nuitka_patch_level', 0)" ), ), ("translations_path", getLocationQueryCode("TranslationsPath")), ( "library_executables_path", getLocationQueryCode("LibraryExecutablesPath"), ), ("data_path", getLocationQueryCode("DataPath")), ), ) if info is None: self.sysexit("Error, it seems '%s' is not installed." % self.binding_name) return info def _getBindingVersion(self): """Get the version of the binding in tuple digit form, e.g. (6,0,3)""" return self._getQtInformation().version def _getNuitkaPatchLevel(self): """Does it include the Nuitka patch, i.e. is a self-built one with it applied.""" return self._getQtInformation().nuitka_patch_level def _getTranslationsPath(self): """Get the path to the Qt translations.""" return self._getQtInformation().translations_path def _getResourcesPath(self): """Get the path to the Qt webengine resources.""" return os.path.join(self._getQtInformation().data_path, "resources") def _getLibaryExecutablePath(self): """Get the patch to Qt binaries.""" return self._getQtInformation().library_executables_path def getQtPluginDirs(self): if self.qt_plugins_dirs is not None: return self.qt_plugins_dirs qt_info = self._getQtInformation() self.qt_plugins_dirs = qt_info.library_paths if not self.qt_plugins_dirs and os.path.exists(qt_info.guess_path1): self.qt_plugins_dirs.append(qt_info.guess_path1) if not self.qt_plugins_dirs and os.path.exists(qt_info.guess_path2): self.qt_plugins_dirs.append(qt_info.guess_path2) # Avoid duplicates. self.qt_plugins_dirs = [ os.path.normpath(dirname) for dirname in self.qt_plugins_dirs ] self.qt_plugins_dirs = tuple(sorted(set(self.qt_plugins_dirs))) if not self.qt_plugins_dirs: self.warning("Couldn't detect Qt plugin directories.") return self.qt_plugins_dirs def _getQtBinDirs(self): for plugin_dir in self.getQtPluginDirs(): if "PyQt" in self.binding_name: qt_bin_dir = os.path.normpath(os.path.join(plugin_dir, "..", "bin")) if os.path.isdir(qt_bin_dir): yield qt_bin_dir else: qt_bin_dir = os.path.normpath(os.path.join(plugin_dir, "..")) yield qt_bin_dir def hasPluginFamily(self, family): for plugin_dir in self.getQtPluginDirs(): if os.path.isdir(os.path.join(plugin_dir, family)): return True # TODO: Special case "xml". return False def _getQmlDirectory(self): for plugin_dir in self.getQtPluginDirs(): qml_plugin_dir = os.path.normpath(os.path.join(plugin_dir, "..", "qml")) if os.path.exists(qml_plugin_dir): return qml_plugin_dir self.sysexit("Error, no such Qt plugin family: qml") def _getQmlFileList(self, dlls): qml_plugin_dir = self._getQmlDirectory() # List all file types of the QML plugin folder that are datafiles and not DLLs. datafile_suffixes = ( ".qml", ".qmlc", ".qmltypes", ".js", ".jsc", ".png", ".ttf", ".metainfo", ".mesh", ".frag", "qmldir", ) if dlls: ignore_suffixes = datafile_suffixes only_suffixes = () else: ignore_suffixes = () only_suffixes = datafile_suffixes return getFileList( qml_plugin_dir, ignore_suffixes=ignore_suffixes, only_suffixes=only_suffixes, ) def _findQtPluginDLLs(self): for qt_plugins_dir in self.getQtPluginDirs(): for filename in getFileList(qt_plugins_dir): filename_relative = os.path.relpath(filename, start=qt_plugins_dir) qt_plugin_name = filename_relative.split(os.path.sep, 1)[0] if not self.hasQtPluginSelected(qt_plugin_name): continue yield self.makeDllEntryPoint( source_path=filename, dest_path=os.path.join( self.binding_name, "qt-plugins", filename_relative, ), package_name=self.binding_package_name, ) def _getChildNamed(self, *child_names): for child_name in child_names: return ModuleName(self.binding_name).getChildNamed(child_name) def getImplicitImports(self, module): # Way too many indeed, pylint: disable=too-many-branches full_name = module.getFullName() top_level_package_name, child_name = full_name.splitPackageName() if top_level_package_name != self.binding_name: return # These are alternatives depending on PyQt5 version if child_name == "QtCore" and "PyQt" in self.binding_name: if python_version < 0x300: yield "atexit" yield "sip" yield self._getChildNamed("sip") if child_name in ( "QtGui", "QtAssistant", "QtDBus", "QtDeclarative", "QtSql", "QtDesigner", "QtHelp", "QtNetwork", "QtScript", "QtQml", "QtGui", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtOpenGL", "QtXml", "QtXmlPatterns", "QtPrintSupport", "QtNfc", "QtWebKitWidgets", "QtBluetooth", "QtMultimediaWidgets", "QtQuick", "QtWebChannel", "QtWebSockets", "QtX11Extras", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core", ): yield self._getChildNamed("QtCore") if child_name in ( "QtDeclarative", "QtWebKit", "QtXmlPatterns", "QtQml", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtQuick", "QtQuickWidgets", "QtWebSockets", "QtWebEngineWidgets", ): yield self._getChildNamed("QtNetwork") if child_name == "QtWebEngineWidgets": yield self._getChildNamed("QtWebEngineCore") yield self._getChildNamed("QtWebChannel") yield self._getChildNamed("QtPrintSupport") elif child_name == "QtScriptTools": yield self._getChildNamed("QtScript") elif child_name in ( "QtWidgets", "QtDeclarative", "QtDesigner", "QtHelp", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtOpenGL", "QtQuick", "QtQuickWidgets", "QtSql", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core", ): yield self._getChildNamed("QtGui") if child_name in ( "QtDesigner", "QtHelp", "QtTest", "QtPrintSupport", "QtSvg", "QtOpenGL", "QtWebKitWidgets", "QtMultimediaWidgets", "QtQuickWidgets", "QtSql", ): yield self._getChildNamed("QtWidgets") if child_name in ("QtPrintSupport",): yield self._getChildNamed("QtSvg") if child_name in ("QtWebKitWidgets",): yield self._getChildNamed("QtWebKit") yield self._getChildNamed("QtPrintSupport") if child_name in ("QtMultimediaWidgets",): yield self._getChildNamed("QtMultimedia") if child_name in ("QtQuick", "QtQuickWidgets"): yield self._getChildNamed("QtQml") if child_name in ("QtQuickWidgets", "QtQml", "QtQuickControls2"): yield self._getChildNamed("QtQuick") if child_name == "Qt": yield self._getChildNamed("QtCore") yield self._getChildNamed("QtDBus") yield self._getChildNamed("QtGui") yield self._getChildNamed("QtNetwork") yield self._getChildNamed("QtNetworkAuth") yield self._getChildNamed("QtSensors") yield self._getChildNamed("QtSerialPort") yield self._getChildNamed("QtMultimedia") yield self._getChildNamed("QtQml") yield self._getChildNamed("QtWidgets") # TODO: Questionable if this still exists in newer PySide. if child_name == "QtUiTools": yield self._getChildNamed("QtGui") yield self._getChildNamed("QtXml") # TODO: Questionable if this still exists in newer PySide. if full_name == "phonon": yield self._getChildNamed("QtGui") def createPostModuleLoadCode(self, module): """Create code to load after a module was successfully imported. For Qt we need to set the library path to the distribution folder we are running from. The code is immediately run after the code and therefore makes sure it's updated properly. """ # Only in standalone mode, this will be needed. if not isStandaloneMode(): return full_name = module.getFullName() if full_name == "%s.QtCore" % self.binding_name: code = """\ from __future__ import absolute_import from %(package_name)s import QCoreApplication import os QCoreApplication.setLibraryPaths( [ os.path.join( os.path.dirname(__file__), "qt-plugins" ) ] ) os.environ["QML2_IMPORT_PATH"] = os.path.join( os.path.dirname(__file__), "qml" ) """ % { "package_name": full_name } yield ( code, """\ Setting Qt library path to distribution folder. We need to avoid loading target system Qt plugins, which may be from another Qt version.""", ) def isQtWebEngineModule(self, full_name): return full_name in ( self.binding_name + ".QtWebEngine", self.binding_name + ".QtWebEngineCore", self.binding_name + ".QtWebEngineWidgets", ) def createPreModuleLoadCode(self, module): """Method called when a module is being imported. Notes: If full name equals to the binding we insert code to include the dist folder in the 'PATH' environment variable (on Windows only). Args: module: the module object Returns: Code to insert and descriptive text (tuple), or (None, None). """ # This isonly relevant on standalone mode for Windows if not isStandaloneMode(): return full_name = module.getFullName() if full_name == self.binding_name and isWin32Windows(): code = """import os path = os.environ.get("PATH", "") if not path.startswith(__nuitka_binary_dir): os.environ["PATH"] = __nuitka_binary_dir + ";" + path """ yield ( code, "Adding binary folder to runtime 'PATH' environment variable for proper loading.", ) def considerDataFiles(self, module): full_name = module.getFullName() if full_name == self.binding_name and ( "qml" in self.getQtPluginsSelected() or "all" in self.getQtPluginsSelected() ): qml_plugin_dir = self._getQmlDirectory() qml_target_dir = self._getQmlTargetDir() self.info("Including Qt plugins 'qml' below '%s'." % qml_target_dir) for filename in self._getQmlFileList(dlls=False): filename_relative = os.path.relpath(filename, qml_plugin_dir) yield makeIncludedDataFile( source_path=filename, dest_path=os.path.join( qml_target_dir, filename_relative, ), reason="Qt QML datafile", ) elif self.isQtWebEngineModule(full_name) and not self.webengine_done_data: self.webengine_done_data = True # TODO: This is probably wrong/not needed on macOS if not isMacOS(): yield makeIncludedGeneratedDataFile( data="""\ [Paths] Prefix = . """, dest_path="qt6.conf" if "6" in self.binding_name else "qt.conf", reason="QtWebEngine needs Qt configuration file", ) resources_dir = self._getResourcesPath() for filename, filename_relative in listDir(resources_dir): yield makeIncludedDataFile( source_path=filename, dest_path=os.path.join( self._getResourcesTargetDir(), filename_relative ), reason="Qt resources", ) if not self.no_qt_translations: translations_path = self._getTranslationsPath() for filename in getFileList(translations_path): filename_relative = os.path.relpath(filename, translations_path) dest_path = self._getTranslationsTargetDir() yield makeIncludedDataFile( source_path=filename, dest_path=os.path.join(dest_path, filename_relative), reason="Qt translation", ) def getExtraDlls(self, module): # pylint: disable=too-many-branches full_name = module.getFullName() if full_name == self.binding_name: if not self.getQtPluginDirs(): self.sysexit( "Error, failed to detect '%s' plugin directories." % self.binding_name ) target_plugin_dir = os.path.join(full_name.asPath(), "qt-plugins") self.info( "Including Qt plugins '%s' below '%s'." % ( ",".join( sorted(x for x in self.getQtPluginsSelected() if x != "xml") ), target_plugin_dir, ) ) # TODO: Yielding a generator should become OK too. for r in self._findQtPluginDLLs(): yield r if isWin32Windows(): # Those 2 vars will be used later, just saving some resources # by caching the files list qt_bin_files = sum( (getFileList(qt_bin_dir) for qt_bin_dir in self._getQtBinDirs()), [], ) count = 0 for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in ("libeay32.dll", "ssleay32.dll"): yield self.makeDllEntryPoint( source_path=filename, dest_path=basename, package_name=full_name, ) count += 1 self.reportFileCount(full_name, count, section="OpenSSL") if ( "qml" in self.getQtPluginsSelected() or "all" in self.getQtPluginsSelected() ): qml_plugin_dir = self._getQmlDirectory() qml_target_dir = self._getQmlTargetDir() for filename in self._getQmlFileList(dlls=True): filename_relative = os.path.relpath(filename, qml_plugin_dir) yield self.makeDllEntryPoint( source_path=filename, dest_path=os.path.join( qml_target_dir, filename_relative, ), package_name=full_name # reason="Qt QML plugin DLL", ) # Also copy required OpenGL DLLs on Windows if isWin32Windows(): opengl_dlls = ("libegl.dll", "libglesv2.dll", "opengl32sw.dll") count = 0 for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in opengl_dlls or basename.startswith( "d3dcompiler_" ): yield self.makeDllEntryPoint( source_path=filename, dest_path=basename, package_name=full_name, ) self.reportFileCount(full_name, count, section="OpenGL") elif full_name == self.binding_name + ".QtNetwork": if not isWin32Windows(): dll_path = self.locateDLL("crypto") if dll_path is not None: yield self.makeDllEntryPoint( source_path=dll_path, dest_path=os.path.basename(dll_path), package_name=full_name, ) dll_path = self.locateDLL("ssl") if dll_path is not None: yield self.makeDllEntryPoint( source_path=dll_path, dest_path=os.path.basename(dll_path), package_name=full_name, ) elif self.isQtWebEngineModule(full_name) and not self.webengine_done_binaries: self.webengine_done_binaries = True # prevent multiple copies self.info("Including QtWebEngine executable.") qt_web_engine_dir = self._getLibaryExecutablePath() for filename, filename_relative in listDir(qt_web_engine_dir): if filename_relative.startswith("QtWebEngineProcess"): yield makeExeEntryPoint( source_path=filename, dest_path=os.path.join( self._getWebEngineTargetDir(), filename_relative ), package_name=full_name, ) break else: self.sysexit( "Error, cannot locate QtWebEngineProcess executable at '%s'." % qt_web_engine_dir ) def removeDllDependencies(self, dll_filename, dll_filenames): for value in self.getQtPluginDirs(): # TODO: That is not a proper check if a file is below that. if dll_filename.startswith(value): for sub_dll_filename in dll_filenames: for badword in ( "libKF5", "libkfontinst", "libkorganizer", "libplasma", "libakregator", "libdolphin", "libnoteshared", "libknotes", "libsystemsettings", "libkerfuffle", "libkaddressbook", "libkworkspace", "libkmail", "libmilou", "libtaskmanager", "libkonsole", "libgwenview", "libweather_ion", ): if os.path.basename(sub_dll_filename).startswith(badword): yield sub_dll_filename def onModuleEncounter(self, module_filename, module_name, module_kind): top_package_name = module_name.getTopLevelPackageName() if isStandaloneMode(): if ( top_package_name in _qt_binding_names and top_package_name != self.binding_name ): if top_package_name not in self.warned_about: self.info( """\ Unwanted import of '%(unwanted)s' that conflicts with '%(binding_name)s' encountered, preventing its use. As a result an "ImportError" might be given at run time. Uninstall it for full compatible behaviour with the uncompiled code to debug it.""" % { "unwanted": top_package_name, "binding_name": self.binding_name, } ) self.warned_about.add(top_package_name) return ( False, "Not included due to potentially conflicting Qt versions with selected Qt binding '%s'." % self.binding_name, ) def onModuleCompleteSet(self, module_set): for module in module_set: module_name = module.getFullName() if module_name in _qt_binding_names and module_name != self.binding_name: self.warning( """\ Unwanted import of '%(unwanted)s' that conflicts with '%(binding_name)s' encountered. Use \ '--nofollow-import-to=%(unwanted)s' or uninstall it.""" % {"unwanted": module_name, "binding_name": self.binding_name} ) if module_name in _other_gui_binding_names: self.warning( """\ Unwanted import of '%(unwanted)s' that conflicts with '%(binding_name)s' encountered. Use \ '--nofollow-import-to=%(unwanted)s' or uninstall it.""" % {"unwanted": module_name, "binding_name": self.binding_name} ) def onModuleSourceCode(self, module_name, source_code): """Third party packages that make binding selections.""" if module_name.hasNamespace("pyqtgraph"): # TODO: Add a mechanism to force all variable references of a name to something # during tree building, that would cover all uses in a nicer way. source_code = source_code.replace( "{QT_LIB.lower()}", self.binding_name.lower() ) source_code = source_code.replace( "QT_LIB.lower()", repr(self.binding_name.lower()) ) return source_code class NuitkaPluginPyQt5QtPluginsPlugin(NuitkaPluginQtBindingsPluginBase): """This is for plugins of PyQt5. When loads an image, it may use a plug-in, which in turn used DLLs, which for standalone mode, can cause issues of not having it. """ plugin_name = "pyqt5" plugin_desc = "Required by the PyQt5 package." binding_name = "PyQt5" def __init__(self, qt_plugins, no_qt_translations): NuitkaPluginQtBindingsPluginBase.__init__( self, qt_plugins=qt_plugins, no_qt_translations=no_qt_translations ) @classmethod def isRelevant(cls): return isStandaloneMode() class NuitkaPluginDetectorPyQt5QtPluginsPlugin(NuitkaPluginBase): detector_for = NuitkaPluginPyQt5QtPluginsPlugin @classmethod def isRelevant(cls): return isStandaloneMode() def onModuleDiscovered(self, module): full_name = module.getFullName() if full_name == NuitkaPluginPyQt5QtPluginsPlugin.binding_name + ".QtCore": self.warnUnusedPlugin("Inclusion of Qt plugins.") elif full_name == "PyQt4.QtCore": self.warning( "Support for PyQt4 has been dropped. Please contact Nuitka commercial if you need it." ) class NuitkaPluginPySide2Plugins(NuitkaPluginQtBindingsPluginBase): """This is for plugins of PySide2. When Qt loads an image, it may use a plug-in, which in turn used DLLs, which for standalone mode, can cause issues of not having it. """ plugin_name = "pyside2" plugin_desc = "Required by the PySide2 package." binding_name = "PySide2" def __init__(self, qt_plugins, no_qt_translations): if self._getNuitkaPatchLevel() < 1: self.warning( """\ This PySide2 version only partially supported through workarounds, full support: https://nuitka.net/pages/pyside2.html""" ) if python_version < 0x360: self.sysexit( "Error, unpatched PySide2 is not supported before CPython <3.6." ) NuitkaPluginQtBindingsPluginBase.__init__( self, qt_plugins=qt_plugins, no_qt_translations=no_qt_translations ) def onModuleEncounter(self, module_filename, module_name, module_kind): # Enforce recursion in to multiprocessing for accelerated mode, which # would normally avoid this. if module_name == self.binding_name and self._getNuitkaPatchLevel() < 1: return True, "Need to monkey patch PySide2 for abstract methods." return NuitkaPluginQtBindingsPluginBase.onModuleEncounter( self, module_filename=module_filename, module_name=module_name, module_kind=module_kind, ) def createPostModuleLoadCode(self, module): """Create code to load after a module was successfully imported. For Qt we need to set the library path to the distribution folder we are running from. The code is immediately run after the code and therefore makes sure it's updated properly. """ for result in NuitkaPluginQtBindingsPluginBase.createPostModuleLoadCode( self, module ): yield result if ( self._getNuitkaPatchLevel() < 1 and module.getFullName() == self.binding_name ): code = r"""\ # Make them unique and count them. wrapper_count = 0 import functools import inspect def nuitka_wrap(cls): global wrapper_count for attr in cls.__dict__: if attr.startswith("__") and attr.endswith("__"): continue value = getattr(cls, attr) if type(value).__name__ == "compiled_function": # Only work on overloaded attributes. for base in cls.__bases__: base_value = getattr(base, attr, None) if base_value: module = inspect.getmodule(base_value) # PySide C stuff does this, and we only need to cover that. if module is None: break else: continue wrapper_count += 1 wrapper_name = "_wrapped_function_%s_%d" % (attr, wrapper_count) signature = inspect.signature(value) # Remove annotations junk that cannot be executed. signature = signature.replace( return_annotation = inspect.Signature.empty, parameters=[ parameter.replace(default=inspect.Signature.empty,annotation=inspect.Signature.empty) for parameter in signature.parameters.values() ] ) v = r''' def %(wrapper_name)s%(signature)s: return %(wrapper_name)s.func(%(parameters)s) ''' % { "signature": signature, "parameters": ",".join(signature.parameters), "wrapper_name": wrapper_name } # TODO: Nuitka does not currently statically optimize this, might change! exec( v, globals(), ) wrapper = globals()[wrapper_name] wrapper.func = value wrapper.__defaults__ = value.__defaults__ setattr(cls, attr, wrapper) return cls @classmethod def my_init_subclass(cls, *args): return nuitka_wrap(cls) import PySide2.QtCore PySide2.QtCore.QAbstractItemModel.__init_subclass__ = my_init_subclass PySide2.QtCore.QObject.__init_subclass__ = my_init_subclass """ yield ( code, """\ Monkey patching classes derived from PySide2 base classes to pass PySide2 checks.""", ) class NuitkaPluginDetectorPySide2Plugins(NuitkaPluginBase): detector_for = NuitkaPluginPySide2Plugins def onModuleDiscovered(self, module): if module.getFullName() == NuitkaPluginPySide2Plugins.binding_name + ".QtCore": self.warnUnusedPlugin("Making callbacks work and include Qt plugins.") class NuitkaPluginPySide6Plugins(NuitkaPluginQtBindingsPluginBase): """This is for plugins of PySide6. When Qt loads an image, it may use a plug-in, which in turn used DLLs, which for standalone mode, can cause issues of not having it. """ plugin_name = "pyside6" plugin_desc = "Required by the PySide6 package for standalone mode." binding_name = "PySide6" def __init__(self, qt_plugins, no_qt_translations): NuitkaPluginQtBindingsPluginBase.__init__( self, qt_plugins=qt_plugins, no_qt_translations=no_qt_translations ) if self._getBindingVersion() < (6, 1, 2): self.warning( """\ Only PySide 6.1.2 or higher (or dev branch compiled), otherwise callbacks won't work.""" ) class NuitkaPluginDetectorPySide6Plugins(NuitkaPluginBase): detector_for = NuitkaPluginPySide6Plugins def onModuleDiscovered(self, module): if module.getFullName() == NuitkaPluginPySide6Plugins.binding_name + ".QtCore": self.warnUnusedPlugin("Standalone mode support and Qt plugins.") class NuitkaPluginPyQt6Plugins(NuitkaPluginQtBindingsPluginBase): """This is for plugins of PyQt6. When Qt loads an image, it may use a plug-in, which in turn used DLLs, which for standalone mode, can cause issues of not having it. """ plugin_name = "pyqt6" plugin_desc = "Required by the PyQt6 package for standalone mode." binding_name = "PyQt6" def __init__(self, qt_plugins, no_qt_translations): NuitkaPluginQtBindingsPluginBase.__init__( self, qt_plugins=qt_plugins, no_qt_translations=no_qt_translations ) self.warning( """\ Support for PyQt6 is experimental, use PySide6 if you can.""" ) Nuitka-0.6.19.1/nuitka/plugins/standard/__init__.py0000600000372100037210000000150114166627112027151 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/plugins/standard/PmwPlugin.py0000600000372100037210000001551514166627112027346 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Plugin to pre-process PMW for inclusion. """ import os import re from nuitka import Options from nuitka.__past__ import StringIO from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.utils.FileOperations import getFileContents, listDir # The main logic of this is from StackOverflow answer: # http://stackoverflow.com/questions/6772916/python-pmw-and-cx-freeze # The order of these files is significant. Files which reference # other files must appear later. Files may be deleted if they are not # used. files = [ "Dialog", "TimeFuncs", "Balloon", "ButtonBox", "EntryField", "Group", "LabeledWidget", "MainMenuBar", "MenuBar", "MessageBar", "MessageDialog", "NoteBook", "OptionMenu", "PanedWidget", "PromptDialog", "RadioSelect", "ScrolledCanvas", "ScrolledField", "ScrolledFrame", "ScrolledListBox", "ScrolledText", "HistoryText", "SelectionDialog", "TextDialog", "TimeCounter", "AboutDialog", "ComboBox", "ComboBoxDialog", "Counter", "CounterDialog", ] # Work out which version is being bundled. class NuitkaPluginPmw(NuitkaPluginBase): plugin_name = "pmw-freezer" plugin_desc = "Required by the Pmw package" def __init__(self, need_blt, need_color): self.need_blt = need_blt self.need_color = need_color @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--include-pmw-blt", action="store_true", dest="need_blt", default=False, help="""\ Should 'Pmw.Blt' not be included, Default is to include it.""", ) group.add_option( "--include-pmw-color", action="store_true", dest="need_color", default=False, help="""\ Should 'Pmw.Color' not be included, Default is to include it.""", ) def onModuleSourceCode(self, module_name, source_code): if module_name == "Pmw": pmw_path = self.locateModule(module_name=module_name) return self._packagePmw(pmw_path) return source_code def _packagePmw(self, pmw_path): self.info("Packaging Pmw into single module fpor freezing.") # Algorithm is from the "__init__.py" of Pwm: def _hasLoader(dirname): # Only accept Pmw_V_R_P with single digits, since ordering will # not work correctly with multiple digits (for example, Pmw_10_0 # will be before Pmw_9_9). if re.search("^Pmw_[0-9]_[0-9](_[0-9])?$", dirname) is not None: for suffix in (".py", ".pyc", ".pyo"): path = os.path.join(pmw_path, dirname, "lib", "PmwLoader" + suffix) if os.path.isfile(path): return 1 return 0 # This mimics the scan the __init__.py does. candidates = [] for _fullpath, candidate in listDir(pmw_path): if _hasLoader(candidate): candidates.append(candidate) candidates.sort() candidates.reverse() if not candidates: self.sysexit("Error, cannot find any Pmw versions.") self.info( "Found the following Pmw version candidates %s." % ",".join(candidates) ) candidate = os.path.join(pmw_path, candidates[0], "lib") version = candidates[0][4:].replace("_", ".") self.info("Picked version %s." % version) return self._packagePmw2(candidate, version) def _packagePmw2(self, srcdir, version): def mungeFile(filename): # Read the filename and modify it so that it can be bundled with the # other Pmw files. filename = "Pmw" + filename + ".py" text = getFileContents(os.path.join(srcdir, filename)) text = re.sub(r"import Pmw\>", "", text) text = re.sub("INITOPT = Pmw.INITOPT", "", text) text = re.sub(r"\ # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Details see below in class definition. """ import os import re from nuitka import Options from nuitka.plugins.PluginBase import NuitkaPluginBase from nuitka.PythonVersions import getSystemPrefixPath from nuitka.utils.FileOperations import listDir from nuitka.utils.Utils import isMacOS, isWin32Windows sklearn_mods = [ "sklearn.utils.sparsetools._graph_validation", "sklearn.utils.sparsetools._graph_tools", "sklearn.utils.lgamma", "sklearn.utils.weight_vector", "sklearn.utils._unittest_backport", "sklearn.externals.joblib.externals.cloudpickle.dumps", "sklearn.externals.joblib.externals.loky.backend.managers", ] if isWin32Windows(): sklearn_mods.extend( [ "sklearn.externals.joblib.externals.loky.backend.synchronize", "sklearn.externals.joblib.externals.loky.backend._win_wait", "sklearn.externals.joblib.externals.loky.backend._win_reduction", "sklearn.externals.joblib.externals.loky.backend.popen_loky_win32", ] ) else: sklearn_mods.extend( [ "sklearn.externals.joblib.externals.loky.backend.synchronize", "sklearn.externals.joblib.externals.loky.backend.compat_posix", "sklearn.externals.joblib.externals.loky.backend._posix_reduction", "sklearn.externals.joblib.externals.loky.backend.popen_loky_posix", ] ) class NuitkaPluginNumpy(NuitkaPluginBase): """This class represents the main logic of the plugin. This is a plugin to ensure scripts using numpy, scipy, pandas, scikit-learn, etc. work well in standalone mode. While there already are relevant entries in the "ImplicitImports.py" plugin, this plugin copies any additional binary or data files required by many installations. """ plugin_name = "numpy" # Nuitka knows us by this name plugin_desc = "Required for numpy, scipy, pandas, etc." def __init__(self, include_matplotlib, include_scipy): self.include_numpy = True # For consistency self.include_scipy = include_scipy # Information about matplotlib install. self.matplotlib_info = None if include_matplotlib: self.warning( "The option '--noinclude-matplotlib' is deprecated, matplotlib as its own plugin now." ) @classmethod def isRelevant(cls): """Check whether plugin might be required. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() @classmethod def addPluginCommandLineOptions(cls, group): group.add_option( "--noinclude-scipy", action="store_false", dest="include_scipy", default=True, help="""\ Should scipy, sklearn or skimage when used be not included with numpy, Default is %default.""", ) # TODO: This is deprecated, remove it eventually. from optparse import SUPPRESS_HELP group.add_option( "--noinclude-matplotlib", action="store_true", dest="include_matplotlib", default=False, help=SUPPRESS_HELP, ) def getExtraDlls(self, module): """Copy extra shared libraries or data for this installation. Args: module: module object Yields: DLL entry point objects """ full_name = module.getFullName() if self.include_numpy and full_name == "numpy": numpy_binaries = tuple( self._getNumpyCoreBinaries(numpy_dir=module.getCompileTimeDirectory()) ) for full_path, target_filename in numpy_binaries: yield self.makeDllEntryPoint( source_path=full_path, dest_path=target_filename, package_name=full_name, ) self.reportFileCount(full_name, len(numpy_binaries)) if full_name == "scipy" and self.include_scipy and isWin32Windows(): scipy_binaries = tuple( self._getScipyCoreBinaries(scipy_dir=module.getCompileTimeDirectory()) ) for source_path, target_filename in scipy_binaries: yield self.makeDllEntryPoint( source_path=source_path, dest_path=target_filename, package_name=full_name, ) self.reportFileCount(full_name, len(scipy_binaries)) @staticmethod def _getNumpyCoreBinaries(numpy_dir): """Return any binaries in numpy package. Notes: This covers the special cases like MKL binaries. Returns: tuple of abspaths of binaries. """ numpy_core_dir = os.path.join(numpy_dir, "core") # first look in numpy/.libs for binaries libdir = os.path.join(numpy_dir, ".libs" if not isMacOS() else ".dylibs") if os.path.isdir(libdir): for full_path, filename in listDir(libdir): yield full_path, filename # Then look for libraries in numpy.core package path # should already return the MKL files in ordinary cases re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) for full_path, filename in listDir(numpy_core_dir): if not re_anylib.match(filename): continue yield full_path, filename # Also look for MKL libraries in folder "above" numpy. # This should meet the layout of Anaconda installs. base_prefix = getSystemPrefixPath() if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") else: lib_dir = os.path.join(base_prefix, "lib") if os.path.isdir(lib_dir): re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) for full_path, filename in listDir(lib_dir): if isWin32Windows(): if not ( filename.startswith(("libi", "libm", "mkl")) and filename.endswith(".dll") ): continue else: if not re_mkllib.match(filename): continue yield full_path, filename @staticmethod def _getScipyCoreBinaries(scipy_dir): """Return binaries from the extra-dlls folder (Windows only).""" for dll_dir_name in ("extra_dll", ".libs"): dll_dir_path = os.path.join(scipy_dir, dll_dir_name) if os.path.isdir(dll_dir_path): for source_path, source_filename in listDir(dll_dir_path): if source_filename.lower().endswith(".dll"): yield source_path, os.path.join( "scipy", dll_dir_name, source_filename ) def onModuleEncounter(self, module_filename, module_name, module_kind): if not self.include_scipy and module_name.hasOneOfNamespaces( "scipy", "sklearn", "skimage" ): return False, "Omit unneeded components" if module_name in ("cv2", "cv2.cv2", "cv2.data"): return True, "Needed for OpenCV" if self.include_scipy and module_name in sklearn_mods: return True, "Needed by sklearn" class NuitkaPluginDetectorNumpy(NuitkaPluginBase): """Only used if plugin is NOT activated. Notes: We are given the chance to issue a warning if we think we may be required. """ detector_for = NuitkaPluginNumpy @classmethod def isRelevant(cls): """Check whether plugin might be required. Returns: True if this is a standalone compilation. """ return Options.isStandaloneMode() def onModuleDiscovered(self, module): """This method checks whether numpy is required. Notes: For this we check whether its first name part is numpy relevant. Args: module: the module object Returns: None """ module_name = module.getFullName() if module_name.hasOneOfNamespaces( "numpy", "scipy", "skimage", "pandas", "sklearn" ): self.warnUnusedPlugin( "Numpy support for at least '%s'." % module_name.getTopLevelPackageName() ) # TODO: Move to its own file Nuitka-0.6.19.1/nuitka/plugins/PluginBase.py0000600000372100037210000005657414166627112025667 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Plugins: Welcome to Nuitka! This is your shortest way to become part of it. This is to provide the base class for all plugins. Some of which are part of proper Nuitka, and some of which are waiting to be created and submitted for inclusion by you. The base class will serve as documentation. And it will point to examples of it being used. """ import inspect import os import shutil import sys from collections import namedtuple from nuitka.__past__ import getMetaClassBase from nuitka.freezer.IncludedEntryPoints import makeDllEntryPoint from nuitka.Options import isStandaloneMode from nuitka.Tracing import plugins_logger from nuitka.utils.Execution import NuitkaCalledProcessError, check_output from nuitka.utils.FileOperations import makePath from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.SharedLibraries import locateDLL, locateDLLsInDirectory pre_modules = {} post_modules = {} warned_unused_plugins = set() class NuitkaPluginBase(getMetaClassBase("Plugin")): """Nuitka base class for all plugins. Derive your plugin from "NuitkaPluginBase" please. For instructions, see https://github.com/Nuitka/Nuitka/blob/orsiris/UserPlugin-Creation.rst Plugins allow to adapt Nuitka's behaviour in a number of ways as explained below at the individual methods. It is used to deal with special requirements some packages may have (e.g. PyQt and tkinter), data files to be included (e.g. certifi), inserting hidden code, coping with otherwise undetectable needs, or issuing messages in certain situations. A plugin in general must be enabled to be used by Nuitka. This happens by specifying "--enable-plugin" (standard plugins) or by "--user-plugin" (user plugins) in the Nuitka command line. However, some plugins are always enabled and invisible to the user. Nuitka comes with a number of "standard" plugins to be enabled as needed. What they are can be displayed using "nuitka --plugin-list file.py" (filename required but ignored). User plugins may be specified (and implicitly enabled) using their Python script pathname. """ # Standard plugins must provide this as a unique string which Nuitka # then uses to identify them. # # User plugins are identified by their path and implicitly activated. # They however still need to specify some arbitrary non-blank string here, # which does not equal the name of an inactivated standard plugin. # For working with options, user plugins must set this variable to # the script's path (use __file__, __module__ or __name__). plugin_name = None @staticmethod def isAlwaysEnabled(): """Request to be always enabled. Notes: Setting this to true is only applicable to standard plugins. In this case, the plugin will be enabled upon Nuitka start-up. Any plugin detector class will then be ignored. Method isRelevant() may also be present and can be used to fine-control enabling the plugin: A to-be-enabled, but irrelevant plugin will still not be activated. Returns: True or False """ return False @classmethod def isRelevant(cls): """Consider if the plugin is relevant. Notes: A plugin may only be a needed on a certain OS, or with some options, but this is only a class method, so you will not have much run time information. Returns: True or False """ return True @classmethod def addPluginCommandLineOptions(cls, group): # Call group.add_option() here. pass @classmethod def getTagDataFileTagOptions(cls): # Return tag_name, description tuples return () @classmethod def getPluginDefaultOptionValues(cls): """This method is used to get a values to use as defaults. Since the defaults are in the command line options, we call that and extract them. """ from optparse import OptionGroup, OptionParser parser = OptionParser() group = OptionGroup(parser, "Pseudo Target") cls.addPluginCommandLineOptions(group) result = {} for option in group.option_list: result[option.dest] = option.default return result def isRequiredImplicitImport(self, module, full_name): """Indicate whether an implicitly imported module should be accepted. Notes: You may negate importing a module specified as "implicit import", although this is an unexpected event. Args: module: the module object full_name: of the implicitly import module Returns: True or False """ # Virtual method, pylint: disable=no-self-use,unused-argument return True def getImplicitImports(self, module): """Return the implicit imports for a given module (iterator). Args: module: the module object Yields: implicit imports for the module """ # Virtual method, pylint: disable=no-self-use,unused-argument return () def onModuleSourceCode(self, module_name, source_code): """Inspect or modify source code. Args: module_name: (str) name of module source_code: (str) its source code Returns: source_code (str) Notes: Default implementation forwards to `checkModuleSourceCode` which is going to allow simply checking the source code without the need to pass it back. """ self.checkModuleSourceCode(module_name, source_code) return source_code def checkModuleSourceCode(self, module_name, source_code): """Inspect source code. Args: module_name: (str) name of module source_code: (str) its source code Returns: None """ def onFrozenModuleSourceCode(self, module_name, is_package, source_code): """Inspect or modify frozen module source code. Args: module_name: (str) full name of module is_package: (bool) True indicates a package source_code: (str) its source code Returns: source_code (str) """ # Virtual method, pylint: disable=no-self-use,unused-argument return source_code def onFrozenModuleBytecode(self, module_name, is_package, bytecode): """Inspect or modify frozen module byte code. Args: module_name: (str) name of module is_package: (bool) True indicates a package bytecode: (bytes) byte code Returns: bytecode (bytes) """ # Virtual method, pylint: disable=no-self-use,unused-argument return bytecode @staticmethod def createPreModuleLoadCode(module): """Create code to execute before importing a module. Notes: Called by @onModuleDiscovered. Args: module: the module object Returns: None (does not apply, default) tuple (code, documentary string) tuple (code, documentary string, flags) """ # Virtual method, pylint: disable=unused-argument return None @staticmethod def createPostModuleLoadCode(module): """Create code to execute after loading to a module. Notes: Called by @onModuleDiscovered. Args: module: the module object Returns: None (does not apply, default) tuple (code, documentary string) tuple (code, documentary string, flags) """ # Virtual method, pylint: disable=unused-argument return None def onModuleDiscovered(self, module): """Called with a module to be loaded. Notes: We may specify code to be prepended and/or appended to this module. This code is stored in the appropriate dict. For every imported module and each of these two options, only one plugin may do this. We check this condition here. Args: module: the module object Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def onModuleEncounter(self, module_filename, module_name, module_kind): """Help decide whether to include a module. Args: module_filename: filename module_name: full module name module_kind: one of "py", "shlib" (shared library) Returns: True or False """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def onModuleInitialSet(self): """Provide extra modules to the initial root module set. Args: None Returns: Iterable of modules, may yield. """ # Virtual method, pylint: disable=no-self-use return () def onModuleCompleteSet(self, module_set): """Provide extra modules to the initial root module set. Args: module_set - tuple of module objects Returns: None Notes: You must not change anything, this is purely for warning and error checking, and potentially for later stages to prepare. """ @staticmethod def locateModule(module_name): """Provide a filename / -path for a to-be-imported module. Args: importing: module object that asked for it (tracing only) module_name: (str or ModuleName) full name of module Returns: filename for module """ from nuitka.importing.Importing import locateModule _module_name, module_filename, _finding = locateModule( module_name=ModuleName(module_name), parent_package=None, level=0 ) return module_filename @staticmethod def locateModules(module_name): """Provide a filename / -path for a to-be-imported module. Args: module_name: (str or ModuleName) full name of module Returns: list of ModuleName """ from nuitka.importing.Importing import locateModules return locateModules(module_name) @classmethod def locateDLL(cls, dll_name): """Locate a DLL by name.""" return locateDLL(dll_name) @classmethod def locateDLLsInDirectory(cls, directory): """Locate all DLLs in a folder Returns: list of (filename, filename_relative, dll_extension) """ return locateDLLsInDirectory(directory) @classmethod def makeDllEntryPoint(cls, source_path, dest_path, package_name): """Create an entry point, as expected to be provided by getExtraDlls.""" return makeDllEntryPoint( source_path=source_path, dest_path=dest_path, package_name=package_name ) def reportFileCount(self, module_name, count, section=None): if count: msg = "Found %d %s DLLs from '%s' %sinstallation." % ( count, "file" if count < 2 else "files", "" if not section else section, module_name.asString(), ) self.info(msg) def considerExtraDlls(self, dist_dir, module): """Provide a tuple of names of binaries to be included. Args: dist_dir: the distribution folder module: the module object needing the binaries Returns: tuple """ # TODO: This should no longer be here, as this API is obsolete, pylint: disable=unused-argument for included_entry_point in self.getExtraDlls(module): # Copy to the dist directory, which normally should not be a plugin task, but is for now. makePath(os.path.dirname(included_entry_point.dest_path)) shutil.copyfile( included_entry_point.source_path, included_entry_point.dest_path ) yield included_entry_point def getExtraDlls(self, module): """Provide IncludedEntryPoint named tuples describing extra needs of the module. Args: module: the module object needing the binaries Returns: yields IncludedEntryPoint objects """ # Virtual method, pylint: disable=no-self-use,unused-argument return () def getModuleSpecificDllPaths(self, module_name): """Provide a list of directories, where DLLs should be searched for this package (or module). Args: module_name: name of a package or module, for which the DLL path addition applies. Returns: iterable of paths """ # Virtual method, pylint: disable=no-self-use,unused-argument return () def removeDllDependencies(self, dll_filename, dll_filenames): """Yield any DLLs / shared libraries not to be included in distribution. Args: dll_filename: DLL name dll_filenames: list of DLLs Yields: yielded filenames to exclude """ # Virtual method, pylint: disable=no-self-use,unused-argument return () def considerDataFiles(self, module): """Yield data file names (source|func, target) for inclusion (iterator). Args: module: module object that may need extra data files Yields: Data file description pairs, either (source, dest) or (func, dest) where the func will be called to create the content dynamically. """ # Virtual method, pylint: disable=no-self-use,unused-argument return () def onStandaloneDistributionFinished(self, dist_dir): """Called after successfully creating a standalone distribution. Note: It is up to the plugin to take subsequent action. Examples are: insert additional information (license, copyright, company or application description), create installation material, further folder clean-up, start downstream applications etc. Args: dist_dir: the created distribution folder Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def onOnefileFinished(self, filename): """Called after successfully creating a onefile executable. Note: It is up to the plugin to take subsequent action. Examples are: insert additional information (license, copyright, company or application description), create installation material, further folder clean-up, start downstream applications etc. Args: filename: the created onefile executable Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def onFinalResult(self, filename): """Called after successfully finishing a compilation. Note: Plugins normally don't need this, and what filename is will be heavily dependent on compilation modes. Actions can be take here, e.g. commercial plugins output generated keys near that executable path. Args: filename: the created binary (module, accelerated exe, dist exe, onefile exe) Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def suppressUnknownImportWarning(self, importing, module_name, source_ref): """Suppress import warnings for unknown modules. Args: importing: the module object module_name: name of module source_ref: ??? Returns: True or False """ # Virtual method, pylint: disable=no-self-use,unused-argument return False def decideCompilation(self, module_name): """Decide whether to compile a module (or just use its bytecode). Notes: The first plugin not returning None makes the decision. Thereafter, no other plugins will be checked. If all plugins return None, the module will be compiled. Args: module_name: name of module Returns: "compiled" or "bytecode" or None (no opinion, use by default) """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def getPreprocessorSymbols(self): """Decide which C defines to be used in compilation. Notes: The plugins can each contribute, but are hopefully using a namespace for their defines. Returns: None for no defines, otherwise dictionary of key to be defined, and non-None values if any, i.e. no "-Dkey" only """ # Virtual method, pylint: disable=no-self-use return None def getExtraCodeFiles(self): """Add extra code files to the compilation. Notes: This is generally a bad idea to use unless you absolutely know what you are doing. Returns: None for no extra codes, otherwise dictionary of key to be filename, and value to be source code. """ # Virtual method, pylint: disable=no-self-use return None def getExtraLinkLibraries(self): """Decide which link library should be added. Notes: Names provided multiple times, e.g. by multiple plugins are only added once. Returns: None for no extra link library, otherwise the name as a **str** or an iterable of names of link libraries. """ # Virtual method, pylint: disable=no-self-use return None def getExtraLinkDirectories(self): """Decide which link directories should be added. Notes: Directories provided multiple times, e.g. by multiple plugins are only added once. Returns: None for no extra link directory, otherwise the name as a **str** or an iterable of names of link directories. """ # Virtual method, pylint: disable=no-self-use return None def warnUnusedPlugin(self, message): """An inactive plugin may issue a warning if it believes this may be wrong. Returns: None """ if self.plugin_name not in warned_unused_plugins: warned_unused_plugins.add(self.plugin_name) plugins_logger.warning( "Use '--enable-plugin=%s' for: %s" % (self.plugin_name, message) ) def onDataComposerResult(self, blob_filename): """Internal use only. Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None def encodeDataComposerName(self, data_name): """Internal use only. Returns: None """ # Virtual method, pylint: disable=no-self-use,unused-argument return None _runtime_information_cache = {} def queryRuntimeInformationMultiple(self, info_name, setup_codes, values): info_name = self.plugin_name + "_" + info_name if info_name in self._runtime_information_cache: return self._runtime_information_cache[info_name] keys = [] query_codes = [] for key, value_expression in values: keys.append(key) query_codes.append("print(repr(%s))" % value_expression) query_codes.append('print("-" * 27)') if type(setup_codes) is str: setup_codes = setup_codes.split("\n") cmd = r"""\ from __future__ import print_function from __future__ import absolute_import try: %(setup_codes)s except ImportError: import sys sys.exit(38) %(query_codes)s """ % { "setup_codes": "\n ".join(setup_codes), "query_codes": "\n".join(query_codes), } try: feedback = check_output([sys.executable, "-c", cmd]) except NuitkaCalledProcessError as e: if e.returncode == 38: return None raise if str is not bytes: # We want to work with strings, that's hopefully OK. feedback = feedback.decode("utf8") # Ignore Windows newlines difference. feedback = [line.strip() for line in feedback.splitlines()] if feedback.count("-" * 27) != len(keys): self.sysexit( "Error, mismatch in output retrieving %r information." % info_name ) feedback = [line for line in feedback if line != "-" * 27] NamedTupleResult = namedtuple(info_name, keys) # We are being lazy here, the code is trusted, pylint: disable=eval-used self._runtime_information_cache[info_name] = NamedTupleResult( *(eval(value) for value in feedback) ) return self._runtime_information_cache[info_name] def queryRuntimeInformationSingle(self, setup_codes, value): return self.queryRuntimeInformationMultiple( info_name="temp_info_for_" + self.plugin_name.replace("-", "_"), setup_codes=setup_codes, values=(("key", value),), ).key @staticmethod def onFunctionBodyParsing(module_name, function_name, body): pass @classmethod def warning(cls, message): plugins_logger.warning(cls.plugin_name + ": " + message) @classmethod def info(cls, message): plugins_logger.info(cls.plugin_name + ": " + message) @classmethod def sysexit(cls, message): plugins_logger.sysexit(cls.plugin_name + ": " + message) def isTriggerModule(module): return module in pre_modules.values() or module in post_modules.values() def replaceTriggerModule(old, new): found = None for key, value in pre_modules.items(): if value is old: found = key break if found is not None: pre_modules[found] = new found = None for key, value in post_modules.items(): if value is old: found = key break if found is not None: post_modules[found] = new import functools def standalone_only(func): """For plugins that have functionality that should be done in standalone mode only.""" @functools.wraps(func) def wrapped(*args, **kwargs): if isStandaloneMode(): return func(*args, **kwargs) else: if inspect.isgeneratorfunction(func): return () else: return None return wrapped Nuitka-0.6.19.1/nuitka/plugins/commercial/0000700000372100037210000000000014167275622025362 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/plugins/commercial/__init__.py0000600000372100037210000000246414166627112027475 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Commercial plugins package. This may load code from the commercial Nuitka repository """ # Auto extend to a Nuitka commercial installation, by adding it to the package # path. That aims at making extending Nuitka with these plugins easier. import os if "NUITKA_COMMERCIAL" in os.environ: path = os.environ["NUITKA_COMMERCIAL"] candidate = os.path.join(path, __name__.replace(".", os.path.sep)) if os.path.isdir(candidate) and os.path.isfile( os.path.join(candidate, "__init__.py") ): __path__.append(candidate) Nuitka-0.6.19.1/nuitka/plugins/Plugins.py0000600000372100037210000011510214166627112025236 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Plugins: Welcome to Nuitka! This is your shortest way to become part of it. This is to provide the base class for all plugins. Some of which are part of proper Nuitka, and some of which are waiting to be created and submitted for inclusion by you. The base class in PluginBase will serve as documentation of available. """ import inspect import os import shutil from optparse import OptionConflictError, OptionGroup import nuitka.plugins.commercial import nuitka.plugins.standard from nuitka import Options, OutputDirectories from nuitka.__past__ import basestring, iter_modules from nuitka.build.DataComposerInterface import deriveModuleConstantsBlobName from nuitka.containers.odict import OrderedDict from nuitka.containers.oset import OrderedSet from nuitka.freezer.IncludedEntryPoints import makeDllEntryPointOld from nuitka.ModuleRegistry import addUsedModule from nuitka.Tracing import plugins_logger, printLine from nuitka.utils.FileOperations import ( addFileExecutablePermission, makePath, putTextFileContents, ) from nuitka.utils.Importing import importFileAsModule from nuitka.utils.ModuleNames import ModuleName, checkModuleName from .PluginBase import NuitkaPluginBase, post_modules, pre_modules # Maps plugin name to plugin instances. active_plugins = OrderedDict() plugin_name2plugin_classes = {} plugin_options = {} plugin_datatag2pluginclasses = {} plugin_values = {} user_plugins = OrderedSet() def _addActivePlugin(plugin_class, args, force=False): plugin_name = plugin_class.plugin_name # No duplicates please. if not force: assert plugin_name not in active_plugins.keys(), ( plugin_name, active_plugins[plugin_name], ) if args: plugin_args = getPluginOptions(plugin_name) else: plugin_args = {} plugin_instance = plugin_class(**plugin_args) assert isinstance(plugin_instance, NuitkaPluginBase), plugin_instance active_plugins[plugin_name] = plugin_instance def getActivePlugins(): """Return list of active plugins. Returns: list of plugins """ return active_plugins.values() def getActiveQtPlugin(): from .standard.PySidePyQtPlugin import getQtPluginNames for plugin_name in getQtPluginNames(): if hasActivePlugin(plugin_name): if hasActivePlugin(plugin_name): return plugin_name return None def hasActivePlugin(plugin_name): """Decide if a plugin is active. Args: plugin_name - name of the plugin Notes: Detectors do not count as an active plugin and ignored. Returns: bool - plugin is loaded """ if plugin_name not in active_plugins: return False # Detectors do not count. plugin_instance = active_plugins.get(plugin_name) return not hasattr(plugin_instance, "detector_for") def getPluginClass(plugin_name): # First, load plugin classes, to know what we are talking about. loadPlugins() # Backward compatibility. plugin_name = Options.getPluginNameConsideringRenames(plugin_name) if plugin_name not in plugin_name2plugin_classes: plugins_logger.sysexit("Error, unknown plug-in '%s' referenced." % plugin_name) return plugin_name2plugin_classes[plugin_name][0] def _addPluginClass(plugin_class, detector): plugin_name = plugin_class.plugin_name if plugin_name in plugin_name2plugin_classes: plugins_logger.sysexit( "Error, plugins collide by name %s: %s <-> %s" % (plugin_name, plugin_class, plugin_name2plugin_classes[plugin_name]) ) plugin_name2plugin_classes[plugin_name] = ( plugin_class, detector, ) def _loadPluginClassesFromPackage(scan_package): scan_path = scan_package.__path__ for item in iter_modules(scan_path): if item.ispkg: continue module_loader = item.module_finder.find_module(item.name) # Ignore bytecode only left overs. try: if module_loader.get_filename().endswith(".pyc"): continue except AttributeError: # Not a bytecode loader, but e.g. extension module, which is OK in case # it was compiled with Nuitka. pass try: plugin_module = module_loader.load_module(item.name) except Exception: if Options.is_nondebug: plugins_logger.warning( "Problem loading plugin %r (%s), ignored. Use --debug to make it visible." % (item.name, module_loader.get_filename()) ) continue raise # At least for Python2, this is not set properly, but we use it for package # data loading. plugin_module.__package__ = scan_package.__name__ plugin_classes = set( obj for obj in plugin_module.__dict__.values() if isObjectAUserPluginBaseClass(obj) ) detectors = [ plugin_class for plugin_class in plugin_classes if hasattr(plugin_class, "detector_for") ] # First the ones with detectors. for detector in detectors: plugin_class = detector.detector_for if detector.__name__.replace( "NuitkaPluginDetector", "" ) != plugin_class.__name__.replace("NuitkaPlugin", ""): plugins_logger.warning( "Class names %r and %r do not match NuitkaPlugin* and NuitkaPluginDetector* naming convention." % (plugin_class.__name__, detector.__name__) ) assert detector.plugin_name is None, detector detector.plugin_name = plugin_class.plugin_name if plugin_class not in plugin_classes: plugins_logger.sysexit( "Plugin detector %r references unknown plugin %r" % (detector, plugin_class) ) plugin_classes.remove(detector) plugin_classes.remove(plugin_class) _addPluginClass( plugin_class=plugin_class, detector=detector, ) # Remaining ones have no detector. for plugin_class in plugin_classes: _addPluginClass(plugin_class=plugin_class, detector=None) def loadStandardPluginClasses(): """Load plugin files located in 'standard' folder. Notes: Scan through the 'standard' and 'commercial' sub-folder of the folder where this module resides. Import each valid Python module (but not packages) and process it as a plugin. Returns: None """ _loadPluginClassesFromPackage(nuitka.plugins.standard) _loadPluginClassesFromPackage(nuitka.plugins.commercial) class Plugins(object): implicit_imports_cache = {} @staticmethod def _considerImplicitImports(plugin, module): from nuitka.importing import Importing result = [] def iterateModuleNames(value): for v in value: if type(v) in (tuple, list): plugin.sysexit( "Plugin %r needs to be change to only return modules names, not %r (for %s)" % (plugin.plugin_name, v, module.getFullName().asString()) ) if inspect.isgenerator(v): for w in iterateModuleNames(v): yield w return if not checkModuleName(v): plugin.sysexit( "Plugin %r returned an invalid module name, not %r (for %s)" % (plugin, v, module.getFullName().asString()) ) yield ModuleName(v) for full_name in iterateModuleNames(plugin.getImplicitImports(module)): try: _module_name, module_filename, _finding = Importing.locateModule( module_name=full_name, parent_package=None, level=-1, ) except Exception: plugin.warning( "Problem locating '%s' for implicit imports of '%s'." % (module.getFullName(), full_name) ) raise if module_filename is None: if Options.isShowInclusion(): plugin.info( "Implicit module '%s' suggested for '%s' not found." % (full_name, module.getFullName()) ) continue result.append((full_name, module_filename)) if result: plugin.info( "Implicit dependencies of module '%s' added '%s'." % (module.getFullName(), ",".join(r[0] for r in result)) ) return result @staticmethod def _reportImplicitImports(plugin, module, implicit_imports, signal_change): from nuitka.importing import Recursion from nuitka.importing.Importing import getModuleNameAndKindFromFilename for full_name, module_filename in implicit_imports: _module_name2, module_kind = getModuleNameAndKindFromFilename( module_filename ) # This will get back to all other plugins allowing them to inhibit it though. decision, reason = Recursion.decideRecursion( module_filename=module_filename, module_name=full_name, module_kind=module_kind, ) if decision: imported_module = Recursion.recurseTo( signal_change=signal_change, module_name=full_name, module_filename=module_filename, module_kind=module_kind, reason=reason, ) addUsedModule( module=imported_module, using_module=module, usage_tag="plugin:" + plugin.plugin_name, reason=reason, source_ref=module.source_ref, ) @classmethod def considerImplicitImports(cls, module, signal_change): for plugin in getActivePlugins(): key = (module.getFullName(), plugin) if key not in cls.implicit_imports_cache: cls.implicit_imports_cache[key] = tuple( cls._considerImplicitImports(plugin=plugin, module=module) ) cls._reportImplicitImports( plugin=plugin, module=module, implicit_imports=cls.implicit_imports_cache[key], signal_change=signal_change, ) # Pre and post load code may have been created, if so indicate it's used. full_name = module.getFullName() if full_name in pre_modules: addUsedModule( pre_modules[full_name], using_module=module, usage_tag="plugins", reason="Not yet propagated by plugins.", source_ref=module.source_ref, ) if full_name in post_modules: addUsedModule( module=post_modules[full_name], using_module=module, usage_tag="plugins", reason="Not yet propagated by plugins.", source_ref=module.source_ref, ) @staticmethod def onStandaloneDistributionFinished(dist_dir): """Let plugins postprocess the distribution folder in standalone mode""" for plugin in getActivePlugins(): plugin.onStandaloneDistributionFinished(dist_dir) @staticmethod def onOnefileFinished(filename): """Let plugins postprocess the onefile executable in onefile mode""" for plugin in getActivePlugins(): plugin.onStandaloneDistributionFinished(filename) @staticmethod def onFinalResult(filename): """Let plugins add to final binary in some way""" for plugin in getActivePlugins(): plugin.onFinalResult(filename) @staticmethod def considerExtraDlls(dist_dir, module): """Ask plugins to provide extra DLLs. Notes: These will be of type nuitka.freezer.IncludedEntryPoints.IncludedEntryPoint and currently there is a backward compatibility for old style plugins that do provide tuples of 3 elements. But plugins are really supposed to provide the stuff created from factory functions for that type. """ result = [] for plugin in getActivePlugins(): for extra_dll in plugin.considerExtraDlls(dist_dir, module): # Backward compatibility with plugins not yet migrated to getExtraDlls usage. if len(extra_dll) == 3: extra_dll = makeDllEntryPointOld( source_path=extra_dll[0], dest_path=extra_dll[1], package_name=extra_dll[2], ) if not os.path.isfile(extra_dll.dest_path): plugin.sysexit( "Error, copied filename %r for module %r that is not a file." % (extra_dll.dest_path, module.getFullName()) ) else: if not os.path.isfile(extra_dll.source_path): plugin.sysexit( "Error, attempting to copy plugin determined filename %r for module %r that is not a file." % (extra_dll.source_path, module.getFullName()) ) makePath(os.path.dirname(extra_dll.dest_path)) shutil.copyfile(extra_dll.source_path, extra_dll.dest_path) if extra_dll.executable: addFileExecutablePermission(extra_dll.dest_path) result.append(extra_dll) return result @staticmethod def getModuleSpecificDllPaths(module_name): """Provide a list of directories, where DLLs should be searched for this package (or module). Args: module_name: name of a package or module, for which the DLL path addition applies. """ result = OrderedSet() for plugin in getActivePlugins(): for dll_path in plugin.getModuleSpecificDllPaths(module_name): result.add(dll_path) return result @staticmethod def removeDllDependencies(dll_filename, dll_filenames): """Create list of removable shared libraries by scanning through the plugins. Args: dll_filename: shared library filename dll_filenames: list of shared library filenames Returns: list of removable files """ dll_filenames = tuple(sorted(dll_filenames)) to_remove = OrderedSet() for plugin in getActivePlugins(): removed_dlls = tuple( plugin.removeDllDependencies(dll_filename, dll_filenames) ) if removed_dlls and Options.isShowInclusion(): plugin.info( "Removing DLLs %s of %s by plugin decision." % (dll_filename, removed_dlls) ) for removed_dll in removed_dlls: to_remove.add(removed_dll) for removed in to_remove: dll_filenames.discard(removed) @staticmethod def considerDataFiles(module): """For a given module, ask plugins for any needed data files it may require. Args: module: module object Yields: Data file description pairs, either (source, dest) or (func, dest) where the func will be called to create the content dynamically. """ for plugin in getActivePlugins(): for value in plugin.considerDataFiles(module): if value: yield plugin, value @classmethod def _createTriggerLoadedModule(cls, module, trigger_name, code, flags): """Create a "trigger" for a module to be imported. Notes: The trigger will incorporate the code to be prepended / appended. Called by @onModuleDiscovered. Args: module: the module object (serves as dict key) trigger_name: string ("-preload"/"-postload") code: the code string Returns trigger_module """ from nuitka.tree.Building import buildModule module_name = ModuleName(module.getFullName() + trigger_name) # In debug mode, put the files in the build folder, so they can be looked up easily. if Options.is_debug and "HIDE_SOURCE" not in flags: source_path = os.path.join( OutputDirectories.getSourceDirectoryPath(), module_name + ".py" ) putTextFileContents(filename=source_path, contents=code) try: trigger_module, _added = buildModule( module_filename=os.path.join( os.path.dirname(module.getCompileTimeFilename()), module_name.asPath() + ".py", ), module_name=module_name, source_code=code, is_top=False, is_main=False, is_shlib=False, is_fake=module_name, hide_syntax_error=False, ) except SyntaxError: plugins_logger.sysexit( "SyntaxError in plugin provided source code for '%s'." % module_name ) if trigger_module.getCompilationMode() == "bytecode": trigger_module.setSourceCode(code) return trigger_module @classmethod def onModuleDiscovered(cls, module): full_name = module.getFullName() def _untangleLoadDesc(descs): if descs and inspect.isgenerator(descs): descs = tuple(descs) if descs: if type(descs[0]) not in (tuple, list): descs = [descs] for desc in descs: if len(desc) == 2: code, reason = desc flags = () else: code, reason, flags = desc if type(flags) is str: flags = (flags,) yield plugin, code, reason, flags preload_descs = [] postload_descs = [] for plugin in getActivePlugins(): plugin.onModuleDiscovered(module) preload_descs.extend( _untangleLoadDesc(descs=plugin.createPreModuleLoadCode(module)) ) postload_descs.extend( _untangleLoadDesc(descs=plugin.createPostModuleLoadCode(module)) ) if preload_descs: total_code = [] total_flags = OrderedSet() for plugin, pre_code, reason, flags in preload_descs: if pre_code: plugin.info( "Injecting pre-module load code for module '%s':" % full_name ) for line in reason.split("\n"): plugin.info(" " + line) total_code.append(pre_code) total_flags.update(flags) if total_code: assert full_name not in pre_modules pre_modules[full_name] = cls._createTriggerLoadedModule( module=module, trigger_name="-preLoad", code="\n\n".join(total_code), flags=total_flags, ) if postload_descs: total_code = [] total_flags = OrderedSet() for plugin, post_code, reason, flags in postload_descs: if post_code: plugin.info( "Injecting post-module load code for module '%s':" % full_name ) for line in reason.split("\n"): plugin.info(" " + line) total_code.append(post_code) total_flags.update(flags) if total_code: assert full_name not in post_modules post_modules[full_name] = cls._createTriggerLoadedModule( module=module, trigger_name="-postLoad", code="\n\n".join(total_code), flags=total_flags, ) @staticmethod def onModuleSourceCode(module_name, source_code): assert type(module_name) is ModuleName assert type(source_code) is str for plugin in getActivePlugins(): new_source_code = plugin.onModuleSourceCode(module_name, source_code) if new_source_code is not None: source_code = new_source_code assert type(source_code) is str return source_code @staticmethod def onFrozenModuleSourceCode(module_name, is_package, source_code): assert type(module_name) is ModuleName assert type(source_code) is str for plugin in getActivePlugins(): source_code = plugin.onFrozenModuleSourceCode( module_name, is_package, source_code ) assert type(source_code) is str return source_code @staticmethod def onFrozenModuleBytecode(module_name, is_package, bytecode): assert type(module_name) is ModuleName assert bytecode.__class__.__name__ == "code" for plugin in getActivePlugins(): bytecode = plugin.onFrozenModuleBytecode(module_name, is_package, bytecode) assert bytecode.__class__.__name__ == "code" return bytecode @staticmethod def onModuleEncounter(module_filename, module_name, module_kind): result = None for plugin in getActivePlugins(): must_recurse = plugin.onModuleEncounter( module_filename, module_name, module_kind ) if must_recurse is None: continue if type(must_recurse) is not tuple and must_recurse not in (True, False): plugin.sysexit( "Error, onModuleEncounter code failed to return a None or tuple(bool, reason) result." ) if result is not None: # false alarm, pylint: disable=unsubscriptable-object assert result[0] == must_recurse[0] result = must_recurse return result @staticmethod def onModuleInitialSet(): """The initial set of root modules is complete, plugins may add more.""" from nuitka.ModuleRegistry import addRootModule for plugin in getActivePlugins(): for module in plugin.onModuleInitialSet(): addRootModule(module) @staticmethod def onModuleCompleteSet(): """The final set of modules is determined, this is only for inspection, cannot change.""" from nuitka.ModuleRegistry import getDoneModules # Make sure it's immutable. module_set = tuple(getDoneModules()) for plugin in getActivePlugins(): plugin.onModuleCompleteSet(module_set) @staticmethod def suppressUnknownImportWarning(importing, source_ref, module_name): """Let plugins decide whether to suppress import warnings for an unknown module. Notes: If all plugins return False or None, the return will be False, else True. Args: importing: the module which is importing "module_name" source_ref: pointer to file source code or bytecode module_name: the module to be imported returns: True or False (default) """ source_ref = importing.getSourceReference() for plugin in getActivePlugins(): if plugin.suppressUnknownImportWarning(importing, module_name, source_ref): return True return False @staticmethod def decideCompilation(module_name): """Let plugins decide whether to C compile a module or include as bytecode. Notes: The decision is made by the first plugin not returning None. Returns: "compiled" (default) or "bytecode". """ for plugin in getActivePlugins(): value = plugin.decideCompilation(module_name) if value is not None: assert value in ("compiled", "bytecode") return value return None preprocessor_symbols = None @classmethod def getPreprocessorSymbols(cls): """Let plugins provide C defines to be used in compilation. Notes: The plugins can each contribute, but are hopefully using a namespace for their defines. Returns: OrderedDict(), where None value indicates no define value, i.e. "-Dkey=value" vs. "-Dkey" """ if cls.preprocessor_symbols is None: cls.preprocessor_symbols = OrderedDict() for plugin in getActivePlugins(): value = plugin.getPreprocessorSymbols() if value is not None: assert type(value) is dict, value # We order per plugin, but from the plugins, lets just take a dict # and achieve determism by ordering the defines by name. for key, value in sorted(value.items()): # False alarm, pylint: disable=I0021,unsupported-assignment-operation cls.preprocessor_symbols[key] = value return cls.preprocessor_symbols @staticmethod def getExtraCodeFiles(): result = OrderedDict() for plugin in getActivePlugins(): value = plugin.getExtraCodeFiles() if value is not None: assert type(value) is dict # We order per plugin, but from the plugins, lets just take a dict # and achieve determism by ordering the files by name. for key, value in sorted(value.items()): if not key.startswith("nuitka_"): key = "plugin." + plugin.plugin_name + "." + key assert key not in result, key result[key] = value return result extra_link_libraries = None @classmethod def getExtraLinkLibraries(cls): if cls.extra_link_libraries is None: cls.extra_link_libraries = OrderedSet() for plugin in getActivePlugins(): value = plugin.getExtraLinkLibraries() if value is not None: if isinstance(value, basestring): cls.extra_link_libraries.add(value) else: for library_name in value: cls.extra_link_libraries.add(library_name) return cls.extra_link_libraries extra_link_directories = None @classmethod def getExtraLinkDirectories(cls): if cls.extra_link_directories is None: cls.extra_link_directories = OrderedSet() for plugin in getActivePlugins(): value = plugin.getExtraLinkDirectories() if value is not None: if isinstance(value, basestring): cls.extra_link_directories.add(value) else: for dir_name in value: cls.extra_link_directories.add(dir_name) return cls.extra_link_directories @classmethod def onDataComposerResult(cls, blob_filename): for plugin in getActivePlugins(): plugin.onDataComposerResult(blob_filename) @classmethod def deriveModuleConstantsBlobName(cls, data_filename): result = deriveModuleConstantsBlobName(data_filename) return cls.encodeDataComposerName(result) @classmethod def encodeDataComposerName(cls, name): if str is not bytes: # Encoding needs to match generated source code output. name = name.encode("latin1") for plugin in getActivePlugins(): r = plugin.encodeDataComposerName(name) if r is not None: name = r break return name @classmethod def onFunctionBodyParsing(cls, provider, function_name, body): module_name = provider.getParentModule().getFullName() for plugin in getActivePlugins(): plugin.onFunctionBodyParsing( module_name=module_name, function_name=function_name, body=body, ) def listPlugins(): """Print available standard plugins.""" loadPlugins() printLine("The following plugins are available in Nuitka".center(80)) printLine("-" * 80) plist = [] name_len = 0 for plugin_name in sorted(plugin_name2plugin_classes): plugin = plugin_name2plugin_classes[plugin_name][0] if hasattr(plugin, "plugin_desc"): plist.append((plugin_name, plugin.plugin_desc)) else: plist.append((plugin_name, "")) name_len = max(len(plugin_name) + 1, name_len) for line in plist: printLine(" " + line[0].ljust(name_len), line[1]) def isObjectAUserPluginBaseClass(obj): """Verify that a user plugin inherits from UserPluginBase.""" try: return ( obj is not NuitkaPluginBase and issubclass(obj, NuitkaPluginBase) and not inspect.isabstract(obj) and not obj.__name__.endswith("PluginBase") ) except TypeError: return False def loadUserPlugin(plugin_filename): """Load of a user plugins and store them in list of active plugins. Notes: A plugin is accepted only if it has a non-empty variable plugin_name, which does not equal that of a disabled (standard) plugin. Supports plugin option specifications. Returns: None """ if not os.path.exists(plugin_filename): plugins_logger.sysexit("Error, cannot find '%s'." % plugin_filename) user_plugin_module = importFileAsModule(plugin_filename) valid_file = False plugin_class = None for key in dir(user_plugin_module): obj = getattr(user_plugin_module, key) if not isObjectAUserPluginBaseClass(obj): continue plugin_name = getattr(obj, "plugin_name", None) if plugin_name and plugin_name not in Options.getPluginsDisabled(): plugin_class = obj valid_file = True break # do not look for more in that module if not valid_file: # this is not a plugin file ... plugins_logger.sysexit("Error, '%s' is not a plugin file." % plugin_filename) return plugin_class _loaded_plugins = False def loadPlugins(): """Initialize plugin class Notes: Load user plugins provided as Python script file names, and standard plugins via their class attribute 'plugin_name'. Several checks are made, see the loader functions. User plugins are enabled as a first step, because they themselves may enable standard plugins. Returns: None """ # Singleton, called potentially multiple times, pylint: disable=global-statement global _loaded_plugins if not _loaded_plugins: _loaded_plugins = True # now enable standard plugins loadStandardPluginClasses() def activatePlugins(): """Activate selected plugin classes Args: None Notes: This creates actual plugin instances, before only class objects were used. User plugins are activated as a first step, because they themselves may enable standard plugins. Returns: None """ loadPlugins() # ensure plugin is known and not both, enabled and disabled for plugin_name in Options.getPluginsEnabled() + Options.getPluginsDisabled(): if plugin_name not in plugin_name2plugin_classes: plugins_logger.sysexit( "Error, unknown plug-in '%s' referenced." % plugin_name ) if ( plugin_name in Options.getPluginsEnabled() and plugin_name in Options.getPluginsDisabled() ): plugins_logger.sysexit( "Error, conflicting enable/disable of plug-in '%s'." % plugin_name ) for (plugin_name, (plugin_class, plugin_detector)) in sorted( plugin_name2plugin_classes.items() ): if plugin_name in Options.getPluginsEnabled(): if plugin_class.isAlwaysEnabled(): plugin_class.warning("Plugin is defined as always enabled.") if plugin_class.isRelevant(): _addActivePlugin(plugin_class, args=True) else: plugin_class.warning( "Not relevant with this OS, or Nuitka arguments given, not activated." ) elif plugin_name in Options.getPluginsDisabled(): pass elif plugin_class.isAlwaysEnabled() and plugin_class.isRelevant(): _addActivePlugin(plugin_class, args=True) elif ( plugin_detector is not None and Options.shallDetectMissingPlugins() and plugin_detector.isRelevant() ): _addActivePlugin(plugin_detector, args=False) for plugin_class in user_plugins: _addActivePlugin(plugin_class, args=True) def lateActivatePlugin(plugin_name, option_values): """Activate plugin after the command line parsing, expects options to be set.""" values = getPluginClass(plugin_name).getPluginDefaultOptionValues() values.update(option_values) setPluginOptions(plugin_name, values) _addActivePlugin(getPluginClass(plugin_name), args=True, force=True) def _addPluginCommandLineOptions(parser, plugin_class, data_files_tags): plugin_name = plugin_class.plugin_name if plugin_name not in plugin_options: option_group = OptionGroup(parser, "Plugin %s" % plugin_name) try: plugin_class.addPluginCommandLineOptions(option_group) except OptionConflictError as e: for other_plugin_name, other_plugin_option_list in plugin_options.items(): for other_plugin_option in other_plugin_option_list: # no public interface for that, pylint: disable=protected-access if ( e.option_id in other_plugin_option._long_opts or other_plugin_option._short_opts ): plugins_logger.sysexit( "Plugin '%s' failed to add options due to conflict with '%s' from plugin '%s." % (plugin_name, e.option_id, other_plugin_name) ) if option_group.option_list: parser.add_option_group(option_group) plugin_options[plugin_name] = option_group.option_list else: plugin_options[plugin_name] = () plugin_data_files_tags = plugin_class.getTagDataFileTagOptions() if plugin_data_files_tags: for tag_name, tag_desc in plugin_data_files_tags: if tag_name in (tag for tag, _desc in data_files_tags): plugins_logger.sysexit( "Plugin '%s' provides data files tag handling '%s' already provided." % (plugin_name, tag_name) ) data_files_tags.append((tag_name, tag_desc)) plugin_datatag2pluginclasses[tag_name] = plugin_class def addPluginCommandLineOptions(parser, plugin_names, data_files_tags): """Add option group for the plugin to the parser. Notes: This is exclusively for use in the commandline parsing. Not all plugins have to have options. But this will add them to the parser in a first pass, so they can be recognized in a second pass with them included. Returns: None """ for plugin_name in plugin_names: plugin_class = getPluginClass(plugin_name) _addPluginCommandLineOptions( parser=parser, plugin_class=plugin_class, data_files_tags=data_files_tags ) def addUserPluginCommandLineOptions(parser, filename, data_files_tags): plugin_class = loadUserPlugin(filename) _addPluginCommandLineOptions( parser=parser, plugin_class=plugin_class, data_files_tags=data_files_tags ) user_plugins.add(plugin_class) def setPluginOptions(plugin_name, values): """Set the option values for the specified plugin. Args: plugin_name: plugin identifier values: dictionary to be used for the plugin constructor Notes: Use this function, if you want to set the plugin values, without using the actual command line parsing. Normally the command line arguments are populating the dictionary for the plugin, but this will be used if given, and command line parsing is not done. """ assert isinstance(values, dict), values plugin_values[plugin_name] = values def getPluginOptions(plugin_name): """Return the options values for the specified plugin. Args: plugin_name: plugin identifier Returns: dict with key, value of options given, potentially from default values. """ result = plugin_values.get(plugin_name, {}) for option in plugin_options.get(plugin_name, {}): option_name = option._long_opts[0] # pylint: disable=protected-access arg_value = getattr(Options.options, option.dest) if "[REQUIRED]" in option.help: if not arg_value: plugins_logger.sysexit( "Error, required plugin argument %r of Nuitka plugin %s not given." % (option_name, plugin_name) ) result[option.dest] = arg_value return result Nuitka-0.6.19.1/nuitka/plugins/__init__.py0000600000372100037210000000150114166627112025351 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/__past__.py0000600000372100037210000001172214166627112023702 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module like __future__ for things that are changed between Python2 and Python3. These are here to provide compatible fall-backs. This is required to run the same code easily with both CPython2 and CPython3. Sometimes, we do not care about the actual types, or API, but would rather just check for something to be a "in (str, unicode)" rather than making useless version checks. """ import sys from abc import ABCMeta # pylint: disable=invalid-name,self-assigning-variable if str is bytes: import __builtin__ as builtins # Python2 code, pylint: disable=import-error else: import builtins # Work around for CPython 3.x renaming "long" to "int". if str is bytes: long = long # Python2 code, pylint: disable=undefined-variable else: long = int # Work around for CPython 3.x renaming "unicode" to "str". if str is bytes: unicode = unicode # Python2 code, pylint: disable=undefined-variable else: unicode = str if str is bytes: def iterItems(d): return d.iteritems() else: def iterItems(d): return d.items() if str is not bytes: raw_input = input xrange = range basestring = str else: raw_input = raw_input xrange = xrange basestring = basestring if str is bytes: from urllib import ( # pylint: disable=I0021,import-error,no-name-in-module urlretrieve, ) else: from urllib.request import urlretrieve if str is bytes: from cStringIO import ( # Python2 code, pylint: disable=import-error StringIO, ) else: from io import StringIO if str is bytes: BytesIO = StringIO else: from io import BytesIO try: from functools import total_ordering except ImportError: # Lame replacement for functools.total_ordering, which does not exist on # Python2.6, this requires "<" and "=" and adds all other operations. def total_ordering(cls): cls.__ne__ = lambda self, other: not self == other cls.__le__ = lambda self, other: self == other or self < other cls.__gt__ = lambda self, other: self != other and not self < other cls.__ge__ = lambda self, other: self == other and not self < other return cls if str is bytes: # Python2 only code, pylint: disable=deprecated-class,no-name-in-module from collections import Iterable, MutableSet else: from collections.abc import Iterable, MutableSet if str is bytes: intern = intern # Python2 code, pylint: disable=undefined-variable else: intern = sys.intern if str is bytes: to_byte = chr from_byte = ord else: def to_byte(value): assert type(value) is int and 0 <= value < 256 return bytes((value,)) def from_byte(value): assert type(value) is bytes and len(value) == 1, value return value[0] try: from typing import GenericAlias except ImportError: GenericAlias = None try: from types import UnionType except ImportError: UnionType = None def getMetaClassBase(meta_class_prefix): """For Python2/3 compatible source, we create a base class that has the metaclass used and doesn't require making a choice. """ class MetaClass(ABCMeta): pass MetaClassBase = MetaClass("%sMetaClassBase" % meta_class_prefix, (object,), {}) return MetaClassBase if str is bytes: try: import subprocess32 as subprocess except ImportError: import subprocess else: import subprocess # Just to make this not Windows-specific. WindowsError = OSError # pylint: disable=I0021,redefined-builtin import pkgutil if not hasattr(pkgutil, "ModuleInfo"): # Python3.5 or lower do not return namedtuple, but it's nicer to read code with it. from collections import namedtuple ModuleInfo = namedtuple("ModuleInfo", "module_finder name ispkg") def iter_modules(path=None, prefix=""): for item in pkgutil.iter_modules(path, prefix): yield ModuleInfo(*item) else: iter_modules = pkgutil.iter_modules # For PyLint to be happy. assert long assert unicode assert urlretrieve assert StringIO assert BytesIO assert type(xrange) is type, xrange assert total_ordering assert intern assert builtins assert Iterable assert MutableSet assert subprocess assert GenericAlias or intern assert UnionType or intern Nuitka-0.6.19.1/nuitka/optimizations/0000700000372100037210000000000014167275622024477 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/optimizations/FunctionInlining.py0000600000372100037210000000756414166627112030336 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ In-lining of functions. Done by assigning the argument values to variables, and producing an outline from the in-lined function. """ from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementReleaseVariable, ) from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.tree.Operations import VisitorNoopMixin, visitTree from nuitka.tree.ReformulationTryFinallyStatements import ( makeTryFinallyStatement, ) from nuitka.tree.TreeHelpers import makeStatementsSequence class VariableScopeUpdater(VisitorNoopMixin): def __init__(self, locals_scope, variable_translation): self.locals_scope = locals_scope self.variable_translation = variable_translation def onEnterNode(self, node): if hasattr(node, "variable"): if node.variable in self.variable_translation: node.variable = self.variable_translation[node.variable] if hasattr(node, "locals_scope"): node.locals_scope = self.locals_scope def updateLocalsScope(provider, locals_scope, variable_translation): visitor = VariableScopeUpdater( locals_scope=locals_scope, variable_translation=variable_translation ) visitTree(provider, visitor) def convertFunctionCallToOutline(provider, function_body, values, call_source_ref): # This has got to have pretty man details, pylint: disable=too-many-locals function_source_ref = function_body.getSourceReference() outline_body = ExpressionOutlineBody( provider=provider, name="inline", source_ref=function_source_ref ) # Make a clone first, so we do not harm other references. clone = function_body.subnode_body.makeClone() locals_scope_clone, variable_translation = function_body.locals_scope.makeClone( clone ) # TODO: Lets update all at once maybe, it would take less visits. updateLocalsScope( clone, locals_scope=locals_scope_clone, variable_translation=variable_translation, ) argument_names = function_body.getParameters().getParameterNames() assert len(argument_names) == len(values), (argument_names, values) statements = [] for argument_name, value in zip(argument_names, values): statements.append( StatementAssignmentVariable( variable=variable_translation[argument_name], source=value, source_ref=call_source_ref, ) ) body = makeStatementsSequence( statements=(statements, clone), allow_none=False, source_ref=function_source_ref ) auto_releases = function_body.getFunctionVariablesWithAutoReleases() # TODO: Not possible to auto release with outline bodies too? if auto_releases: releases = [ StatementReleaseVariable(variable=variable, source_ref=function_source_ref) for variable in auto_releases ] body = makeTryFinallyStatement( provider=outline_body, tried=body, final=releases, source_ref=function_source_ref, ) outline_body.setChild("body", body) return outline_body Nuitka-0.6.19.1/nuitka/optimizations/ValueTraces.py0000600000372100037210000004453714166627112027300 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Value trace objects. Value traces indicate the flow of values and merges their versions for the SSA (Single State Assignment) form being used in Nuitka. Values can be seen as: * Unknown (maybe initialized, maybe not, we cannot know) * Uninit (definitely not initialized, first version) * Init (definitely initialized, e.g. parameter variables) * Assign (assignment was done) * Deleted (del was done, now unassigned, uninitialted) * Merge (result of diverged code paths, loop potentially) * LoopIncomplete (aggregation during loops, not yet fully known) * LoopComplete (complete knowledge of loop types) """ from nuitka.nodes.shapes.BuiltinTypeShapes import tshape_dict, tshape_tuple from nuitka.nodes.shapes.StandardShapes import ( ShapeLoopCompleteAlternative, ShapeLoopInitialAlternative, tshape_uninit, tshape_unknown, ) from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) class ValueTraceBase(object): # We are going to have many instance attributes, but should strive to minimize, as # there is going to be a lot of fluctuation in these objects. __slots__ = ( "owner", "usage_count", "name_usage_count", "merge_usage_count", "closure_usages", "previous", ) @counted_init def __init__(self, owner, previous): self.owner = owner # Definite usage indicator. self.usage_count = 0 # If 0, this indicates, the variable name needs to be assigned as name. self.name_usage_count = 0 # If 0, this indicates no value merges happened on the value. self.merge_usage_count = 0 self.closure_usages = False # Previous trace this is replacing. self.previous = previous if isCountingInstances(): __del__ = counted_del() def __repr__(self): return "<%s of %s>" % (self.__class__.__name__, self.owner.getCodeName()) def getOwner(self): return self.owner @staticmethod def isLoopTrace(): return False def addUsage(self): self.usage_count += 1 def addNameUsage(self): self.usage_count += 1 self.name_usage_count += 1 if self.name_usage_count <= 2 and self.previous is not None: self.previous.addNameUsage() def addMergeUsage(self): self.usage_count += 1 self.merge_usage_count += 1 def getUsageCount(self): return self.usage_count def getNameUsageCount(self): return self.name_usage_count def getMergeUsageCount(self): return self.merge_usage_count def getMergeOrNameUsageCount(self): return self.merge_usage_count + self.name_usage_count def getPrevious(self): return self.previous @staticmethod def isAssignTrace(): return False @staticmethod def isUnassignedTrace(): return False @staticmethod def isDeletedTrace(): return False @staticmethod def isUninitTrace(): return False @staticmethod def isInitTrace(): return False @staticmethod def isUnknownTrace(): return False @staticmethod def isEscapeTrace(): return False @staticmethod def isEscapeOrUnknownOrUninitTrace(): return False @staticmethod def isMergeTrace(): return False def mustHaveValue(self): """Will this definitely have a value. Every trace has this overloaded. """ assert False, self def mustNotHaveValue(self): """Will this definitely have a value. Every trace has this overloaded. """ assert False, self def getReplacementNode(self, usage): # Virtual method, pylint: disable=no-self-use,unused-argument return None @staticmethod def hasShapeDictionaryExact(): return False @staticmethod def hasShapeStrExact(): return False @staticmethod def hasShapeUnicodeExact(): return False @staticmethod def hasShapeTupleExact(): return False @staticmethod def getTruthValue(): return None @staticmethod def getComparisonValue(): return False, None @staticmethod def getAttributeNode(): return None @staticmethod def getAttributeNodeTrusted(): return None @staticmethod def getAttributeNodeVeryTrusted(): return None class ValueTraceUnassignedBase(ValueTraceBase): __slots__ = () @staticmethod def isUnassignedTrace(): return True @staticmethod def getTypeShape(): return tshape_uninit def compareValueTrace(self, other): # We are unassigned, just need to know if the other one is, pylint: disable=no-self-use return other.isUnassignedTrace() @staticmethod def mustHaveValue(): return False @staticmethod def mustNotHaveValue(): return True class ValueTraceUninit(ValueTraceUnassignedBase): __slots__ = () def __init__(self, owner, previous): ValueTraceUnassignedBase.__init__(self, owner=owner, previous=previous) @staticmethod def isUninitTrace(): return True @staticmethod def isEscapeOrUnknownOrUninitTrace(): return True class ValueTraceDeleted(ValueTraceUnassignedBase): """Trace caused by a deletion.""" __slots__ = ("del_node",) def __init__(self, owner, previous, del_node): ValueTraceUnassignedBase.__init__(self, owner=owner, previous=previous) self.del_node = del_node @staticmethod def isDeletedTrace(): return True def getDelNode(self): return self.del_node class ValueTraceInit(ValueTraceBase): __slots__ = () def __init__(self, owner): ValueTraceBase.__init__(self, owner=owner, previous=None) @staticmethod def getTypeShape(): return tshape_unknown def compareValueTrace(self, other): # We are initialized, just need to know if the other one is, pylint: disable=no-self-use return other.isInitTrace() @staticmethod def isInitTrace(): return True @staticmethod def mustHaveValue(): return True @staticmethod def mustNotHaveValue(): return False class ValueTraceInitStarArgs(ValueTraceInit): @staticmethod def getTypeShape(): return tshape_tuple @staticmethod def hasShapeTupleExact(): return True class ValueTraceInitStarDict(ValueTraceInit): @staticmethod def getTypeShape(): return tshape_dict @staticmethod def hasShapeDictionaryExact(): return True class ValueTraceUnknown(ValueTraceBase): __slots__ = () @staticmethod def getTypeShape(): return tshape_unknown def addUsage(self): self.usage_count += 1 if self.previous: self.previous.addUsage() def addMergeUsage(self): self.usage_count += 1 self.merge_usage_count += 1 if self.previous: self.previous.addMergeUsage() def compareValueTrace(self, other): # We are unknown, just need to know if the other one is, pylint: disable=no-self-use return other.isUnknownTrace() @staticmethod def isUnknownTrace(): return True @staticmethod def isEscapeOrUnknownOrUninitTrace(): return True @staticmethod def mustHaveValue(): return False @staticmethod def mustNotHaveValue(): return False def getAttributeNode(self): # TODO: Differentiate unknown with not previous node from ones with for performance and # clarity. if self.previous is not None: return self.previous.getAttributeNodeVeryTrusted() def getAttributeNodeTrusted(self): if self.previous is not None: return self.previous.getAttributeNodeVeryTrusted() def getAttributeNodeVeryTrusted(self): if self.previous is not None: return self.previous.getAttributeNodeVeryTrusted() class ValueTraceEscaped(ValueTraceUnknown): __slots__ = () def addUsage(self): self.usage_count += 1 # The previous must be prevented from optimization if still used afterwards. if self.usage_count <= 2: self.previous.addNameUsage() def addMergeUsage(self): self.usage_count += 1 if self.usage_count <= 2: self.previous.addNameUsage() self.merge_usage_count += 1 if self.merge_usage_count <= 2: self.previous.addMergeUsage() def mustHaveValue(self): return self.previous.mustHaveValue() def mustNotHaveValue(self): return self.previous.mustNotHaveValue() def getReplacementNode(self, usage): return self.previous.getReplacementNode(usage) @staticmethod def isUnknownTrace(): return False @staticmethod def isEscapeTrace(): return True @staticmethod def isEscapeOrUnknownOrUninitTrace(): return True def getAttributeNode(self): return self.previous.getAttributeNodeTrusted() def getAttributeNodeTrusted(self): return self.previous.getAttributeNodeTrusted() def getAttributeNodeVeryTrusted(self): return self.previous.getAttributeNodeVeryTrusted() class ValueTraceAssign(ValueTraceBase): __slots__ = ("assign_node", "replace_it") def __init__(self, owner, assign_node, previous): ValueTraceBase.__init__(self, owner=owner, previous=previous) self.assign_node = assign_node self.replace_it = None def __repr__(self): return "".format( source_ref=self.assign_node.getSourceReference().getAsString(), value=self.assign_node.subnode_source, ) @staticmethod def isAssignTrace(): return True def compareValueTrace(self, other): return other.isAssignTrace() and self.assign_node is other.assign_node @staticmethod def mustHaveValue(): return True @staticmethod def mustNotHaveValue(): return False def getTypeShape(self): return self.assign_node.getTypeShape() def getAssignNode(self): return self.assign_node def setReplacementNode(self, replacement): self.replace_it = replacement def getReplacementNode(self, usage): if self.replace_it is not None: return self.replace_it(usage) else: return None def hasShapeDictionaryExact(self): return self.assign_node.subnode_source.hasShapeDictionaryExact() def hasShapeStrExact(self): return self.assign_node.subnode_source.hasShapeStrExact() def hasShapeUnicodeExact(self): return self.assign_node.subnode_source.hasShapeUnicodeExact() def getTruthValue(self): return self.assign_node.subnode_source.getTruthValue() def getComparisonValue(self): return self.assign_node.subnode_source.getComparisonValue() def getAttributeNode(self): return self.assign_node.subnode_source def getAttributeNodeTrusted(self): source_node = self.assign_node.subnode_source if source_node.hasShapeTrustedAttributes(): return source_node else: return None def getAttributeNodeVeryTrusted(self): source_node = self.assign_node.subnode_source if source_node.isExpressionImportModuleHard(): return source_node else: return None class ValueTraceMergeBase(ValueTraceBase): """Merge of two or more traces or start of loops.""" __slots__ = () def addNameUsage(self): self.usage_count += 1 self.name_usage_count += 1 if self.name_usage_count <= 2 and self.previous is not None: for previous in self.previous: previous.addNameUsage() def addUsage(self): self.usage_count += 1 # Only do it once. if self.usage_count == 1: for trace in self.previous: trace.addMergeUsage() def addMergeUsage(self): self.addUsage() self.merge_usage_count += 1 class ValueTraceMerge(ValueTraceMergeBase): """Merge of two or more traces. Happens at the end of conditional blocks. This is "phi" in SSA theory. Also used for merging multiple "return", "break" or "continue" exits. """ __slots__ = () def __init__(self, traces): ValueTraceMergeBase.__init__(self, owner=traces[0].owner, previous=traces) def __repr__(self): return "".format(previous=self.previous) def getTypeShape(self): type_shapes = set() for trace in self.previous: type_shape = trace.getTypeShape() if type_shape is tshape_unknown: return tshape_unknown type_shapes.add(type_shape) # TODO: Find the lowest common denominator. if len(type_shapes) == 1: return type_shapes.pop() else: return tshape_unknown @staticmethod def isMergeTrace(): return True def compareValueTrace(self, other): if not other.isMergeTrace(): return False if len(self.previous) != len(other.previous): return False for a, b in zip(self.previous, other.previous): if not a.compareValueTrace(b): return False return True def mustHaveValue(self): for previous in self.previous: if not previous.isInitTrace() and not previous.isAssignTrace(): return False return True def mustNotHaveValue(self): for previous in self.previous: if not previous.mustNotHaveValue(): return False return True def hasShapeDictionaryExact(self): return all(previous.hasShapeDictionaryExact() for previous in self.previous) def getTruthValue(self): any_false = False any_true = False for previous in self.previous: truth_value = previous.getTruthValue() # One unknown kills it. if truth_value is None: return None elif truth_value is True: # True and false values resembled unknown. if any_false: return None any_true = True else: # True and false values resembled unknown. if any_true: return None any_false = True # Now all agreed and were not unknown, so we can conclude all false or all true. return any_true def getComparisonValue(self): # TODO: Support multiple values as candidates, e.g. both 1, 3 could be compared to 2, for # now we are delaying that. return False, None class ValueTraceLoopBase(ValueTraceMergeBase): __slots__ = ("loop_node", "type_shapes", "type_shape", "recursion") def __init__(self, loop_node, previous, type_shapes): # Note: That previous is being added to later. ValueTraceMergeBase.__init__(self, owner=previous.owner, previous=(previous,)) self.loop_node = loop_node self.type_shapes = type_shapes self.type_shape = None self.recursion = False def __repr__(self): return "<%s shapes %s of %s>" % ( self.__class__.__name__, self.type_shapes, self.owner.getCodeName(), ) @staticmethod def isLoopTrace(): return True def getTypeShape(self): if self.type_shape is None: if len(self.type_shapes) > 1: self.type_shape = ShapeLoopCompleteAlternative(self.type_shapes) else: self.type_shape = next(iter(self.type_shapes)) return self.type_shape def addLoopContinueTraces(self, continue_traces): self.previous += tuple(continue_traces) for previous in continue_traces: previous.addMergeUsage() def mustHaveValue(self): # To handle recursion, we lie to ourselves. if self.recursion: return True self.recursion = True for previous in self.previous: if not previous.mustHaveValue(): self.recursion = False return False self.recursion = False return True class ValueTraceLoopComplete(ValueTraceLoopBase): __slots__ = () def compareValueTrace(self, other): # Incomplete loop value traces behave the same. return ( self.__class__ is other.__class__ and self.loop_node == other.loop_node and self.type_shapes == other.type_shapes ) # TODO: These could be better @staticmethod def mustHaveValue(): return False @staticmethod def mustNotHaveValue(): return False @staticmethod def getTruthValue(): return None @staticmethod def getComparisonValue(): return False, None class ValueTraceLoopIncomplete(ValueTraceLoopBase): __slots__ = () def getTypeShape(self): if self.type_shape is None: self.type_shape = ShapeLoopInitialAlternative(self.type_shapes) return self.type_shape def compareValueTrace(self, other): # Incomplete loop value traces behave the same. return self.__class__ is other.__class__ and self.loop_node == other.loop_node @staticmethod def mustHaveValue(): return False @staticmethod def mustNotHaveValue(): return False @staticmethod def getTruthValue(): return None @staticmethod def getComparisonValue(): return False, None Nuitka-0.6.19.1/nuitka/optimizations/BytecodeDemotion.py0000600000372100037210000000615314166627112030307 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Demotion of compiled modules to bytecode modules. """ import marshal from nuitka import Options from nuitka.Bytecodes import compileSourceToBytecode from nuitka.Caching import writeImportedModulesNamesToCache from nuitka.importing.ImportCache import ( isImportedModuleByName, replaceImportedModule, ) from nuitka.ModuleRegistry import replaceRootModule from nuitka.nodes.ModuleNodes import makeUncompiledPythonModule from nuitka.plugins.Plugins import Plugins from nuitka.Tracing import inclusion_logger def demoteSourceCodeToBytecode(module_name, source_code, filename): # Second chance for plugins to modify source code just before turning it # to bytecode. source_code = Plugins.onFrozenModuleSourceCode( module_name=module_name, is_package=False, source_code=source_code ) bytecode = compileSourceToBytecode(source_code, filename) bytecode = Plugins.onFrozenModuleBytecode( module_name=module_name, is_package=False, bytecode=bytecode ) return marshal.dumps(bytecode) def demoteCompiledModuleToBytecode(module): """Demote a compiled module to uncompiled (bytecode).""" full_name = module.getFullName() filename = module.getCompileTimeFilename() if Options.isShowProgress(): inclusion_logger.info( "Demoting module %r to bytecode from %r." % (full_name.asString(), filename) ) source_code = module.getSourceCode() bytecode = demoteSourceCodeToBytecode( module_name=full_name, source_code=source_code, filename=filename ) uncompiled_module = makeUncompiledPythonModule( module_name=full_name, filename=filename, bytecode=bytecode, is_package=module.isCompiledPythonPackage(), user_provided=True, technical=False, ) used_modules = module.getUsedModules() uncompiled_module.setUsedModules(used_modules) module.finalize() if isImportedModuleByName(full_name): replaceImportedModule(old=module, new=uncompiled_module) replaceRootModule(old=module, new=uncompiled_module) from nuitka.plugins.PluginBase import isTriggerModule, replaceTriggerModule if isTriggerModule(module): replaceTriggerModule(old=module, new=uncompiled_module) writeImportedModulesNamesToCache( module_name=full_name, source_code=source_code, used_modules=used_modules ) Nuitka-0.6.19.1/nuitka/optimizations/Graphs.py0000600000372100037210000000414014166627112026270 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Graph optimization states. These are not the graphs you might be thinking of. This is for rending the progress of optimization into images. """ from nuitka import Options from nuitka.ModuleRegistry import getDoneModules from nuitka.Tracing import general graph = None computation_counters = {} progressive = False def _addModuleGraph(module, desc): module_graph = module.asGraph(graph, desc) return module_graph def onModuleOptimizationStep(module): # Update the graph if active. if graph is not None: computation_counters[module] = computation_counters.get(module, 0) + 1 if progressive: _addModuleGraph(module, computation_counters[module]) def startGraph(): # We maintain this globally to make it accessible, pylint: disable=global-statement global graph if Options.shallCreateGraph(): try: from pygraphviz import AGraph # pylint: disable=I0021,import-error graph = AGraph(name="Optimization", directed=True) graph.layout() except ImportError: general.sysexit("Cannot import pygraphviz module, no graphing capability.") def endGraph(output_filename): if graph is not None: for module in getDoneModules(): _addModuleGraph(module, "final") graph.draw(output_filename + ".dot", prog="dot") Nuitka-0.6.19.1/nuitka/optimizations/TraceCollections.py0000600000372100037210000011741014166627112030306 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Trace collection (also often still referred to as constraint collection). At the core of value propagation there is the collection of constraints that allow to propagate knowledge forward or not. This is about collecting these constraints and to manage them. """ import contextlib from collections import defaultdict from contextlib import contextmanager from nuitka import Tracing, Variables from nuitka.__past__ import iterItems # Python3 compatibility. from nuitka.containers.oset import OrderedSet from nuitka.ModuleRegistry import addUsedModule from nuitka.nodes.NodeMakingHelpers import getComputationResult from nuitka.nodes.shapes.BuiltinTypeShapes import tshape_dict from nuitka.nodes.shapes.StandardShapes import tshape_uninit from nuitka.tree.SourceReading import readSourceLine from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) from nuitka.utils.Timing import TimerReport from .ValueTraces import ( ValueTraceAssign, ValueTraceDeleted, ValueTraceEscaped, ValueTraceInit, ValueTraceInitStarArgs, ValueTraceInitStarDict, ValueTraceLoopComplete, ValueTraceLoopIncomplete, ValueTraceMerge, ValueTraceUninit, ValueTraceUnknown, ) signalChange = None @contextmanager def withChangeIndicationsTo(signal_change): """Decide where change indications should go to.""" global signalChange # Singleton, pylint: disable=global-statement old = signalChange signalChange = signal_change yield signalChange = old class CollectionUpdateMixin(object): """Mixin to use in every collection to add traces.""" # Mixins are not allow to specify slots. __slots__ = () def hasVariableTrace(self, variable, version): return (variable, version) in self.variable_traces def getVariableTrace(self, variable, version): return self.variable_traces[(variable, version)] def getVariableTraces(self, variable): result = [] for key, variable_trace in iterItems(self.variable_traces): candidate = key[0] if variable is candidate: result.append(variable_trace) return result def getVariableTracesAll(self): return self.variable_traces def addVariableTrace(self, variable, version, trace): key = variable, version assert key not in self.variable_traces, (key, self) self.variable_traces[key] = trace def addVariableMergeMultipleTrace(self, variable, traces): version = variable.allocateTargetNumber() trace_merge = ValueTraceMerge(traces) self.addVariableTrace(variable, version, trace_merge) return version class CollectionStartpointMixin(CollectionUpdateMixin): """Mixin to use in start points of collections. These are modules, functions, etc. typically entry points. """ # Mixins are not allow to specify slots, pylint: disable=assigning-non-slot __slots__ = () # Many things are traced def __init__(self): # Variable assignments performed in here, last issued number, only used # to determine the next number that should be used for a new assignment. self.variable_versions = {} # The full trace of a variable with a version for the function or module # this is. self.variable_traces = {} self.break_collections = None self.continue_collections = None self.return_collections = None self.exception_collections = None self.outline_functions = None def getLoopBreakCollections(self): return self.break_collections def onLoopBreak(self, collection=None): if collection is None: collection = self self.break_collections.append( TraceCollectionBranch(parent=collection, name="loop break") ) def getLoopContinueCollections(self): return self.continue_collections def onLoopContinue(self, collection=None): if collection is None: collection = self self.continue_collections.append( TraceCollectionBranch(parent=collection, name="loop continue") ) def onFunctionReturn(self, collection=None): if collection is None: collection = self if self.return_collections is not None: self.return_collections.append( TraceCollectionBranch(parent=collection, name="return") ) def onExceptionRaiseExit(self, raisable_exceptions, collection=None): """Indicate to the trace collection what exceptions may have occurred. Args: raisable_exception: Currently ignored, one or more exceptions that could occur, e.g. "BaseException". collection: To pass the collection that will be the parent Notes: Currently this is unused. Passing "collection" as an argument, so we know the original collection to attach the branch to, is maybe not the most clever way to do this We also might want to specialize functions for specific exceptions, there is little point in providing BaseException as an argument in so many places. The actual storage of the exceptions that can occur is currently missing entirely. We just use this to detect "any exception" by not being empty. """ # TODO: We might want to track per exception, pylint: disable=unused-argument if collection is None: collection = self if self.exception_collections is not None: self.exception_collections.append( TraceCollectionBranch(parent=collection, name="exception") ) def getFunctionReturnCollections(self): return self.return_collections def getExceptionRaiseCollections(self): return self.exception_collections def hasEmptyTraces(self, variable): # TODO: Combine these steps into one for performance gains. traces = self.getVariableTraces(variable) return areEmptyTraces(traces) def hasReadOnlyTraces(self, variable): # TODO: Combine these steps into one for performance gains. traces = self.getVariableTraces(variable) return areReadOnlyTraces(traces) def initVariableUnknown(self, variable): trace = ValueTraceUnknown(owner=self.owner, previous=None) self.addVariableTrace(variable, 0, trace) return trace def initVariableModule(self, variable): trace = ValueTraceUnknown(owner=self.owner, previous=None) self.addVariableTrace(variable, 0, trace) return trace def _initVariableInit(self, variable): trace = ValueTraceInit(self.owner) self.addVariableTrace(variable, 0, trace) return trace def _initVariableInitStarArgs(self, variable): trace = ValueTraceInitStarArgs(self.owner) self.addVariableTrace(variable, 0, trace) return trace def _initVariableInitStarDict(self, variable): trace = ValueTraceInitStarDict(self.owner) self.addVariableTrace(variable, 0, trace) return trace def _initVariableUninit(self, variable): trace = ValueTraceUninit(owner=self.owner, previous=None) self.addVariableTrace(variable, 0, trace) return trace def updateVariablesFromCollection(self, old_collection, source_ref): Variables.updateVariablesFromCollection(old_collection, self, source_ref) @contextlib.contextmanager def makeAbortStackContext( self, catch_breaks, catch_continues, catch_returns, catch_exceptions ): if catch_breaks: old_break_collections = self.break_collections self.break_collections = [] if catch_continues: old_continue_collections = self.continue_collections self.continue_collections = [] if catch_returns: old_return_collections = self.return_collections self.return_collections = [] if catch_exceptions: old_exception_collections = self.exception_collections self.exception_collections = [] yield if catch_breaks: self.break_collections = old_break_collections if catch_continues: self.continue_collections = old_continue_collections if catch_returns: self.return_collections = old_return_collections if catch_exceptions: self.exception_collections = old_exception_collections def initVariable(self, variable): if variable.isParameterVariable(): # TODO: That's not happening, maybe just assert against it. result = self._initVariableInit(variable) elif variable.isLocalVariable(): result = self._initVariableUninit(variable) elif variable.isModuleVariable(): result = self.initVariableModule(variable) elif variable.isTempVariable(): result = self._initVariableUninit(variable) elif variable.isLocalsDictVariable(): if variable.getOwner().getTypeShape() is tshape_dict: result = self._initVariableUninit(variable) else: result = self.initVariableUnknown(variable) else: assert False, variable return result def addOutlineFunction(self, outline): if self.outline_functions is None: self.outline_functions = [outline] else: self.outline_functions.append(outline) def getOutlineFunctions(self): return self.outline_functions def onLocalsDictEscaped(self, locals_scope): if locals_scope is not None: for variable in locals_scope.variables.values(): self.markActiveVariableAsEscaped(variable) # TODO: Limit to the scope. for variable in self.getActiveVariables(): if variable.isTempVariable() or variable.isModuleVariable(): continue self.markActiveVariableAsEscaped(variable) class TraceCollectionBase(object): """This contains for logic for maintaining active traces. They are kept for "variable" and versions. """ __slots__ = ("owner", "parent", "name", "value_states", "variable_actives") if isCountingInstances(): __del__ = counted_del() @counted_init def __init__(self, owner, name, parent): self.owner = owner self.parent = parent self.name = name # Value state extra information per node. self.value_states = {} # Currently active values in the tracing. self.variable_actives = {} def __repr__(self): return "<%s for %s at 0x%x>" % (self.__class__.__name__, self.name, id(self)) def getOwner(self): return self.owner def getVariableCurrentTrace(self, variable): """Get the current value trace associated to this variable It is also created on the fly if necessary. We create them lazy so to keep the tracing branches minimal where possible. """ return self.getVariableTrace( variable=variable, version=self._getCurrentVariableVersion(variable) ) def markCurrentVariableTrace(self, variable, version): self.variable_actives[variable] = version def _getCurrentVariableVersion(self, variable): try: return self.variable_actives[variable] except KeyError: # Initialize variables on the fly. if not self.hasVariableTrace(variable, 0): self.initVariable(variable) self.markCurrentVariableTrace(variable, 0) return self.variable_actives[variable] def getActiveVariables(self): return self.variable_actives.keys() def markActiveVariableAsEscaped(self, variable): current = self.getVariableCurrentTrace(variable) if not current.isEscapeOrUnknownOrUninitTrace(): version = variable.allocateTargetNumber() self.addVariableTrace( variable, version, ValueTraceEscaped(owner=self.owner, previous=current), ) self.markCurrentVariableTrace(variable, version) def markActiveVariableAsUnknown(self, variable): current = self.getVariableCurrentTrace(variable) if not current.isUnknownTrace(): version = variable.allocateTargetNumber() self.addVariableTrace( variable, version, ValueTraceUnknown(owner=self.owner, previous=current), ) self.markCurrentVariableTrace(variable, version) def markActiveVariableAsLoopMerge( self, loop_node, current, variable, shapes, incomplete ): if incomplete: result = ValueTraceLoopIncomplete(loop_node, current, shapes) else: # TODO: Empty is a missing optimization somewhere, but it also happens that # a variable is getting released in a loop. # assert shapes, (variable, current) if not shapes: shapes.add(tshape_uninit) result = ValueTraceLoopComplete(loop_node, current, shapes) version = variable.allocateTargetNumber() self.addVariableTrace(variable, version, result) self.markCurrentVariableTrace(variable, version) return result def markActiveVariablesAsEscaped(self): for variable in self.getActiveVariables(): if variable.isTempVariable(): continue self.markActiveVariableAsEscaped(variable) def markActiveVariablesAsUnknown(self): for variable in self.getActiveVariables(): if variable.isTempVariable(): continue self.markActiveVariableAsUnknown(variable) @staticmethod def signalChange(tags, source_ref, message): # This is monkey patched from another module. pylint: disable=I0021,not-callable signalChange(tags, source_ref, message) def onUsedFunction(self, function_body): owning_module = function_body.getParentModule() # Make sure the owning module is added to the used set. This is most # important for helper functions, or modules, which otherwise have # become unused. addUsedModule( module=owning_module, using_module=None, usage_tag="function", reason="Function %s" % self.name, source_ref=owning_module.source_ref, ) needs_visit = owning_module.addUsedFunction(function_body) if needs_visit: function_body.computeFunctionRaw(self) @staticmethod def mustAlias(a, b): if a.isExpressionVariableRef() and b.isExpressionVariableRef(): return a.getVariable() is b.getVariable() return False @staticmethod def mustNotAlias(a, b): # TODO: not yet really implemented if a.isExpressionConstantRef() and b.isExpressionConstantRef(): if a.isMutable() or b.isMutable(): return True return False def onControlFlowEscape(self, node): # TODO: One day, we should trace which nodes exactly cause a variable # to be considered escaped, pylint: disable=unused-argument for variable in self.getActiveVariables(): # TODO: Move this to the variable, and prepare and cache it better for # compile time savings. if variable.isModuleVariable(): self.markActiveVariableAsUnknown(variable) elif variable.isLocalVariable(): if ( str is not bytes and variable.hasWritersOutsideOf(self.owner) is not False ): self.markActiveVariableAsUnknown(variable) elif variable.hasAccessesOutsideOf(self.owner) is not False: self.markActiveVariableAsEscaped(variable) def removeKnowledge(self, node): if node.isExpressionVariableRef(): if node.variable.isModuleVariable(): self.markActiveVariableAsUnknown(node.variable) else: self.markActiveVariableAsEscaped(node.variable) def onValueEscapeStr(self, node): # TODO: We can ignore these for now. pass def removeAllKnowledge(self): self.markActiveVariablesAsUnknown() def onVariableSet(self, variable, version, assign_node): variable_trace = ValueTraceAssign( owner=self.owner, assign_node=assign_node, previous=self.getVariableCurrentTrace(variable), ) self.addVariableTrace(variable, version, variable_trace) # Make references point to it. self.markCurrentVariableTrace(variable, version) return variable_trace def onVariableDel(self, variable, version, del_node): # Add a new trace, allocating a new version for the variable, and # remember the delete of the current old_trace = self.getVariableCurrentTrace(variable) # TODO: Annotate value content as escaped. variable_trace = ValueTraceDeleted( owner=self.owner, del_node=del_node, previous=old_trace ) # Assign to not initialized again. self.addVariableTrace(variable, version, variable_trace) # Make references point to it. self.markCurrentVariableTrace(variable, version) return variable_trace def onLocalsUsage(self, locals_scope): self.onLocalsDictEscaped(locals_scope) result = [] scope_locals_variables = locals_scope.getLocalsRelevantVariables() for variable in self.getActiveVariables(): if variable.isLocalVariable() and variable in scope_locals_variables: variable_trace = self.getVariableCurrentTrace(variable) variable_trace.addNameUsage() result.append((variable, variable_trace)) return result def onVariableContentEscapes(self, variable): self.markActiveVariableAsEscaped(variable) def onExpression(self, expression, allow_none=False): if expression is None and allow_none: return None assert expression.isExpression(), expression parent = expression.parent assert parent, expression # Now compute this expression, allowing it to replace itself with # something else as part of a local peep hole optimization. r = expression.computeExpressionRaw(trace_collection=self) assert type(r) is tuple, (expression, expression.getVisitableNodes(), r) new_node, change_tags, change_desc = r if change_tags is not None: # This is mostly for tracing and indication that a change occurred # and it may be interesting to look again. self.signalChange(change_tags, expression.getSourceReference(), change_desc) if new_node is not expression: parent.replaceChild(expression, new_node) return new_node def onStatement(self, statement): try: assert statement.isStatement(), statement new_statement, change_tags, change_desc = statement.computeStatement(self) # print new_statement, change_tags, change_desc if new_statement is not statement: self.signalChange( change_tags, statement.getSourceReference(), change_desc ) return new_statement except Exception: Tracing.printError( "Problem with statement at %s:\n-> %s" % ( statement.source_ref.getAsString(), readSourceLine(statement.source_ref), ) ) raise def computedStatementResult(self, statement, change_tags, change_desc): """Make sure the replacement statement is computed. Use this when a replacement expression needs to be seen by the trace collection and be computed, without causing any duplication, but where otherwise there would be loss of annotated effects. This may e.g. be true for nodes that need an initial run to know their exception result and type shape. """ # Need to compute the replacement still. new_statement = statement.computeStatement(self) if new_statement[0] is not statement: # Signal intermediate result as well. self.signalChange(change_tags, statement.getSourceReference(), change_desc) return new_statement else: return statement, change_tags, change_desc def computedExpressionResult(self, expression, change_tags, change_desc): """Make sure the replacement expression is computed. Use this when a replacement expression needs to be seen by the trace collection and be computed, without causing any duplication, but where otherwise there would be loss of annotated effects. This may e.g. be true for nodes that need an initial run to know their exception result and type shape. """ # Need to compute the replacement still. new_expression = expression.computeExpression(self) if new_expression[0] is not expression: # Signal intermediate result as well. self.signalChange(change_tags, expression.getSourceReference(), change_desc) return new_expression else: return expression, change_tags, change_desc def computedExpressionResultRaw(self, expression, change_tags, change_desc): """Make sure the replacement expression is computed. Use this when a replacement expression needs to be seen by the trace collection and be computed, without causing any duplication, but where otherwise there would be loss of annotated effects. This may e.g. be true for nodes that need an initial run to know their exception result and type shape. This is for raw, i.e. subnodes are not yet computed automatically. """ # Need to compute the replacement still. new_expression = expression.computeExpressionRaw(self) if new_expression[0] is not expression: # Signal intermediate result as well. self.signalChange(change_tags, expression.getSourceReference(), change_desc) return new_expression else: return expression, change_tags, change_desc def mergeBranches(self, collection_yes, collection_no): """Merge two alternative branches into this trace. This is mostly for merging conditional branches, or other ways of having alternative control flow. This deals with up to two alternative branches to both change this collection. """ # Many branches due to inlining the actual merge and preparing it # pylint: disable=too-many-branches if collection_yes is None: if collection_no is not None: # Handle one branch case, we need to merge versions backwards as # they may make themselves obsolete. collection1 = self collection2 = collection_no else: # Refuse to do stupid work return elif collection_no is None: # Handle one branch case, we need to merge versions backwards as # they may make themselves obsolete. collection1 = self collection2 = collection_yes else: # Handle two branch case, they may or may not do the same things. collection1 = collection_yes collection2 = collection_no variable_versions = {} for variable, version in iterItems(collection1.variable_actives): variable_versions[variable] = version for variable, version in iterItems(collection2.variable_actives): if variable not in variable_versions: variable_versions[variable] = 0, version else: other = variable_versions[variable] if other != version: variable_versions[variable] = other, version else: variable_versions[variable] = other for variable in variable_versions: if variable not in collection2.variable_actives: variable_versions[variable] = variable_versions[variable], 0 self.variable_actives = {} for variable, versions in iterItems(variable_versions): if type(versions) is tuple: trace1 = self.getVariableTrace(variable, versions[0]) trace2 = self.getVariableTrace(variable, versions[1]) if trace1.isEscapeTrace() and trace1.previous is trace2: version = versions[0] elif trace2 is trace1.isEscapeTrace() and trace2.previous is trace1: version = versions[1] else: version = self.addVariableMergeMultipleTrace( variable=variable, traces=( trace1, trace2, ), ) else: version = versions self.markCurrentVariableTrace(variable, version) def mergeMultipleBranches(self, collections): # This one is really complex, pylint: disable=too-many-branches assert collections # Optimize for length 1, which is trivial merge and needs not a # lot of work, and length 2 has dedicated code as it's so frequent. merge_size = len(collections) if merge_size == 1: self.replaceBranch(collections[0]) return elif merge_size == 2: return self.mergeBranches(*collections) # print("Enter mergeMultipleBranches", len(collections)) with TimerReport( message="Running merge for %s took %%.2f seconds" % collections, decider=lambda: 0, ): variable_versions = defaultdict(OrderedSet) for collection in collections: for variable, version in iterItems(collection.variable_actives): variable_versions[variable].add(version) for collection in collections: for variable, versions in iterItems(variable_versions): if variable not in collection.variable_actives: versions.add(0) self.variable_actives = {} for variable, versions in iterItems(variable_versions): if len(versions) == 1: (version,) = versions else: traces = [] escaped = [] winner_version = None for version in versions: trace = self.getVariableTrace(variable, version) if trace.isEscapeTrace(): winner_version = version escaped_trace = trace.previous if escaped_trace in traces: traces.remove(trace.previous) escaped.append(escaped) traces.append(trace) else: if trace not in escaped: traces.append(trace) if len(traces) == 1: version = winner_version assert winner_version is not None else: version = self.addVariableMergeMultipleTrace( variable=variable, traces=tuple(traces) ) self.markCurrentVariableTrace(variable, version) # print("Leave mergeMultipleBranches", len(collections)) def replaceBranch(self, collection_replace): self.variable_actives.update(collection_replace.variable_actives) collection_replace.variable_actives = None def onLoopBreak(self, collection=None): if collection is None: collection = self return self.parent.onLoopBreak(collection) def onLoopContinue(self, collection=None): if collection is None: collection = self return self.parent.onLoopContinue(collection) def onFunctionReturn(self, collection=None): if collection is None: collection = self return self.parent.onFunctionReturn(collection) def onExceptionRaiseExit(self, raisable_exceptions, collection=None): if collection is None: collection = self return self.parent.onExceptionRaiseExit(raisable_exceptions, collection) def getLoopBreakCollections(self): return self.parent.getLoopBreakCollections() def getLoopContinueCollections(self): return self.parent.getLoopContinueCollections() def getFunctionReturnCollections(self): return self.parent.getFunctionReturnCollections() def getExceptionRaiseCollections(self): return self.parent.getExceptionRaiseCollections() def makeAbortStackContext( self, catch_breaks, catch_continues, catch_returns, catch_exceptions ): return self.parent.makeAbortStackContext( catch_breaks=catch_breaks, catch_continues=catch_continues, catch_returns=catch_returns, catch_exceptions=catch_exceptions, ) def onLocalsDictEscaped(self, locals_scope): self.parent.onLocalsDictEscaped(locals_scope) def getCompileTimeComputationResult( self, node, computation, description, user_provided=False ): new_node, change_tags, message = getComputationResult( node=node, computation=computation, description=description, user_provided=user_provided, ) if change_tags == "new_raise": self.onExceptionRaiseExit(BaseException) return new_node, change_tags, message def getIteratorNextCount(self, iter_node): return self.value_states.get(iter_node) def initIteratorValue(self, iter_node): # TODO: More complex state information will be needed eventually. self.value_states[iter_node] = 0 def onIteratorNext(self, iter_node): if iter_node in self.value_states: self.value_states[iter_node] += 1 def resetValueStates(self): for key in self.value_states: self.value_states[key] = None def addOutlineFunction(self, outline): self.parent.addOutlineFunction(outline) def getVeryTrustedModuleVariables(self): return self.parent.getVeryTrustedModuleVariables() class TraceCollectionBranch(CollectionUpdateMixin, TraceCollectionBase): __slots__ = ("variable_traces",) def __init__(self, name, parent): TraceCollectionBase.__init__(self, owner=parent.owner, name=name, parent=parent) # Detach from others self.variable_actives = dict(parent.variable_actives) # For quick access without going to parent. self.variable_traces = parent.variable_traces def computeBranch(self, branch): if branch.isStatementsSequence(): result = branch.computeStatementsSequence(trace_collection=self) if result is not branch: branch.parent.replaceChild(branch, result) else: self.onExpression(expression=branch) def initVariable(self, variable): variable_trace = self.parent.initVariable(variable) self.variable_actives[variable] = 0 return variable_trace def dumpTraces(self): Tracing.printSeparator() self.parent.dumpTraces() Tracing.printSeparator() def dumpActiveTraces(self): Tracing.printSeparator() Tracing.printLine("Active are:") for variable, _version in sorted(self.variable_actives.iteritems()): self.getVariableCurrentTrace(variable).dump() Tracing.printSeparator() class TraceCollectionFunction(CollectionStartpointMixin, TraceCollectionBase): __slots__ = ( "variable_versions", "variable_traces", "break_collections", "continue_collections", "return_collections", "exception_collections", "outline_functions", "very_trusted_module_variables", ) def __init__(self, parent, function_body): assert ( function_body.isExpressionFunctionBody() or function_body.isExpressionGeneratorObjectBody() or function_body.isExpressionCoroutineObjectBody() or function_body.isExpressionAsyncgenObjectBody() ), function_body CollectionStartpointMixin.__init__(self) TraceCollectionBase.__init__( self, owner=function_body, name="collection_" + function_body.getCodeName(), parent=parent, ) if parent is not None: self.very_trusted_module_variables = parent.getVeryTrustedModuleVariables() else: self.very_trusted_module_variables = () if function_body.isExpressionFunctionBody(): parameters = function_body.getParameters() for parameter_variable in parameters.getTopLevelVariables(): self._initVariableInit(parameter_variable) self.variable_actives[parameter_variable] = 0 list_star_variable = parameters.getListStarArgVariable() if list_star_variable is not None: self._initVariableInitStarArgs(list_star_variable) self.variable_actives[list_star_variable] = 0 dict_star_variable = parameters.getDictStarArgVariable() if dict_star_variable is not None: self._initVariableInitStarDict(dict_star_variable) self.variable_actives[dict_star_variable] = 0 for closure_variable in function_body.getClosureVariables(): self.initVariableUnknown(closure_variable) self.variable_actives[closure_variable] = 0 # TODO: Have special function type for exec functions stuff. locals_scope = function_body.getLocalsScope() if locals_scope is not None: if not locals_scope.isMarkedForPropagation(): for locals_dict_variable in locals_scope.variables.values(): self._initVariableUninit(locals_dict_variable) else: function_body.locals_scope = None def initVariableModule(self, variable): trusted_node = self.very_trusted_module_variables.get(variable) if trusted_node is None: return CollectionStartpointMixin.initVariableModule(self, variable) assign_trace = ValueTraceAssign( self.owner, assign_node=trusted_node.getParent(), previous=None ) # This is rare enough to not need a more optimized code. self.addVariableTrace(variable, 0, assign_trace) self.markActiveVariableAsEscaped(variable) return self.getVariableCurrentTrace(variable) class TraceCollectionPureFunction(TraceCollectionFunction): """Pure functions don't feed their parent.""" __slots__ = ("used_functions",) def __init__(self, function_body): TraceCollectionFunction.__init__(self, parent=None, function_body=function_body) self.used_functions = OrderedSet() def getUsedFunctions(self): return self.used_functions def onUsedFunction(self, function_body): self.used_functions.add(function_body) class TraceCollectionModule(CollectionStartpointMixin, TraceCollectionBase): __slots__ = ( "variable_versions", "variable_traces", "break_collections", "continue_collections", "return_collections", "exception_collections", "outline_functions", "very_trusted_module_variables", ) def __init__(self, module, very_trusted_module_variables): assert module.isCompiledPythonModule(), module CollectionStartpointMixin.__init__(self) TraceCollectionBase.__init__( self, owner=module, name="module:" + module.getFullName(), parent=None ) self.very_trusted_module_variables = very_trusted_module_variables def getVeryTrustedModuleVariables(self): return self.very_trusted_module_variables def updateVeryTrustedModuleVariables(self, very_trusted_module_variables): result = self.very_trusted_module_variables != very_trusted_module_variables self.very_trusted_module_variables = very_trusted_module_variables return result # TODO: This should not exist, but be part of decision at the time these are collected. def areEmptyTraces(variable_traces): """Do these traces contain any writes or accesses.""" # Many cases immediately return, that is how we do it here, # pylint: disable=too-many-branches,too-many-return-statements for variable_trace in variable_traces: if variable_trace.isAssignTrace(): return False elif variable_trace.isInitTrace(): return False elif variable_trace.isDeletedTrace(): # A "del" statement can do this, and needs to prevent variable # from being removed. return False elif variable_trace.isUninitTrace(): if variable_trace.getUsageCount(): # Checking definite is enough, the merges, we shall see # them as well. return False elif variable_trace.isUnknownTrace(): if variable_trace.getUsageCount(): # Checking definite is enough, the merges, we shall see # them as well. return False elif variable_trace.isEscapeTrace(): if variable_trace.getUsageCount(): # Checking definite is enough, the merges, we shall see # them as well. return False elif variable_trace.isMergeTrace(): if variable_trace.getUsageCount(): # Checking definite is enough, the merges, we shall see # them as well. return False elif variable_trace.isLoopTrace(): return False else: assert False, variable_trace return True def areReadOnlyTraces(variable_traces): """Do these traces contain any writes.""" # Many cases immediately return, that is how we do it here, for variable_trace in variable_traces: if variable_trace.isAssignTrace(): return False elif variable_trace.isInitTrace(): pass elif variable_trace.isDeletedTrace(): # A "del" statement can do this, and needs to prevent variable # from being not released. return False elif variable_trace.isUninitTrace(): pass elif variable_trace.isUnknownTrace(): return False elif variable_trace.isEscapeTrace(): pass elif variable_trace.isMergeTrace(): pass elif variable_trace.isLoopTrace(): pass else: assert False, variable_trace return True Nuitka-0.6.19.1/nuitka/optimizations/OptimizeBuiltinCalls.py0000600000372100037210000014142514166627112031162 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Optimize calls to built-in references to specific built-in calls. For built-in name references, we check if it's one of the supported built-in types, and then specialize for the ones, where it makes sense. """ from nuitka.__past__ import xrange from nuitka.Errors import NuitkaAssumptionError from nuitka.nodes.AssignNodes import ( StatementAssignmentVariable, StatementDelVariable, ) from nuitka.nodes.AttributeNodes import ( ExpressionBuiltinGetattr, ExpressionBuiltinHasattr, ExpressionBuiltinSetattr, makeExpressionAttributeLookup, ) from nuitka.nodes.BuiltinAllNodes import ExpressionBuiltinAll from nuitka.nodes.BuiltinAnyNodes import ExpressionBuiltinAny from nuitka.nodes.BuiltinComplexNodes import ( ExpressionBuiltinComplex1, ExpressionBuiltinComplex2, ) from nuitka.nodes.BuiltinDecodingNodes import ( ExpressionBuiltinChr, ExpressionBuiltinOrd, ) from nuitka.nodes.BuiltinDecoratorNodes import ( ExpressionBuiltinClassmethod, ExpressionBuiltinStaticmethod, ) from nuitka.nodes.BuiltinDictNodes import ExpressionBuiltinDict from nuitka.nodes.BuiltinFormatNodes import ( ExpressionBuiltinAscii, ExpressionBuiltinBin, ExpressionBuiltinFormat, ExpressionBuiltinHex, ExpressionBuiltinId, ExpressionBuiltinOct, ) from nuitka.nodes.BuiltinHashNodes import ExpressionBuiltinHash from nuitka.nodes.BuiltinIntegerNodes import ( ExpressionBuiltinInt1, ExpressionBuiltinInt2, ) from nuitka.nodes.BuiltinIteratorNodes import ( ExpressionBuiltinIter1, ExpressionBuiltinIter2, ) from nuitka.nodes.BuiltinLenNodes import ExpressionBuiltinLen from nuitka.nodes.BuiltinNextNodes import ( ExpressionBuiltinNext1, ExpressionBuiltinNext2, ) from nuitka.nodes.BuiltinOpenNodes import ExpressionBuiltinOpen from nuitka.nodes.BuiltinRangeNodes import ( ExpressionBuiltinRange1, ExpressionBuiltinRange2, ExpressionBuiltinRange3, ExpressionBuiltinXrange1, ExpressionBuiltinXrange2, ExpressionBuiltinXrange3, ) from nuitka.nodes.BuiltinRefNodes import ( ExpressionBuiltinAnonymousRef, makeExpressionBuiltinTypeRef, ) from nuitka.nodes.BuiltinSumNodes import ( ExpressionBuiltinSum1, ExpressionBuiltinSum2, ) from nuitka.nodes.BuiltinTypeNodes import ( ExpressionBuiltinBool, ExpressionBuiltinBytearray1, ExpressionBuiltinBytearray3, ExpressionBuiltinFloat, ExpressionBuiltinFrozenset, ExpressionBuiltinList, ExpressionBuiltinSet, ExpressionBuiltinStrP2, ExpressionBuiltinStrP3, ExpressionBuiltinTuple, ExpressionBuiltinUnicodeP2, ) from nuitka.nodes.BuiltinVarsNodes import ExpressionBuiltinVars from nuitka.nodes.CallNodes import makeExpressionCall from nuitka.nodes.ClassNodes import ExpressionBuiltinType3 from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs from nuitka.nodes.ConditionalNodes import ( ExpressionConditional, makeStatementConditional, ) from nuitka.nodes.ConstantRefNodes import makeConstantRefNode from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTupleOrConstant from nuitka.nodes.ExecEvalNodes import ( ExpressionBuiltinCompile, ExpressionBuiltinEval, ) from nuitka.nodes.GlobalsLocalsNodes import ( ExpressionBuiltinDir1, ExpressionBuiltinGlobals, ) from nuitka.nodes.ImportNodes import ExpressionBuiltinImport from nuitka.nodes.NodeMakingHelpers import ( makeConstantReplacementNode, makeExpressionBuiltinLocals, makeRaiseExceptionReplacementExpression, makeRaiseExceptionReplacementExpressionFromInstance, ) from nuitka.nodes.OperatorNodes import ExpressionOperationBinaryDivmod from nuitka.nodes.OperatorNodesUnary import ( ExpressionOperationNot, ExpressionOperationUnaryAbs, ExpressionOperationUnaryRepr, ) from nuitka.nodes.OutlineNodes import ExpressionOutlineBody from nuitka.nodes.ReturnNodes import makeStatementReturn from nuitka.nodes.SliceNodes import makeExpressionBuiltinSlice from nuitka.nodes.TypeNodes import ( ExpressionBuiltinIsinstance, ExpressionBuiltinIssubclass, ExpressionBuiltinSuper0, ExpressionBuiltinSuper2, ExpressionBuiltinType1, ) from nuitka.nodes.VariableRefNodes import ( ExpressionTempVariableRef, ExpressionVariableRef, ) from nuitka.PythonVersions import python_version from nuitka.specs import BuiltinParameterSpecs from nuitka.tree.ReformulationExecStatements import wrapEvalGlobalsAndLocals from nuitka.tree.ReformulationTryFinallyStatements import ( makeTryFinallyStatement, ) from nuitka.tree.TreeHelpers import ( makeCallNode, makeStatementsSequence, makeStatementsSequenceFromStatement, ) def dir_extractor(node): locals_scope = node.subnode_called.getLocalsScope() def buildDirEmptyCase(source_ref): source = makeExpressionBuiltinLocals( locals_scope=locals_scope, source_ref=source_ref ) result = makeCallNode( makeExpressionAttributeLookup( expression=source, attribute_name="keys", source_ref=source_ref ), source_ref, ) # For Python3, keys doesn't really return values, but instead a handle # only, but we want it to be a list. if python_version >= 0x300: result = ExpressionBuiltinList(value=result, source_ref=source_ref) return result return BuiltinParameterSpecs.extractBuiltinArgs( node=node, # TODO: Needs locals_scope attached. builtin_class=ExpressionBuiltinDir1, builtin_spec=BuiltinParameterSpecs.builtin_dir_spec, empty_special_class=buildDirEmptyCase, ) def vars_extractor(node): locals_scope = node.subnode_called.getLocalsScope() def selectVarsEmptyClass(source_ref): return makeExpressionBuiltinLocals( locals_scope=locals_scope, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, # TODO: Needs locals_cope attached builtin_class=ExpressionBuiltinVars, builtin_spec=BuiltinParameterSpecs.builtin_vars_spec, empty_special_class=selectVarsEmptyClass, ) def import_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinImport, builtin_spec=BuiltinParameterSpecs.builtin_import_spec, ) def type_extractor(node): args = node.subnode_args if args is None: iter_length = 0 else: iter_length = args.getIterationLength() if iter_length == 1: return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinType1, builtin_spec=BuiltinParameterSpecs.builtin_type1_spec, ) elif iter_length == 3: return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinType3, builtin_spec=BuiltinParameterSpecs.builtin_type3_spec, ) else: return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError("type() takes 1 or 3 arguments") ) def iter_extractor(node): def wrapIterCreation(callable_arg, sentinel, source_ref): if sentinel is None: return ExpressionBuiltinIter1(value=callable_arg, source_ref=source_ref) else: return ExpressionBuiltinIter2( callable_arg=callable_arg, sentinel=sentinel, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapIterCreation, builtin_spec=BuiltinParameterSpecs.builtin_iter_spec, ) def next_extractor(node): # Split up next with and without defaults, they are not going to behave # really very similar. def selectNextBuiltinClass(iterator, default, source_ref): if default is None: return ExpressionBuiltinNext1(value=iterator, source_ref=source_ref) else: return ExpressionBuiltinNext2( iterator=iterator, default=default, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectNextBuiltinClass, builtin_spec=BuiltinParameterSpecs.builtin_next_spec, ) def sum_extractor(node): # Split up sumwith and without start value, one is much easier. def selectSumBuiltinClass(sequence, start, source_ref): if start is None: return ExpressionBuiltinSum1(sequence=sequence, source_ref=source_ref) else: return ExpressionBuiltinSum2( sequence=sequence, start=start, source_ref=source_ref ) def makeSum0(source_ref): # pylint: disable=unused-argument return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError( "sum expected at least 1 arguments, got 0" if python_version < 0x380 else "sum() takes at least 1 positional argument (0 given)" ), ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectSumBuiltinClass, builtin_spec=BuiltinParameterSpecs.builtin_sum_spec, empty_special_class=makeSum0, ) def dict_extractor(node): # The "dict" built-in is a bit strange in that it accepts a position # parameter, or not, but won't have a default value. def wrapExpressionBuiltinDictCreation(positional_args, dict_star_arg, source_ref): if positional_args: # Only one allowed, the spec converted too many into an exception. (pos_arg,) = positional_args else: pos_arg = None return ExpressionBuiltinDict( pos_arg=pos_arg, pairs=dict_star_arg, source_ref=source_ref, ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapExpressionBuiltinDictCreation, builtin_spec=BuiltinParameterSpecs.builtin_dict_spec, ) def chr_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinChr, builtin_spec=BuiltinParameterSpecs.builtin_chr_spec, ) def ord_extractor(node): def makeOrd0(source_ref): # pylint: disable=unused-argument return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError("ord() takes exactly one argument (0 given)"), ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinOrd, builtin_spec=BuiltinParameterSpecs.builtin_ord_spec, empty_special_class=makeOrd0, ) def bin_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinBin, builtin_spec=BuiltinParameterSpecs.builtin_bin_spec, ) def oct_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinOct, builtin_spec=BuiltinParameterSpecs.builtin_oct_spec, ) def hex_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinHex, builtin_spec=BuiltinParameterSpecs.builtin_hex_spec, ) def id_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinId, builtin_spec=BuiltinParameterSpecs.builtin_id_spec, ) def repr_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionOperationUnaryRepr, builtin_spec=BuiltinParameterSpecs.builtin_repr_spec, ) if python_version >= 0x300: def ascii_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinAscii, builtin_spec=BuiltinParameterSpecs.builtin_repr_spec, ) def range_extractor(node): def selectRangeBuiltin(low, high, step, source_ref): if high is None: return ExpressionBuiltinRange1(low=low, source_ref=source_ref) elif step is None: return ExpressionBuiltinRange2(low=low, high=high, source_ref=source_ref) else: return ExpressionBuiltinRange3( low=low, high=high, step=step, source_ref=source_ref ) def makeRange0(source_ref): # pylint: disable=unused-argument try: range() except Exception as e: # We want to broad here, pylint: disable=broad-except return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=e ) else: raise NuitkaAssumptionError("range without argument is expected to raise") return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectRangeBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_range_spec, empty_special_class=makeRange0, ) def xrange_extractor(node): def selectXrangeBuiltin(low, high, step, source_ref): if high is None: return ExpressionBuiltinXrange1(low=low, source_ref=source_ref) elif step is None: return ExpressionBuiltinXrange2(low=low, high=high, source_ref=source_ref) else: return ExpressionBuiltinXrange3( low=low, high=high, step=step, source_ref=source_ref ) def makeXrange0(source_ref): # pylint: disable=unused-argument try: xrange() except Exception as e: # We want to broad here, pylint: disable=broad-except return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=e ) else: raise NuitkaAssumptionError("range without argument is expected to raise") return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectXrangeBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_xrange_spec, empty_special_class=makeXrange0, ) def len_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinLen, builtin_spec=BuiltinParameterSpecs.builtin_len_spec, ) def all_extractor(node): # pylint: disable=unused-argument def makeAll0(source_ref): exception_message = "all() takes exactly one argument (0 given)" return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError(exception_message) ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinAll, builtin_spec=BuiltinParameterSpecs.builtin_all_spec, empty_special_class=makeAll0, ) def abs_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionOperationUnaryAbs, builtin_spec=BuiltinParameterSpecs.builtin_abs_spec, ) def any_extractor(node): # pylint: disable=unused-argument def makeAny0(source_ref): exception_message = "any() takes exactly one argument (0 given)" return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError(exception_message) ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinAny, builtin_spec=BuiltinParameterSpecs.builtin_any_spec, empty_special_class=makeAny0, ) def tuple_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinTuple, builtin_spec=BuiltinParameterSpecs.builtin_tuple_spec, ) def list_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinList, builtin_spec=BuiltinParameterSpecs.builtin_list_spec, ) def set_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinSet, builtin_spec=BuiltinParameterSpecs.builtin_set_spec, ) def frozenset_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinFrozenset, builtin_spec=BuiltinParameterSpecs.builtin_frozenset_spec, ) def float_extractor(node): def makeFloat0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=float(), node=node, user_provided=False ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinFloat, builtin_spec=BuiltinParameterSpecs.builtin_float_spec, empty_special_class=makeFloat0, ) def complex_extractor(node): def makeComplex0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=complex(), node=node, user_provided=False ) def selectComplexBuiltin(real, imag, source_ref): if imag is None: return ExpressionBuiltinComplex1(value=real, source_ref=source_ref) else: return ExpressionBuiltinComplex2( real=real, imag=imag, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectComplexBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_complex_spec, empty_special_class=makeComplex0, ) def str_extractor(node): builtin_class = ExpressionBuiltinStrP2 if str is bytes else ExpressionBuiltinStrP3 return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=builtin_class, builtin_spec=builtin_class.builtin_spec, ) if python_version < 0x300: def unicode_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinUnicodeP2, builtin_spec=ExpressionBuiltinUnicodeP2.builtin_spec, ) else: from nuitka.nodes.BuiltinTypeNodes import ( ExpressionBuiltinBytes1, ExpressionBuiltinBytes3, ) def bytes_extractor(node): def makeBytes0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=bytes(), node=node, user_provided=False ) def selectBytesBuiltin(string, encoding, errors, source_ref): if encoding is None and errors is None: return ExpressionBuiltinBytes1(value=string, source_ref=source_ref) else: return ExpressionBuiltinBytes3( value=string, encoding=encoding, errors=errors, source_ref=source_ref, ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectBytesBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_bytes_p3_spec, empty_special_class=makeBytes0, ) def bool_extractor(node): def makeBool0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=bool(), node=node, user_provided=False ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinBool, builtin_spec=BuiltinParameterSpecs.builtin_bool_spec, empty_special_class=makeBool0, ) def int_extractor(node): def makeInt0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=int(), node=node, user_provided=False ) def selectIntBuiltin(value, base, source_ref): if base is None: return ExpressionBuiltinInt1(value=value, source_ref=source_ref) else: return ExpressionBuiltinInt2(value=value, base=base, source_ref=source_ref) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectIntBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_int_spec, empty_special_class=makeInt0, ) if python_version < 0x300: from nuitka.nodes.BuiltinIntegerNodes import ( ExpressionBuiltinLong1, ExpressionBuiltinLong2, ) def long_extractor(node): def makeLong0(source_ref): # pylint: disable=unused-argument return makeConstantReplacementNode( constant=int(), node=node, user_provided=False ) def selectIntBuiltin(value, base, source_ref): if base is None: return ExpressionBuiltinLong1(value=value, source_ref=source_ref) else: return ExpressionBuiltinLong2( value=value, base=base, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectIntBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_int_spec, empty_special_class=makeLong0, ) def globals_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinGlobals, builtin_spec=BuiltinParameterSpecs.builtin_globals_spec, ) def locals_extractor(node): locals_scope = node.subnode_called.getLocalsScope() def makeLocalsNode(source_ref): return makeExpressionBuiltinLocals( locals_scope=locals_scope, source_ref=source_ref ) # Note: Locals on the module level is really globals. return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=makeLocalsNode, builtin_spec=BuiltinParameterSpecs.builtin_locals_spec, ) if python_version < 0x300: from nuitka.nodes.ExecEvalNodes import ExpressionBuiltinExecfile def execfile_extractor(node): def wrapExpressionBuiltinExecfileCreation( filename, globals_arg, locals_arg, source_ref ): outline_body = ExpressionOutlineBody( provider=node.getParentVariableProvider(), name="execfile_call", source_ref=source_ref, ) globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( provider=node.getParentVariableProvider(), globals_node=globals_arg, locals_node=locals_arg, temp_scope=outline_body.getOutlineTempScope(), source_ref=source_ref, ) tried = makeStatementsSequence( statements=( tried, makeStatementReturn( expression=ExpressionBuiltinExecfile( source_code=makeCallNode( makeExpressionAttributeLookup( expression=ExpressionBuiltinOpen( filename=filename, mode=makeConstantRefNode( constant="rU", source_ref=source_ref ), buffering=None, source_ref=source_ref, ), attribute_name="read", source_ref=source_ref, ), source_ref, ), globals_arg=globals_ref, locals_arg=locals_ref, source_ref=source_ref, ), source_ref=source_ref, ), ), allow_none=False, source_ref=source_ref, ) outline_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outline_body, tried=tried, final=final, source_ref=source_ref, ) ), ) return outline_body return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapExpressionBuiltinExecfileCreation, builtin_spec=BuiltinParameterSpecs.builtin_execfile_spec, ) def eval_extractor(node): def wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref): provider = node.getParentVariableProvider() outline_body = ExpressionOutlineBody( provider=node.getParentVariableProvider(), name="eval_call", source_ref=source_ref, ) globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( provider=provider, globals_node=globals_arg, locals_node=locals_arg, temp_scope=outline_body.getOutlineTempScope(), source_ref=source_ref, ) # The wrapping should not relocate to the "source_ref". assert ( globals_arg is None or globals_ref.getSourceReference() == globals_arg.getSourceReference() ) assert ( locals_arg is None or locals_ref.getSourceReference() == locals_arg.getSourceReference() ) source_variable = outline_body.allocateTempVariable( temp_scope=None, name="source" ) final.setChild( "statements", final.subnode_statements + ( StatementDelVariable( variable=source_variable, tolerant=True, source_ref=source_ref ), ), ) strip_choice = makeConstantRefNode(constant=(" \t",), source_ref=source_ref) if python_version >= 0x300: strip_choice = ExpressionConditional( condition=ExpressionComparisonIs( left=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), source_ref=source_ref, ), right=makeExpressionBuiltinTypeRef( builtin_name="bytes", source_ref=source_ref ), source_ref=source_ref, ), expression_yes=makeConstantRefNode( constant=(b" \t",), source_ref=source_ref ), expression_no=strip_choice, source_ref=source_ref, ) # Source needs some special treatment for eval, if it's a string, it # must be stripped. string_fixup = StatementAssignmentVariable( variable=source_variable, source=makeExpressionCall( called=makeExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), attribute_name="strip", source_ref=source_ref, ), args=strip_choice, # This is a tuple kw=None, source_ref=source_ref, ), source_ref=source_ref, ) acceptable_builtin_types = [ ExpressionBuiltinAnonymousRef(builtin_name="code", source_ref=source_ref) ] if python_version >= 0x270: acceptable_builtin_types.append( makeExpressionBuiltinTypeRef( builtin_name="memoryview", source_ref=source_ref ) ) statements = ( StatementAssignmentVariable( variable=source_variable, source=source, source_ref=source_ref ), makeStatementConditional( condition=ExpressionOperationNot( operand=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), classes=makeExpressionMakeTupleOrConstant( elements=acceptable_builtin_types, user_provided=True, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=string_fixup, no_branch=None, source_ref=source_ref, ), makeStatementReturn( expression=ExpressionBuiltinEval( source_code=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), globals_arg=globals_ref, locals_arg=locals_ref, source_ref=source_ref, ), source_ref=source_ref, ), ) tried = makeStatementsSequence( statements=(tried,) + statements, allow_none=False, source_ref=source_ref ) outline_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outline_body, tried=tried, final=final, source_ref=source_ref, ) ), ) return outline_body return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapEvalBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_eval_spec, ) if python_version >= 0x300: from nuitka.nodes.ExecEvalNodes import ExpressionBuiltinExec def exec_extractor(node): def wrapExpressionBuiltinExecCreation( source, globals_arg, locals_arg, source_ref ): provider = node.getParentVariableProvider() outline_body = ExpressionOutlineBody( provider=provider, name="exec_call", source_ref=source_ref ) globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( provider=provider, globals_node=globals_arg, locals_node=locals_arg, temp_scope=outline_body.getOutlineTempScope(), source_ref=source_ref, ) tried = makeStatementsSequence( statements=( tried, makeStatementReturn( expression=ExpressionBuiltinExec( source_code=source, globals_arg=globals_ref, locals_arg=locals_ref, source_ref=source_ref, ), source_ref=source_ref, ), ), allow_none=False, source_ref=source_ref, ) # Hack: Allow some APIs to work already tried.parent = outline_body outline_body.setChild( "body", makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=provider, tried=tried, final=final, source_ref=source_ref, ) ), ) return outline_body return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapExpressionBuiltinExecCreation, builtin_spec=BuiltinParameterSpecs.builtin_eval_spec, ) def compile_extractor(node): def wrapExpressionBuiltinCompileCreation( source_code, filename, mode, flags, dont_inherit, optimize=None, source_ref=None ): return ExpressionBuiltinCompile( source_code=source_code, filename=filename, mode=mode, flags=flags, dont_inherit=dont_inherit, optimize=optimize, source_ref=source_ref, ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapExpressionBuiltinCompileCreation, builtin_spec=BuiltinParameterSpecs.builtin_compile_spec, ) def open_extractor(node): def makeOpen0(source_ref): # pylint: disable=unused-argument try: # Not giving arguments or context on purpose # pylint: disable=consider-using-with,unspecified-encoding open() except Exception as e: # We want to broad here, pylint: disable=broad-except return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=e ) else: raise NuitkaAssumptionError("open without argument is expected to raise") return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinOpen, builtin_spec=BuiltinParameterSpecs.builtin_open_spec, empty_special_class=makeOpen0, ) def super_extractor(node): def wrapSuperBuiltin(type_arg, object_arg, source_ref): if type_arg is None and python_version >= 0x300: if provider.isCompiledPythonModule(): return makeRaiseExceptionReplacementExpression( expression=node, exception_type="RuntimeError", exception_value="super(): no arguments", ) class_variable = provider.getVariableForReference(variable_name="__class__") provider.trace_collection.getVariableCurrentTrace(class_variable).addUsage() type_arg = ExpressionVariableRef( # Ought to be already closure taken due to "super" flag in # tree building. variable=class_variable, source_ref=source_ref, ) # If we already have this as a local variable, then use that # instead. type_arg_owner = class_variable.getOwner() if type_arg_owner is provider or not ( type_arg_owner.isExpressionFunctionBody() or type_arg_owner.isExpressionClassBody() ): return makeRaiseExceptionReplacementExpression( expression=node, exception_type="SystemError" if python_version < 0x331 else "RuntimeError", exception_value="super(): __class__ cell not found", ) if object_arg is None: if ( provider.isExpressionGeneratorObjectBody() or provider.isExpressionCoroutineObjectBody() or provider.isExpressionAsyncgenObjectBody() ): parameter_provider = provider.getParentVariableProvider() else: parameter_provider = provider if parameter_provider.getParameters().getArgumentCount() == 0: return makeRaiseExceptionReplacementExpression( expression=node, exception_type="RuntimeError", exception_value="super(): no arguments", ) else: par1_name = parameter_provider.getParameters().getArgumentNames()[0] object_variable = provider.getVariableForReference( variable_name=par1_name ) provider.trace_collection.getVariableCurrentTrace( object_variable ).addUsage() object_arg = ExpressionVariableRef( variable=object_variable, source_ref=source_ref ) if not object_arg.getVariable().isParameterVariable(): return makeRaiseExceptionReplacementExpression( expression=node, exception_type="SystemError" if python_version < 0x300 else "RuntimeError", exception_value="super(): __class__ cell not found", ) return ExpressionBuiltinSuper0( type_arg=type_arg, object_arg=object_arg, source_ref=source_ref ) return ExpressionBuiltinSuper2( type_arg=type_arg, object_arg=object_arg, source_ref=source_ref ) provider = node.getParentVariableProvider().getEntryPoint() if not provider.isCompiledPythonModule(): provider.discardFlag("has_super") return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapSuperBuiltin, builtin_spec=BuiltinParameterSpecs.builtin_super_spec, ) def hasattr_extractor(node): # We need to have to builtin arguments, pylint: disable=redefined-builtin def makeExpressionBuiltinHasattr(object, name, source_ref): return ExpressionBuiltinHasattr( expression=object, name=name, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=makeExpressionBuiltinHasattr, builtin_spec=BuiltinParameterSpecs.builtin_hasattr_spec, ) def getattr_extractor(node): # We need to have to builtin arguments, pylint: disable=redefined-builtin def makeExpressionBuiltinGetattr(object, name, default, source_ref): return ExpressionBuiltinGetattr( expression=object, name=name, default=default, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=makeExpressionBuiltinGetattr, builtin_spec=BuiltinParameterSpecs.builtin_getattr_spec, ) def setattr_extractor(node): # We need to have to builtin arguments, pylint: disable=redefined-builtin def makeExpressionBuiltinSetattr(object, name, value, source_ref): return ExpressionBuiltinSetattr( expression=object, name=name, value=value, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=makeExpressionBuiltinSetattr, builtin_spec=BuiltinParameterSpecs.builtin_setattr_spec, ) def isinstance_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinIsinstance, builtin_spec=BuiltinParameterSpecs.builtin_isinstance_spec, ) def issubclass_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinIssubclass, builtin_spec=BuiltinParameterSpecs.builtin_isinstance_spec, ) def bytearray_extractor(node): def makeBytearray0(source_ref): return makeConstantRefNode(constant=bytearray(), source_ref=source_ref) def selectNextBuiltinClass(string, encoding, errors, source_ref): if encoding is None: return ExpressionBuiltinBytearray1(value=string, source_ref=source_ref) else: return ExpressionBuiltinBytearray3( string=string, encoding=encoding, errors=errors, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=selectNextBuiltinClass, builtin_spec=BuiltinParameterSpecs.builtin_bytearray_spec, empty_special_class=makeBytearray0, ) def slice_extractor(node): def wrapSlice(start, stop, step, source_ref): if start is not None and stop is None: # Default rules are strange. If one argument is given, it's the # second one then. stop = start start = None return makeExpressionBuiltinSlice( start=start, stop=stop, step=step, source_ref=source_ref ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=wrapSlice, builtin_spec=BuiltinParameterSpecs.builtin_slice_spec, ) def hash_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinHash, builtin_spec=BuiltinParameterSpecs.builtin_hash_spec, ) def format_extractor(node): def makeFormat0(source_ref): # pylint: disable=unused-argument return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError("format() takes at least 1 argument (0 given)"), ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinFormat, builtin_spec=BuiltinParameterSpecs.builtin_format_spec, empty_special_class=makeFormat0, ) def staticmethod_extractor(node): def makeStaticmethod0(source_ref): # pylint: disable=unused-argument return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError("staticmethod expected 1 arguments, got 0"), ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinStaticmethod, builtin_spec=BuiltinParameterSpecs.builtin_staticmethod_spec, empty_special_class=makeStaticmethod0, ) def classmethod_extractor(node): def makeStaticmethod0(source_ref): # pylint: disable=unused-argument return makeRaiseExceptionReplacementExpressionFromInstance( expression=node, exception=TypeError("classmethod expected 1 arguments, got 0"), ) return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionBuiltinClassmethod, builtin_spec=BuiltinParameterSpecs.builtin_classmethod_spec, empty_special_class=makeStaticmethod0, ) def divmod_extractor(node): return BuiltinParameterSpecs.extractBuiltinArgs( node=node, builtin_class=ExpressionOperationBinaryDivmod, builtin_spec=BuiltinParameterSpecs.builtin_divmod_spec, ) _dispatch_dict = { "compile": compile_extractor, "globals": globals_extractor, "locals": locals_extractor, "eval": eval_extractor, "dir": dir_extractor, "vars": vars_extractor, "__import__": import_extractor, "chr": chr_extractor, "ord": ord_extractor, "bin": bin_extractor, "oct": oct_extractor, "hex": hex_extractor, "id": id_extractor, "type": type_extractor, "iter": iter_extractor, "next": next_extractor, "sum": sum_extractor, "tuple": tuple_extractor, "list": list_extractor, "dict": dict_extractor, "set": set_extractor, "frozenset": frozenset_extractor, "float": float_extractor, "complex": complex_extractor, "str": str_extractor, "bool": bool_extractor, "int": int_extractor, "repr": repr_extractor, "len": len_extractor, "any": any_extractor, "abs": abs_extractor, "all": all_extractor, "super": super_extractor, "hasattr": hasattr_extractor, "getattr": getattr_extractor, "setattr": setattr_extractor, "isinstance": isinstance_extractor, "issubclass": issubclass_extractor, "bytearray": bytearray_extractor, "slice": slice_extractor, "hash": hash_extractor, "format": format_extractor, "open": open_extractor, "staticmethod": staticmethod_extractor, "classmethod": classmethod_extractor, "divmod": divmod_extractor, } if python_version < 0x300: # These are not in Python3 _dispatch_dict["long"] = long_extractor _dispatch_dict["unicode"] = unicode_extractor _dispatch_dict["execfile"] = execfile_extractor _dispatch_dict["xrange"] = xrange_extractor _dispatch_dict["range"] = range_extractor else: # This one is not in Python2: _dispatch_dict["bytes"] = bytes_extractor _dispatch_dict["ascii"] = ascii_extractor _dispatch_dict["exec"] = exec_extractor # The Python3 range is really an xrange, use that. _dispatch_dict["range"] = xrange_extractor def check(): from nuitka.Builtins import builtin_names for builtin_name in _dispatch_dict: assert builtin_name in builtin_names, builtin_name check() _builtin_ignore_list = ( # Not supporting 'print', because it could be replaced, and is not # worth the effort yet. "print", # TODO: This could, and should be supported, as we could e.g. lower # types easily for it. "sorted", # TODO: This would be very worthwhile, as it could easily optimize # its iteration away. "zip", # TODO: This would be most precious due to the type hint it gives "enumerate", # TODO: Also worthwhile for known values. "reversed", # TODO: Not sure what this really is about. "memoryview", ) def _describeNewNode(builtin_name, inspect_node): """Describe the change for better understanding.""" # Don't mention side effects, that's not what we care about. if inspect_node.isExpressionSideEffects(): inspect_node = inspect_node.subnode_expression if inspect_node.isExpressionBuiltinImport(): tags = "new_import" message = """\ Replaced dynamic "__import__" call with static built-in call.""" elif inspect_node.isExpressionBuiltin() or inspect_node.isStatementExec(): tags = "new_builtin" message = "Replaced call to built-in '%s' with built-in call '%s'." % ( builtin_name, inspect_node.kind, ) elif inspect_node.isExpressionRaiseException(): tags = "new_raise" message = """\ Replaced call to built-in '%s' with exception raise.""" % ( builtin_name, ) elif inspect_node.isExpressionOperationBinary(): tags = "new_expression" message = """\ Replaced call to built-in '%s' with binary operation '%s'.""" % ( builtin_name, inspect_node.getOperator(), ) elif inspect_node.isExpressionOperationUnary(): tags = "new_expression" message = """\ Replaced call to built-in '%s' with unary operation '%s'.""" % ( builtin_name, inspect_node.getOperator(), ) elif inspect_node.isExpressionCall(): tags = "new_expression" message = """\ Replaced call to built-in '%s' with call.""" % ( builtin_name, ) elif inspect_node.isExpressionOutlineBody(): tags = "new_expression" message = ( """\ Replaced call to built-in '%s' with outlined call.""" % builtin_name ) elif inspect_node.isExpressionConstantRef(): tags = "new_expression" message = ( """\ Replaced call to built-in '%s' with constant value.""" % builtin_name ) else: assert False, (builtin_name, "->", inspect_node) return tags, message def computeBuiltinCall(builtin_name, call_node): # There is some dispatching for how to output various types of changes, # with lots of cases. if builtin_name in _dispatch_dict: new_node = _dispatch_dict[builtin_name](call_node) assert new_node is not call_node, builtin_name assert new_node is not None, builtin_name # For traces, we are going to ignore side effects, and output traces # only based on the basis of it. tags, message = _describeNewNode(builtin_name, new_node) return new_node, tags, message else: # TODO: Achieve coverage of all built-ins in at least the ignore list. # if False and builtin_name not in _builtin_ignore_list: # optimization_logger.warning( # "Not handling built-in %r, consider support." % builtin_name # ) return call_node, None, None Nuitka-0.6.19.1/nuitka/optimizations/Tags.py0000600000372100037210000000434014166627112025744 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tags and set of it. Used by optimization to keep track of the current state of optimization, these tags trigger the execution of optimization steps, which in turn may emit these tags to execute other steps. """ allowed_tags = ( # New code means new statements. # Could be a new module, or an inlined exec statement. "new_code", # Added new import. "new_import", # New statements added, removed. "new_statements", # New expression added. "new_expression", # Loop analysis is incomplete, or only just now completed. "loop_analysis", # TODO: A bit unclear what this it, potentially a changed variable. "var_usage", # Detected module variable to be read only. "read_only_mvar", # Trusting module variables in functions. "trusted_module_variables", # New built-in reference detected. "new_builtin_ref", # New built-in call detected. "new_builtin", # New raise statement detected. "new_raise", # New constant introduced. "new_constant", ) class TagSet(set): def onSignal(self, signal): if type(signal) is str: signal = signal.split() for tag in signal: self.add(tag) def check(self, tags): for tag in tags.split(): assert tag in allowed_tags, tag if tag in self: return True return False def add(self, tag): assert tag in allowed_tags, tag set.add(self, tag) Nuitka-0.6.19.1/nuitka/optimizations/__init__.py0000600000372100037210000000150114166627112026601 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/optimizations/Optimization.py0000600000372100037210000002503114166627112027534 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Control the flow of optimizations applied to node tree. Applies abstract execution on all so far known modules until no more optimization is possible. Every successful optimization to anything might make others possible. """ import inspect from nuitka import ModuleRegistry, Options, Variables from nuitka.importing import ImportCache from nuitka.importing.Recursion import considerUsedModules from nuitka.plugins.Plugins import Plugins from nuitka.Progress import ( closeProgressBar, reportProgressBar, setupProgressBar, ) from nuitka.Tracing import ( general, memory_logger, optimization_logger, progress_logger, ) from nuitka.utils.MemoryUsage import ( MemoryWatch, getHumanReadableProcessMemoryUsage, ) from . import Graphs from .BytecodeDemotion import demoteCompiledModuleToBytecode from .Tags import TagSet from .TraceCollections import withChangeIndicationsTo _progress = Options.isShowProgress() _is_verbose = Options.isVerbose() tag_set = None def signalChange(tags, source_ref, message): """Indicate a change to the optimization framework.""" if message is not None: # Try hard to not call a delayed evaluation of node descriptions. if _is_verbose: optimization_logger.info( "{source_ref} : {tags} : {message}".format( source_ref=source_ref.getAsString(), tags=tags, message=message() if inspect.isfunction(message) else message, ) ) # assert pass_count < 2 tag_set.onSignal(tags) def optimizeCompiledPythonModule(module): optimization_logger.info_fileoutput( "Doing module local optimizations for '{module_name}'.".format( module_name=module.getFullName() ), other_logger=progress_logger, ) touched = False if _progress and Options.isShowMemory(): memory_watch = MemoryWatch() # Temporary workaround, since we do some optimization based on the last pass results # that are then not yet fully seen in the traces yet until another time around, we # allow to continue the loop even without changes one more time. unchanged_count = 0 while True: tag_set.clear() try: # print("Compute module") with withChangeIndicationsTo(signalChange): scopes_were_incomplete = module.computeModule() except SystemExit: raise except BaseException: general.info("Interrupted while working on '%s'." % module) raise if scopes_were_incomplete: tag_set.add("var_usage") Graphs.onModuleOptimizationStep(module) # Ignore other modules brought into the game. if "new_code" in tag_set: tag_set.remove("new_code") # Search for local change tags. if not tag_set: unchanged_count += 1 if unchanged_count == 1 and pass_count == 1: optimization_logger.info_fileoutput( "No changed, but retrying one more time.", other_logger=progress_logger, ) continue optimization_logger.info_fileoutput( "Finished with the module.", other_logger=progress_logger ) break unchanged_count = 0 optimization_logger.info_fileoutput( "Not finished with the module due to following change kinds: %s" % ",".join(sorted(tag_set)), other_logger=progress_logger, ) # Otherwise we did stuff, so note that for return value. touched = True if _progress and Options.isShowMemory(): memory_watch.finish() memory_logger.info( "Memory usage changed during optimization of '%s': %s" % (module.getFullName(), memory_watch.asStr()) ) considerUsedModules(module=module, signal_change=signalChange) return touched def optimizeUncompiledPythonModule(module): full_name = module.getFullName() progress_logger.info( "Doing module dependency considerations for '{module_name}':".format( module_name=full_name ) ) considerUsedModules(module=module, signal_change=signalChange) package_name = full_name.getPackageName() if package_name is not None: # TODO: It's unclear why, but some standard library modules on older Python3 # seem to not have parent packages after the scan. try: used_module = ImportCache.getImportedModuleByName(package_name) except KeyError: pass else: ModuleRegistry.addUsedModule( module=used_module, using_module=module, usage_tag="package", reason="Package of %s" % module.getFullName(), source_ref=module.source_ref, ) Plugins.considerImplicitImports(module=module, signal_change=signalChange) def optimizeShlibModule(module): # Pick up parent package if any. module.attemptRecursion() Plugins.considerImplicitImports(module=module, signal_change=signalChange) def optimizeModule(module): # The tag set is global, so it can track changes without context. # pylint: disable=global-statement global tag_set tag_set = TagSet() if module.isPythonShlibModule(): optimizeShlibModule(module) changed = False elif module.isCompiledPythonModule(): changed = optimizeCompiledPythonModule(module) else: optimizeUncompiledPythonModule(module) changed = False return changed pass_count = 0 last_total = 0 def _restartProgress(): global pass_count # Singleton, pylint: disable=global-statement closeProgressBar() pass_count += 1 optimization_logger.info_fileoutput( "PASS %d:" % pass_count, other_logger=progress_logger ) setupProgressBar( stage="PASS %d" % pass_count, unit="module", total=ModuleRegistry.getRemainingModulesCount() + ModuleRegistry.getDoneModulesCount(), min_total=last_total, ) def _traceProgressModuleStart(current_module): optimization_logger.info_fileoutput( """\ Optimizing module '{module_name}', {remaining:d} more modules to go \ after that.""".format( module_name=current_module.getFullName(), remaining=ModuleRegistry.getRemainingModulesCount(), ), other_logger=progress_logger, ) # Progress bar and spammy tracing don't go along. if not _is_verbose: reportProgressBar( item=current_module.getFullName(), total=ModuleRegistry.getRemainingModulesCount() + ModuleRegistry.getDoneModulesCount(), update=False, ) if _progress and Options.isShowMemory(): output = "Memory usage {memory}:".format( memory=getHumanReadableProcessMemoryUsage() ) memory_logger.info(output) def _traceProgressModuleEnd(current_module): reportProgressBar( item=current_module.getFullName(), total=ModuleRegistry.getRemainingModulesCount() + ModuleRegistry.getDoneModulesCount(), update=True, ) def _endProgress(): global last_total # Singleton, pylint: disable=global-statement last_total = closeProgressBar() def restoreFromXML(text): from nuitka.nodes.NodeBases import fromXML from nuitka.TreeXML import fromString xml = fromString(text) module = fromXML(provider=None, xml=xml) return module def makeOptimizationPass(): """Make a single pass for optimization, indication potential completion.""" # Controls complex optimization finished = True ModuleRegistry.startTraversal() _restartProgress() while True: current_module = ModuleRegistry.nextModule() if current_module is None: # TODO: Internal module seems to cause extra passes. # optimizeModule(getInternalModule()) break _traceProgressModuleStart(current_module) changed = optimizeModule(current_module) _traceProgressModuleEnd(current_module) if changed: finished = False # Unregister collection traces from now unused code, dropping the trace # collections of functions no longer used. This must be done after global # optimization due to cross module usages. for current_module in ModuleRegistry.getDoneModules(): if current_module.isCompiledPythonModule(): for unused_function in current_module.getUnusedFunctions(): Variables.updateVariablesFromCollection( old_collection=unused_function.trace_collection, new_collection=None, source_ref=unused_function.getSourceReference(), ) unused_function.trace_collection = None unused_function.finalize() used_functions = tuple( function for function in current_module.subnode_functions if function in current_module.getUsedFunctions() ) current_module.setChild("functions", used_functions) _endProgress() return finished def optimizeModules(output_filename): Graphs.startGraph() finished = makeOptimizationPass() # Demote compiled modules to bytecode, now that imports had a chance to be resolved, and # dependencies were handled. for module in ModuleRegistry.getDoneModules(): if ( module.isCompiledPythonModule() and module.getCompilationMode() == "bytecode" ): demoteCompiledModuleToBytecode(module) # Second, "endless" pass. while not finished: finished = makeOptimizationPass() Graphs.endGraph(output_filename) Nuitka-0.6.19.1/nuitka/PythonFlavors.py0000600000372100037210000000721414166627112024756 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Python flavors specifics. This abstracts the Python variants from different people. There is not just CPython, but Anaconda, Debian, pyenv, Apple, lots of people who make Python in a way the requires technical differences, e.g. static linking, LTO, or DLL presence, link paths, etc. """ import os import sys from nuitka.utils.FileOperations import isPathBelowOrSameAs from nuitka.utils.Utils import ( isLinux, isMacOS, isWin32Windows, withNoDeprecationWarning, ) from .PythonVersions import ( getRunningPythonDLLPath, getSystemPrefixPath, isStaticallyLinkedPython, python_version, ) def isNuitkaPython(): """Is this our own fork of CPython named Nuitka-Python.""" if python_version >= 0x300: return sys.implementation.name == "nuitkapython" else: return sys.subversion[0] == "nuitkapython" _is_anaconda = None def isAnacondaPython(): """Detect if Python variant Anaconda""" # singleton, pylint: disable=global-statement global _is_anaconda if _is_anaconda is None: _is_anaconda = os.path.exists(os.path.join(sys.prefix, "conda-meta")) return _is_anaconda def isApplePython(): return isMacOS() and isPathBelowOrSameAs( path="/usr/bin/", filename=getSystemPrefixPath() ) def isPyenvPython(): if isWin32Windows(): return False return os.environ.get("PYENV_ROOT") and isPathBelowOrSameAs( path=os.environ["PYENV_ROOT"], filename=getSystemPrefixPath() ) def isMSYS2MingwPython(): if not isWin32Windows() or "GCC" not in sys.version: return False import sysconfig return "-mingw_" in sysconfig.get_config_var("SO") def isUninstalledPython(): # Debian package. if isDebianPackagePython(): return False if isStaticallyLinkedPython(): return True if os.name == "nt": import ctypes.wintypes GetSystemDirectory = ctypes.windll.kernel32.GetSystemDirectoryW GetSystemDirectory.argtypes = (ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD) GetSystemDirectory.restype = ctypes.wintypes.DWORD MAX_PATH = 4096 buf = ctypes.create_unicode_buffer(MAX_PATH) res = GetSystemDirectory(buf, MAX_PATH) assert res != 0 system_path = os.path.normcase(buf.value) return not getRunningPythonDLLPath().startswith(system_path) return isAnacondaPython() or "WinPython" in sys.version def isWinPython(): return "WinPython" in sys.version def isDebianPackagePython(): """Is this Python from a debian package.""" if not isLinux(): return False if python_version < 0x300: return hasattr(sys, "_multiarch") else: with withNoDeprecationWarning(): try: from distutils.dir_util import _multiarch except ImportError: return False else: return True Nuitka-0.6.19.1/nuitka/Constants.py0000600000372100037210000002344714166627112024122 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module for constants in Nuitka. This contains tools to compare, classify and test constants. """ import math import sys from types import BuiltinFunctionType from nuitka.Builtins import builtin_type_names from nuitka.PythonVersions import python_version from .__past__ import GenericAlias, UnionType, iterItems, long, unicode, xrange from .Builtins import ( builtin_anon_names, builtin_anon_value_list, builtin_exception_values_list, builtin_named_values_list, ) NoneType = type(None) def compareConstants(a, b): # Many many cases to deal with, pylint: disable=too-many-branches,too-many-return-statements # Supposed fast path for comparison. if type(a) is not type(b): return False # Now it's either not the same, or it is a container that contains NaN or it # is a complex or float that is NaN, the other cases can use == at the end. if type(a) is complex: return compareConstants(a.imag, b.imag) and compareConstants(a.real, b.real) if type(a) is float: # Check sign first, -0.0 is not 0.0, or -nan is not nan, it has a # different sign for a start. if math.copysign(1.0, a) != math.copysign(1.0, b): return False if math.isnan(a) and math.isnan(b): return True return a == b if type(a) in (tuple, list): if len(a) != len(b): return False for ea, eb in zip(a, b): if not compareConstants(ea, eb): return False return True if type(a) is dict: if len(a) != len(b): return False for ea1, ea2 in iterItems(a): for eb1, eb2 in iterItems(b): if compareConstants(ea1, eb1) and compareConstants(ea2, eb2): break else: return False return True if type(a) in (frozenset, set): if len(a) != len(b): return False for ea in a: if ea not in b: # Due to NaN values, we need to compare each set element with # all the other set to be really sure. for eb in b: if compareConstants(ea, eb): break else: return False return True if type(a) is xrange: return str(a) == str(b) # The NaN values of float and complex may let this fail, even if the # constants are built in the same way, therefore above checks. return a == b # These built-in type references are kind of constant too. The list should be # complete. constant_builtin_types = ( int, str, float, list, tuple, set, dict, slice, complex, xrange, NoneType, ) if python_version >= 0x300: constant_builtin_types += (bytes,) else: constant_builtin_types += ( unicode, long, # This has no name in Python, but the natural one in C-API. builtin_anon_names["instance"], ) def isConstant(constant): # Too many cases and all return, that is how we do it here, # pylint: disable=too-many-branches,too-many-return-statements constant_type = type(constant) if constant_type is dict: for key, value in iterItems(constant): if not isConstant(key): return False if not isConstant(value): return False return True elif constant_type in (tuple, list): for element_value in constant: if not isConstant(element_value): return False return True elif constant_type is slice: if ( not isConstant(constant.start) or not isConstant(constant.stop) or not isConstant(constant.step) ): return False return True elif constant_type in ( str, unicode, complex, int, long, bool, float, NoneType, range, bytes, set, frozenset, xrange, bytearray, ): return True elif constant in (Ellipsis, NoneType, NotImplemented): return True elif constant in builtin_anon_value_list: return True elif constant_type is type: # Maybe pre-build this as a set for quicker testing. return ( constant.__name__ in builtin_type_names or constant in builtin_exception_values_list ) elif constant_type is BuiltinFunctionType and constant in builtin_named_values_list: # TODO: Some others could also be usable and even interesting, but # then probably should go into other node types, e.g. str.join is # a candidate. return True elif constant_type is GenericAlias: return True elif constant_type is UnionType: return True elif constant is sys.version_info: return True else: return False def isMutable(constant): """Is a constant mutable That means a user of a reference to it, can modify it. Strings are a prime example of immutable, dictionaries are mutable. """ # Many cases and all return, that is how we do it here, # pylint: disable=too-many-branches,too-many-return-statements constant_type = type(constant) if constant_type in ( str, unicode, complex, int, long, bool, float, NoneType, range, bytes, slice, xrange, type, BuiltinFunctionType, ): return False elif constant_type in (dict, list, set, bytearray): return True elif constant_type is tuple: for value in constant: if isMutable(value): return True return False elif constant_type is frozenset: for value in constant: if isMutable(value): return True return False elif constant is Ellipsis: return False elif constant is NotImplemented: return False elif constant_type is GenericAlias: return isMutable(constant.__origin__) or isMutable(constant.__args__) elif constant_type is UnionType: return False elif constant is sys.version_info: return False else: assert False, repr(constant) def isHashable(constant): """Is a constant hashable That means a user of a reference to it, can use it for dicts and set keys. This is distinct from mutable, there is one types that is not mutable, and still not hashable: slices. """ # Many cases and all return, that is how we do it here, # pylint: disable=too-many-return-statements constant_type = type(constant) if constant_type in ( str, unicode, complex, int, long, bool, float, NoneType, xrange, bytes, type, BuiltinFunctionType, ): return True elif constant_type in (dict, list, set, slice, bytearray): return False elif constant_type is tuple: for value in constant: if not isHashable(value): return False return True elif constant_type is frozenset: for value in constant: if not isHashable(value): return False return True elif constant is Ellipsis: return True else: assert False, constant_type def getUnhashableConstant(constant): # Too many cases and all return, that is how we do it here, # pylint: disable=too-many-return-statements constant_type = type(constant) if constant_type in ( str, unicode, complex, int, long, bool, float, NoneType, xrange, bytes, type, BuiltinFunctionType, ): return None elif constant_type in (dict, list, set): return constant elif constant_type is tuple: for value in constant: res = getUnhashableConstant(value) if res is not None: return res return None elif constant is Ellipsis: return None elif constant in constant_builtin_types: return None elif constant_type is slice: return None else: assert False, constant_type def createConstantDict(keys, values): # Create it proper size immediately. constant_value = dict.fromkeys(keys, None) for key, value in zip(keys, values): constant_value[key] = value return constant_value def isCompileTimeConstantValue(value): """Determine if a value will be usable at compile time.""" # This needs to match code in makeCompileTimeConstantReplacementNode if isConstant(value): return True elif type(value) is type: return True else: return False # Shared empty values, it would cost time to create them locally. the_empty_dict = {} the_empty_list = [] the_empty_set = set() the_empty_bytearray = bytearray() the_empty_tuple = () the_empty_frozenset = frozenset() the_empty_slice = slice(None) Nuitka-0.6.19.1/nuitka/Bytecodes.py0000600000372100037210000000653414166627112024065 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Handle bytecode and compile source code to bytecode. """ import ast from nuitka.Options import hasPythonFlagNoAsserts, hasPythonFlagNoDocstrings from nuitka.tree.TreeHelpers import getKind doc_having = tuple( getattr(ast, cand) for cand in ("FunctionDef", "ClassDef", "AsyncFunctionDef") if hasattr(ast, cand) ) def _removeDocFromBody(node): if node.body and getKind(node.body[0]) == "Expr": if getKind(node.body[0].value) == "Str": # python3.7 or earlier node.body[0].value.s = "" elif getKind(node.body[0].value) == "Constant": # python3.8 node.body[0].value.value = "" def compileSourceToBytecode(source_code, filename): """Compile given source code into bytecode.""" # Prepare compile call with AST tree. tree = ast.parse(source_code, filename) # Do we need to remove docstrings. remove_docstrings_from_tree = hasPythonFlagNoDocstrings() # For Python2, we need to do this manually. remove_asserts_from_tree = hasPythonFlagNoAsserts() and str is bytes if remove_docstrings_from_tree or remove_asserts_from_tree: # Module level docstring. if remove_docstrings_from_tree: _removeDocFromBody(tree) for node in ast.walk(tree): if remove_asserts_from_tree: node_type = type(node) if node_type is ast.Name: if node.id == "__debug__": node.id = "False" elif node_type is ast.Assert: # Cannot really remove the assertion node easily, lets just replace it with # "assert 1" and remove the assert msg. Probably not worth more effort for # Python2 at this time. node.test = ast.Num() node.test.n = 1 node.test.lineno = node.lineno node.test.col_offset = node.col_offset node.msg = None # Check if it's a docstring having node type. if remove_docstrings_from_tree and isinstance(node, doc_having): _removeDocFromBody(node) if str is bytes: bytecode = compile( tree, filename=filename, mode="exec", dont_inherit=True, ) else: # Let the handling of __debug__ happen within compile built-in. optimize = 0 if hasPythonFlagNoAsserts(): optimize = 1 bytecode = compile( tree, filename=filename, mode="exec", dont_inherit=True, optimize=optimize ) return bytecode Nuitka-0.6.19.1/nuitka/utils/0000700000372100037210000000000014167275622022726 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/utils/ModuleNames.py0000600000372100037210000001567514166627112025523 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module names are common string type, which deserves special operations. These are used in Nuitka for module and package names in most places, and allow to easily make checks on them. """ import fnmatch import os def checkModuleName(value): return ".." not in str(value) and not ( str(value).endswith(".") or str(value) == "." ) class ModuleName(str): def __init__(self, value): assert checkModuleName(value), value # TODO: Disallow some conversion, e.g. from module, function, etc. # objects, and white list what types we accept. str.__init__(value) @staticmethod def makeModuleNameInPackage(module_name, package_name): """Create a module name in a package. Args: - module_name (str or ModuleName) module name to put below the package - package_name (str or ModuleName or None) package to put below Returns: Module name "package_name.module_name" or if "package_name" is None then simply "module_name". Notes: Prefer this factory function over manually duplicating the pattern behind it. """ if package_name is not None: return ModuleName(package_name + "." + module_name) else: return ModuleName(module_name) def __repr__(self): return "" % str(self) def asString(self): """Get a simply str value. Notes: This should only be used to create constant values for code generation, there is no other reason to lower the type of these values otherwise. """ return str(self) def asPath(self): return str(self).replace(".", os.path.sep) def getPackageName(self): """Get the package name if any. Returns: ModuleName of the containing package or None if already top level. """ return self.splitModuleBasename()[0] def getRelativePackageName(self, level): result = ".".join(self.asString().split(".")[: -level + 1]) if result == "": return None else: return ModuleName(result) def getTopLevelPackageName(self): """Get the top level package name. Returns: ModuleName of the top level name. """ package_name = self.getPackageName() if package_name is None: return self else: return package_name.getTopLevelPackageName() def getBasename(self): """Get leaf name of the module without package part. Returns: ModuleName without package. """ return self.splitModuleBasename()[1] def splitModuleBasename(self): """Split a module into package name and module name.""" if "." in self: package_part = ModuleName(self[: self.rfind(".")]) module_name = ModuleName(self[self.rfind(".") + 1 :]) else: package_part = None module_name = self return package_part, module_name def splitPackageName(self): """Split a module into the top level package name and remaining module name.""" if "." in self: package_part = ModuleName(self[: self.find(".")]) module_name = ModuleName(self[self.find(".") + 1 :]) else: package_part = None module_name = self return package_part, module_name def hasNamespace(self, package_name): return self == package_name or self.isBelowNamespace(package_name) def hasOneOfNamespaces(self, *package_names): """Check if a module name is below one of many namespaces. Args: - package_names: Star argument that allows also lists and tuples Returns: bool - module name is below one of the packages. """ for package_name in package_names: if type(package_name) in (tuple, list): if self.hasOneOfNamespaces(*package_name): return True elif self.hasNamespace(package_name): return True return False def isBelowNamespace(self, package_name): assert type(package_name) in (str, ModuleName), package_name # Avoid startswith on these. return str(self).startswith(package_name + ".") def getChildNamed(self, *args): return ModuleName(".".join([self] + list(args))) def matchesToShellPatterns(self, patterns): """Match a module name to a list of patterns Args: patters: List of patterns that comply with fnmatch.fnmatch description or also is below the package. So "*.tests" will matches to also "something.tests.MyTest", thereby allowing to match whole packages with one pattern only. Returns: Tuple of two values, where the first value is the result, second value explains which pattern matched and how. """ for pattern in patterns: if self == pattern: return True, "is exact match of %r" % pattern elif self.isBelowNamespace(pattern): return True, "is package content of %r" % pattern elif fnmatch.fnmatch(self.asString(), pattern): return True, "matches pattern %r" % pattern elif fnmatch.fnmatch(self.asString(), pattern + ".*"): return True, "is package content of match to pattern %r" % pattern return False, None # Reject APIs being used. TODO: Maybe make this a decorator for reuse. # TODO: Add rsplit and subscript operations too. for _func_name in ("split", "startswith", "endswith"): code = """\ def %(func_name)s(*args, **kwargs): from nuitka.Errors import NuitkaCodeDeficit raise NuitkaCodeDeficit(''' Do not use %(func_name)s on ModuleName objects, use e.g. .hasNamespace(), .getBasename(), .getTopLevelPackageName() .hasOneOfNamespaces Check API documentation of nuitka.utils.ModuleNames.ModuleName ''') """ % { "func_name": _func_name } exec(code) # Avoid code duplication, pylint: disable=exec-used Nuitka-0.6.19.1/nuitka/utils/Json.py0000600000372100037210000000212314166627112024203 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Utils module to provide helper for our common json operations. TODO: Use this for our information caching files as well, and have easy ways to provide information to write. """ import json from .FileOperations import getFileContents def loadJsonFromFilename(filename): return json.loads(getFileContents(filename)) Nuitka-0.6.19.1/nuitka/utils/ReExecute.py0000600000372100037210000000730614166627112025173 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Ability to restart Nuitka, needed for removing site module effects and using Python PGO after compile. Note: This avoids imports at all costs, such that initial startup doesn't do more than necessary. """ import os import sys def callExecProcess(args): """Do exec in a portable way preserving exit code. On Windows, unfortunately there is no real exec, so we have to spawn a new process instead. """ # On Windows os.execl does not work properly if os.name == "nt": import subprocess args = list(args) del args[1] try: # Context manager is not available on all Python versions, pylint: disable=consider-using-with process = subprocess.Popen(args=args) process.communicate() # No point in cleaning up, pylint: disable=protected-access try: os._exit(process.returncode) except OverflowError: # Seems negative values go wrong otherwise, # see https://bugs.python.org/issue28474 os._exit(process.returncode - 2 ** 32) except KeyboardInterrupt: # There was a more relevant stack trace already, so abort this # right here, pylint: disable=protected-access os._exit(2) else: # The star arguments is the API of execl os.execl(*args) def reExecuteNuitka(pgo_filename): # Execute with full path as the process name, so it can find itself and its # libraries. args = [sys.executable, sys.executable] if sys.version_info >= (3, 7) and sys.flags.utf8_mode: args += ["-X", "utf8"] if "nuitka.__main__" in sys.modules: our_filename = sys.modules["nuitka.__main__"].__file__ else: our_filename = sys.modules["__main__"].__file__ args += ["-S", our_filename] os.environ["NUITKA_BINARY_NAME"] = sys.modules["__main__"].__file__ os.environ["NUITKA_PACKAGE_HOME"] = os.path.dirname( os.path.abspath(sys.modules["nuitka"].__path__[0]) ) if pgo_filename is not None: args.append("--pgo-python-input=%s" % pgo_filename) # Same arguments as before. args += sys.argv[1:] os.environ["NUITKA_PYTHONPATH"] = repr(sys.path) from nuitka.importing.PreloadedPackages import ( detectPreLoadedPackagePaths, detectPthImportedPackages, ) os.environ["NUITKA_NAMESPACES"] = repr(detectPreLoadedPackagePaths()) if "site" in sys.modules: site_filename = sys.modules["site"].__file__ if site_filename.endswith(".pyc"): site_filename = site_filename[:-4] + ".py" os.environ["NUITKA_SITE_FILENAME"] = site_filename os.environ["NUITKA_PTH_IMPORTED"] = repr(detectPthImportedPackages()) if sys.flags.no_site: os.environ["NUITKA_NOSITE_FLAG"] = "1" os.environ["PYTHONHASHSEED"] = "0" os.environ["NUITKA_REEXECUTION"] = "1" # Does not return: callExecProcess(args) Nuitka-0.6.19.1/nuitka/utils/StaticLibraries.py0000600000372100037210000001342014166627112026360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module deals with finding and information about static libraries. """ import os from nuitka.containers.oset import OrderedSet from nuitka.PythonFlavors import isDebianPackagePython, isNuitkaPython from nuitka.PythonVersions import ( getPythonABI, getSystemPrefixPath, python_version, python_version_str, ) from nuitka.Tracing import general from .FileOperations import getFileContentByLine, getFileList from .Utils import getLinuxDistribution, isDebianBasedLinux, isWin32Windows _ldconf_paths = None _static_lib_cache = {} def locateStaticLinkLibrary(dll_name): if dll_name not in _static_lib_cache: _static_lib_cache[dll_name] = _locateStaticLinkLibrary(dll_name) return _static_lib_cache[dll_name] def _locateStaticLinkLibrary(dll_name): # singleton, pylint: disable=global-statement # global _ldconf_paths if _ldconf_paths is None: _ldconf_paths = OrderedSet() for conf_filemame in getFileList("/etc/ld.so.conf.d", only_suffixes=".conf"): for conf_line in getFileContentByLine(conf_filemame): conf_line = conf_line.split("#", 1)[0] conf_line = conf_line.strip() if os.path.exists(conf_line): _ldconf_paths.add(conf_line) for ld_config_path in _ldconf_paths: candidate = os.path.join(ld_config_path, "lib%s.a" % dll_name) if os.path.exists(candidate): return candidate return None _static_lib_python_path = False def isDebianSuitableForStaticLinking(): dist_name, dist_version = getLinuxDistribution() if dist_name == "Debian": if dist_version is None: return True dist_version = tuple(int(x) for x in dist_version.split(".")) return dist_version >= (10,) elif dist_name == "Ubuntu": return True else: # TODO: Needs implementing potentially, Mint etc. are based # on something that should be considered. return True def _getSystemStaticLibPythonPath(): # Return driven function with many cases, pylint: disable=too-many-branches,too-many-return-statements sys_prefix = getSystemPrefixPath() python_abi_version = python_version_str + getPythonABI() if isNuitkaPython(): # Nuitka Python has this. if isWin32Windows(): return os.path.join( sys_prefix, "libs", "python" + python_abi_version.replace(".", "") + ".lib", ) else: return os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".a", ) if isWin32Windows(): candidates = [ # Anaconda has this. os.path.join( sys_prefix, "libs", "libpython" + python_abi_version.replace(".", "") + ".dll.a", ), # MSYS2 mingw64 Python has this. os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".dll.a", ), ] for candidate in candidates: if os.path.exists(candidate): return candidate else: candidate = os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".a" ) if os.path.exists(candidate): return candidate # For Python2 this works. TODO: Figure out Debian and Python3. if ( python_version < 0x300 and isDebianPackagePython() and isDebianSuitableForStaticLinking() ): candidate = locateStaticLinkLibrary("python" + python_abi_version) else: candidate = None if candidate is not None and os.path.exists(candidate): # Also check libz, can be missing if not locateStaticLinkLibrary("z"): general.warning( "Error, missing libz-dev installation needed for static lib-python." ) return candidate # This is not necessarily only for Python3 on Debian, but maybe others as well, # but that's what's been tested. if python_version >= 0x300 and isDebianPackagePython() and isDebianBasedLinux(): try: import sysconfig candidate = os.path.join( sysconfig.get_config_var("LIBPL"), "libpython" + python_abi_version + "-pic.a", ) if os.path.exists(candidate): return candidate except ImportError: # Cannot detect this properly for Python 2.6, but we don't care much # about that anyway. pass return None def getSystemStaticLibPythonPath(): global _static_lib_python_path # singleton, pylint: disable=global-statement if _static_lib_python_path is False: _static_lib_python_path = _getSystemStaticLibPythonPath() return _static_lib_python_path Nuitka-0.6.19.1/nuitka/utils/ThreadedExecutor.py0000600000372100037210000000505214166627112026535 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Threaded pool execution. This can use Python3 native, or even Python2.7 backport, or has a Python2.6 stub that does not thread at all. """ from threading import RLock, current_thread # Set this to false, to enable actual use of threads. This was found no longer # useful with dependency walker, but might be true in other cases. _use_threaded_executor = False class NonThreadedPoolExecutor(object): def __init__(self, max_workers=None): # This stub ignores max_workers, pylint: disable=unused-argument self.results = [] def __enter__(self): return self def __exit__(self, exc_type, exc_value, exc_traceback): return False def submit(self, function, *args): # Submitted jobs are simply done immediately. self.results.append(function(*args)) return self def waitWorkers(workers): if workers: return iter(workers[0].results) ThreadPoolExecutor = NonThreadedPoolExecutor if _use_threaded_executor: try: from concurrent.futures import ( # pylint: disable=I0021,import-error,no-name-in-module,unused-import FIRST_EXCEPTION, ThreadPoolExecutor, as_completed, wait, ) # We overwrite this if wanted, pylint: disable=function-redefined def waitWorkers(workers): wait(workers, return_when=FIRST_EXCEPTION) for future in as_completed(workers): yield future.result() except ImportError: # No backport installed, use stub for at least Python 2.6, and potentially # also Python 2.7, we might want to tell the user about it though, that # we think it should be installed. pass def getThreadIdent(): return current_thread() assert RLock assert ThreadPoolExecutor Nuitka-0.6.19.1/nuitka/utils/FileOperations.py0000600000372100037210000005265514166627112026234 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Utils for file and directory operations. This provides enhanced and more error resilient forms of standard stuff. It will also frequently add sorting for determism. """ from __future__ import print_function import errno import glob import os import shutil import stat import tempfile import time from contextlib import contextmanager from nuitka.__past__ import ( # pylint: disable=I0021,redefined-builtin WindowsError, basestring, ) from nuitka.PythonVersions import python_version from nuitka.Tracing import my_print, options_logger from .Importing import importFromInlineCopy from .ThreadedExecutor import RLock, getThreadIdent from .Utils import getOS, isWin32Windows # Locking seems to be only required for Windows mostly, but we can keep # it for all. file_lock = RLock() # Use this in case of dead locks or even to see file operations being done. _lock_tracing = False @contextmanager def withFileLock(reason="unknown"): """Acquire file handling lock. Args: reason: What is being done. Notes: This is most relevant for Windows, but prevents concurrent access from threads generally, which could lead to observing half ready things. """ if _lock_tracing: my_print(getThreadIdent(), "Want file lock for %s" % reason) file_lock.acquire() if _lock_tracing: my_print(getThreadIdent(), "Acquired file lock for %s" % reason) yield if _lock_tracing: my_print(getThreadIdent(), "Released file lock for %s" % reason) file_lock.release() def areSamePaths(path1, path2): """Decide if two paths the same. Args: path1: First path path2: Second path Returns: Boolean value indicating if the two paths point to the same path. Notes: Case differences ignored on platforms where that is the norm, and with it normalized, and turned absolute paths, it becomes a mere string compare after that. is no differences. """ path1 = os.path.normcase(os.path.abspath(os.path.normpath(path1))) path2 = os.path.normcase(os.path.abspath(os.path.normpath(path2))) return path1 == path2 def haveSameFileContents(path1, path2): # Local import, to avoid this for normal use cases. import filecmp return filecmp.cmp(path1, path2) def getFileSize(path): return os.path.getsize(path) def relpath(path, start="."): """Make it a relative path, if possible. Args: path: path to work on start: where to start from, defaults to current directory Returns: Changed path, pointing to the same path relative to current directory if possible. Notes: On Windows, a relative path is not possible across device names, therefore it may have to return the absolute path instead. """ if start == ".": start = os.curdir try: return os.path.relpath(path, start) except ValueError: # On Windows, paths on different devices prevent it to work. Use that # full path then. if getOS() == "Windows": return os.path.abspath(path) raise def isRelativePath(path): if os.path.isabs(path): return False if path.startswith((".." + os.path.sep, "../")): return False return True def makePath(path): """Create a directory if it doesn't exist. Args: path: path to create as a directory Notes: This also is thread safe on Windows, i.e. no race is possible. """ with withFileLock("creating directory %s" % path): if not os.path.isdir(path): os.makedirs(path) def isPathExecutable(path): """Is the given path executable.""" return os.path.isfile(path) and os.access(path, os.X_OK) def _getRealPathWindows(path): # Slow, because we are using an external process, we it's only for standalone and Python2, # which is slow already. import subprocess result = subprocess.check_output( """powershell -NoProfile "Get-Item '%s' | Select-Object -ExpandProperty Target" """ % path ) if str is not bytes: result = result.decode("utf8") return os.path.join(os.path.dirname(path), result.rstrip("\r\n")) def getDirectoryRealPath(path): """Get os.path.realpath with Python2 and Windows symlink workaround applied. Args: path: path to get realpath of Returns: path with symlinks resolved Notes: Workaround for Windows symlink is applied. """ path = os.path.realpath(path) # Attempt to resolve Windows symlinks on Python2 if os.name == "nt" and not os.path.isdir(path): path = _getRealPathWindows(path) return path def listDir(path): """Give a sorted listing of a path. Args: path: directory to create a listing from Returns: Sorted list of tuples of full filename, and basename of a directory. Notes: Typically the full name and the basename are both needed so this function simply does both, for ease of use on the calling side. This should be used, because it makes sure to resolve the symlinks to directories on Windows, that a naive "os.listdir" won't do by default. """ real_path = getDirectoryRealPath(path) return sorted( [(os.path.join(path, filename), filename) for filename in os.listdir(real_path)] ) def getFileList( path, ignore_dirs=(), ignore_filenames=(), ignore_suffixes=(), only_suffixes=(), normalize=True, ): """Get all files below a given path. Args: path: directory to create a recursive listing from ignore_dirs: Don't descend into these directory, ignore them ignore_filenames: Ignore files named exactly like this ignore_suffixes: Don't return files with these suffixes only_suffixes: If not empty, limit returned files to these suffixes Returns: Sorted list of all filenames below that directory, relative to it. Notes: This function descends into directories, but does not follow symlinks. """ # We work with a lot of details here, pylint: disable=too-many-locals result = [] # Normalize ignoredirs for better matching. ignore_dirs = [os.path.normcase(ignore_dir) for ignore_dir in ignore_dirs] ignore_filenames = [ os.path.normcase(ignore_filename) for ignore_filename in ignore_filenames ] for root, dirnames, filenames in os.walk(path): dirnames.sort() filenames.sort() # Normalize dirnames for better matching. dirnames_normalized = [os.path.normcase(dirname) for dirname in dirnames] for ignore_dir in ignore_dirs: if ignore_dir in dirnames_normalized: dirnames.remove(ignore_dir) # Normalize filenames for better matching. filenames_normalized = [os.path.normcase(filename) for filename in filenames] for ignore_filename in ignore_filenames: if ignore_filename in filenames_normalized: filenames.remove(ignore_filename) for filename in filenames: if os.path.normcase(filename).endswith(ignore_suffixes): continue if only_suffixes and not os.path.normcase(filename).endswith(only_suffixes): continue fullname = os.path.join(root, filename) if normalize: fullname = os.path.normpath(fullname) result.append(fullname) return result def getSubDirectories(path, ignore_dirs=()): """Get all directories below a given path. Args: path: directory to create a recursive listing from Returns: Sorted list of all directories below that directory, relative to it. Notes: This function descends into directories, but does not follow symlinks. """ result = [] ignore_dirs = [os.path.normcase(ignore_dir) for ignore_dir in ignore_dirs] for root, dirnames, _filenames in os.walk(path): # Normalize dirnames for better matching. dirnames_normalized = [os.path.normcase(dirname) for dirname in dirnames] for ignore_dir in ignore_dirs: if ignore_dir in dirnames_normalized: dirnames.remove(ignore_dir) dirnames.sort() for dirname in dirnames: result.append(os.path.join(root, dirname)) result.sort() return result def deleteFile(path, must_exist): """Delete a file, potentially making sure it exists. Args: path: file to delete Notes: This also is thread safe on Windows, i.e. no race is possible. """ with withFileLock("deleting file %s" % path): if os.path.islink(path) or os.path.isfile(path): try: os.unlink(path) except OSError: if must_exist: raise elif must_exist: raise OSError("Does not exist", path) def splitPath(path): """Split path, skipping empty elements.""" return tuple( element for element in os.path.split(path.rstrip(os.path.sep)) if element ) def getFilenameExtension(path): """Get the filename extension. Note: The extension is case normalized, i.e. it may actually be ".TXT" rather than ".txt", use "changeFilenameExtension" if you want to replace it with something else. Note: For checks on extension, use hasFilenameExtension instead. """ return os.path.splitext(os.path.normcase(path))[1] def changeFilenameExtension(path, extension): """Change the filename extension.""" return os.path.splitext(path)[0] + extension def hasFilenameExtension(path, extensions): """Has a filename one of the given extensions. Note: The extensions should be normalized, i.e. lower case and will match other cases where the file system does that on a platform. """ extension = getFilenameExtension(path) if isinstance(extensions, basestring): return extension == extensions else: return extension in extensions def removeDirectory(path, ignore_errors): """Remove a directory recursively. On Windows, it happens that operations fail, and succeed when reried, so added a retry and small delay, then another retry. Should make it much more stable during tests. All kinds of programs that scan files might cause this, but they do it hopefully only briefly. """ def onError(func, path, exc_info): # Try again immediately, ignore what happened, pylint: disable=unused-argument try: func(path) except OSError: time.sleep(0.1) func(path) with withFileLock("removing directory %s" % path): if os.path.exists(path): try: shutil.rmtree(path, ignore_errors=False, onerror=onError) except OSError: if ignore_errors: shutil.rmtree(path, ignore_errors=ignore_errors) else: raise @contextmanager def withTemporaryFile(suffix="", mode="w", delete=True, temp_path=None): with tempfile.NamedTemporaryFile( suffix=suffix, mode=mode, delete=delete, dir=temp_path ) as temp_file: yield temp_file def getFileContentByLine(filename, mode="r", encoding=None): # We read the whole, to keep lock times minimal. We only deal with small # files like this normally. return getFileContents(filename, mode, encoding=encoding).splitlines() def getFileContents(filename, mode="r", encoding=None): """Get the contents of a file. Args: filename: str with the file to be read mode: "r" for str, "rb" for bytes result encoding: optional encoding to used when reading the file, e.g. "utf8" Returns: str or bytes - depending on mode. """ with withFileLock("reading file %s" % filename): with openTextFile(filename, mode, encoding=encoding) as f: return f.read() def getFileFirstLine(filename, mode="r", encoding=None): """Get the contents of a file. Args: filename: str with the file to be read mode: "r" for str, "rb" for bytes result encoding: optional encoding to used when reading the file, e.g. "utf8" Returns: str or bytes - depending on mode. """ with withFileLock("reading file %s" % filename): with openTextFile(filename, mode, encoding=encoding) as f: return f.readline() def openTextFile(filename, mode, encoding=None): if encoding is not None: import codecs return codecs.open(filename, mode, encoding=encoding) else: # Avoid deprecation warning, is now the default. if python_version >= 0x370: mode = mode.replace("U", "") # Encoding was checked to be not needed. return open(filename, mode) # pylint: disable=unspecified-encoding def putTextFileContents(filename, contents, encoding=None): """Write a text file from given contents. Args: filename: str with the file to be created contents: str or iterable of strings with what should be written into the file encoding: optional encoding to used when writing the file Returns: None """ def _writeContents(output_file): if isinstance(contents, basestring): print(contents, file=output_file, end="") else: for line in contents: print(line, file=output_file) with withFileLock("writing file %s" % filename): with openTextFile(filename, "w", encoding=encoding) as output_file: _writeContents(output_file) @contextmanager def withPreserveFileMode(filename): old_mode = os.stat(filename).st_mode yield os.chmod(filename, old_mode) @contextmanager def withMadeWritableFileMode(filename): with withPreserveFileMode(filename): os.chmod(filename, int("644", 8)) yield def removeFileExecutablePermission(filename): old_stat = os.stat(filename) mode = old_stat.st_mode mode &= ~(stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) if mode != old_stat.st_mode: os.chmod(filename, mode) def addFileExecutablePermission(filename): old_stat = os.stat(filename) mode = old_stat.st_mode mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH if mode != old_stat.st_mode: os.chmod(filename, mode) def renameFile(source_filename, dest_filename): # There is no way to safely update a file on Windows, but lets # try on Linux at least. old_stat = os.stat(source_filename) try: os.rename(source_filename, dest_filename) except OSError: shutil.copyfile(source_filename, dest_filename) os.unlink(source_filename) os.chmod(dest_filename, old_stat.st_mode) def copyTree(source_path, dest_path): """Copy whole directory tree, preserving attributes. Args: source_path: where to copy from dest_path: where to copy to, may already exist Notes: This must be used over `shutil.copytree` which has troubles with existing directories. """ if python_version >= 0x380: # Python 3.8+ has dirs_exist_ok return shutil.copytree(source_path, dest_path, dirs_exist_ok=True) else: from distutils.dir_util import copy_tree return copy_tree(source_path, dest_path) def copyFileWithPermissions(source_path, dest_path): """Improved version of shutil.copy2. File systems might not allow to transfer extended attributes, which we then ignore and only copy permissions. """ try: shutil.copy2(source_path, dest_path) except PermissionError as e: if e.errno != errno.EACCES: raise source_mode = os.stat(source_path).st_mode shutil.copy(source_path, dest_path) os.chmod(dest_path, source_mode) def getWindowsDrive(path): """Windows drive for a given path.""" drive, _ = os.path.splitdrive(os.path.abspath(path)) return os.path.normcase(drive) def isPathBelow(path, filename): """Is a path inside of a given directory path.""" path = os.path.abspath(path) filename = os.path.abspath(filename) if isWin32Windows(): if getWindowsDrive(path) != getWindowsDrive(filename): return False return os.path.relpath(filename, path).split(os.path.sep)[0] != ".." def isPathBelowOrSameAs(path, filename): """Is a path inside of a given directory path or the same path as that directory.""" return isPathBelow(path, filename) or areSamePaths(path, filename) def getWindowsShortPathName(filename): """Gets the short path name of a given long path. Args: filename - long Windows filename Returns: Path that is a short filename pointing at the same file. Notes: Originally from http://stackoverflow.com/a/23598461/200291 """ import ctypes.wintypes GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW GetShortPathNameW.argtypes = [ ctypes.wintypes.LPCWSTR, ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD, ] GetShortPathNameW.restype = ctypes.wintypes.DWORD output_buf_size = 0 while True: output_buf = ctypes.create_unicode_buffer(output_buf_size) needed = GetShortPathNameW( os.path.abspath(filename), output_buf, output_buf_size ) if needed == 0: # Windows only code, pylint: disable=I0021,undefined-variable raise WindowsError( ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError()) ) if output_buf_size >= needed: # Short paths should be ASCII. Don't return unicode without a need, # as e.g. Scons hates that in environment variables. if str is bytes: return output_buf.value.encode("utf8") else: return output_buf.value else: output_buf_size = needed def getExternalUsePath(filename, only_dirname=False): """Gets the externally usable absolute path for a given relative path. Args: filename - filename, potentially relative Returns: Path that is a absolute and (on Windows) short filename pointing at the same file. Notes: This is only os.path.abspath except on Windows, where is coverts to a short path too. """ filename = os.path.abspath(filename) if os.name == "nt": if only_dirname: dirname = getWindowsShortPathName(os.path.dirname(filename)) assert os.path.exists(dirname) filename = os.path.join(dirname, os.path.basename(filename)) else: filename = getWindowsShortPathName(filename) return filename def getLinkTarget(filename): """Return the path a link is pointing too, if any. Args: filename - check this path, need not be a filename Returns: (bool, link_target) - first value indicates if it is a link, second the link target Notes: This follows symlinks to the very end. """ is_link = False while os.path.exists(filename) and os.path.islink(filename): link_target = os.readlink(filename) filename = os.path.join(os.path.dirname(filename), link_target) is_link = True return is_link, filename def replaceFileAtomic(source_path, dest_path): """ Move ``src`` to ``dst``. If ``dst`` exists, it will be silently overwritten. Both paths must reside on the same filesystem for the operation to be atomic. """ if python_version >= 0x300: os.replace(source_path, dest_path) else: importFromInlineCopy("atomicwrites", must_exist=True).replace_atomic( source_path, dest_path ) def resolveShellPatternToFilenames(pattern): """Resolve shell pattern to filenames. Args: pattern - str Returns: list - filenames that matched. """ if "**" in pattern: if python_version >= 0x350: result = glob.glob(pattern, recursive=True) else: glob2 = importFromInlineCopy("glob2", must_exist=False) if glob2 is None: options_logger.sysexit( "Using pattern with ** is not supported before Python 3.5 unless glob2 is installed." ) result = glob2.glob(pattern) else: result = glob.glob(pattern) result = [os.path.normpath(filename) for filename in result] result.sort() return result @contextmanager def withDirectoryChange(path, allow_none=False): """Change current directory temporarily in a context.""" if path is not None or not allow_none: old_cwd = os.getcwd() os.chdir(path) yield if path is not None or not allow_none: os.chdir(old_cwd) Nuitka-0.6.19.1/nuitka/utils/MacOSApp.py0000600000372100037210000000737614166627112024714 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ For macOS application bundle creation """ import os import shutil from nuitka import Options, OutputDirectories from nuitka.containers.odict import OrderedDict from .FileOperations import makePath, openTextFile from .Images import convertImageToIconFormat def createPlistInfoFile(logger, onefile): # Many details, pylint: disable=too-many-locals import plistlib if Options.isStandaloneMode(): bundle_dir = os.path.dirname(OutputDirectories.getStandaloneDirectoryPath()) else: bundle_dir = os.path.dirname( OutputDirectories.getResultRunFilename(onefile=onefile) ) result_filename = OutputDirectories.getResultFullpath(onefile=onefile) app_name = Options.getMacOSAppName() or os.path.basename(result_filename) signed_app_name = Options.getMacOSSignedAppName() or app_name app_version = Options.getMacOSAppVersion() or "1.0" # TODO: We want an OrderedDict probably for stability. infos = OrderedDict( [ ("CFBundleDisplayName", app_name), ("CFBundleName", app_name), ("CFBundleIdentifier", signed_app_name), ("CFBundleExecutable", app_name), ("CFBundleInfoDictionaryVersion", "6.0"), ("CFBundlePackageType", "APPL"), ("CFBundleShortVersionString", app_version), ] ) icon_paths = Options.getIconPaths() if icon_paths: assert len(icon_paths) == 1 icon_path = icon_paths[0] # Convert to single macOS .icns file if necessary if not icon_path.endswith(".icns"): logger.info( "File '%s' is not in macOS icon format, converting to it." % icon_path ) icon_build_path = os.path.join( OutputDirectories.getSourceDirectoryPath(onefile=onefile), "icons", ) makePath(icon_build_path) converted_icon_path = os.path.join( icon_build_path, "Icons.icns", ) convertImageToIconFormat( logger=logger, image_filename=icon_path, icon_filename=converted_icon_path, ) icon_path = converted_icon_path icon_name = os.path.basename(icon_path) resources_dir = os.path.join(bundle_dir, "Resources") makePath(resources_dir) shutil.copyfile(icon_path, os.path.join(resources_dir, icon_name)) infos["CFBundleIconFile"] = icon_name # Console mode, which is why we have to use bundle in the first place typically. if Options.shallDisableConsoleWindow(): infos["NSHighResolutionCapable"] = True else: infos["LSBackgroundOnly"] = True filename = os.path.join(bundle_dir, "Info.plist") if str is bytes: plist_contents = plistlib.writePlistToString(infos) else: plist_contents = plistlib.dumps(infos) with openTextFile(filename=filename, mode="wb") as plist_file: plist_file.write(plist_contents) Nuitka-0.6.19.1/nuitka/utils/Signing.py0000600000372100037210000000456614166627112024705 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Signing of executables. """ from nuitka.Tracing import postprocessing_logger from .Execution import executeToolChecked from .FileOperations import withMadeWritableFileMode _macos_codesign_usage = "The 'codesign' is used to remove invalidated signatures on macOS and required to be found." def removeMacOSCodeSignature(filename): """Remove the code signature from a filename. Args: filename - The file to be modified. Returns: None Notes: This is macOS specific. """ with withMadeWritableFileMode(filename): executeToolChecked( logger=postprocessing_logger, command=["codesign", "--remove-signature", "--all-architectures", filename], absence_message=_macos_codesign_usage, ) def addMacOSCodeSignature(filename, identity, entitlements_filename, deep): extra_args = [] # Weak signing is supported. if not identity: identity = "-" command = [ "codesign", "-s", identity, "--force", "--timestamp", "--all-architectures", ] # hardened runtime unless no good identify if identity != "-": extra_args.append("--options=runtime") if entitlements_filename: extra_args.append("--entitlements") extra_args.append(entitlements_filename) if deep: extra_args.append("--deep") command.append(filename) with withMadeWritableFileMode(filename): executeToolChecked( logger=postprocessing_logger, command=command, absence_message=_macos_codesign_usage, ) Nuitka-0.6.19.1/nuitka/utils/Utils.py0000600000372100037210000001537614166627112024410 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Utility module. Here the small things that fit nowhere else and don't deserve their own module. """ import os import sys from contextlib import contextmanager def getOS(): if os.name == "nt": return "Windows" elif os.name == "posix": result = os.uname()[0] # Handle msys2 posix nature still meaning it's Windows. if result.startswith(("MSYS_NT-", "MINGW64_NT-")): result = "Windows" return result else: assert False, os.name _linux_distribution_info = None def getLinuxDistribution(): """Name of the Linux distribution. We should usually avoid this, and rather test for the feature, but in some cases it's hard to manage that. """ # singleton, pylint: disable=global-statement global _linux_distribution_info if getOS() != "Linux": return None, None if _linux_distribution_info is None: import platform # pylint: disable=I0021,deprecated-method,no-member try: result = platform.dist()[0] version = platform.dist()[1] except AttributeError: result = None version = None if os.path.exists("/etc/os-release"): from .FileOperations import getFileContentByLine for line in getFileContentByLine("/etc/os-release"): if line.startswith("ID="): result = line[3:].strip('"') if line.startswith("VERSION="): version = line[8:].strip('"') if result is None: from .Execution import check_output try: result = check_output(["lsb_release", "-i", "-s"], shell=False) if str is not bytes: result = result.decode("utf8") except FileNotFoundError: pass if result is None: from nuitka.Tracing import general general.sysexit("Error, cannot detect Linux distribution.") # Change e.g. "11 (Bullseye)"" to "11". if version is not None and version.strip(): version = version.split()[0] _linux_distribution_info = result.title(), version return _linux_distribution_info def getWindowsRelease(): if getOS() != "Windows": return None import platform return platform.release() def isDebianBasedLinux(): # TODO: What is with Mint, maybe others, this list should be expanded potentially. dist_name, _dist_version = getLinuxDistribution() return dist_name in ("Debian", "Ubuntu") def isWin32Windows(): """The Win32 variants of Python does have win32 only, not posix.""" return os.name == "nt" def isPosixWindows(): """The MSYS2 variant of Python does have posix only, not Win32.""" return os.name == "posix" and getOS() == "Windows" def isLinux(): """The Linux OS.""" return getOS() == "Linux" def isMacOS(): """The macOS platform.""" return getOS() == "Darwin" def isNetBSD(): """The NetBSD OS.""" return getOS() == "NetBSD" def isFreeBSD(): """The FreeBSD OS.""" return getOS() == "FreeBSD" def isOpenBSD(): """The FreeBSD OS.""" return getOS() == "OpenBSD" _is_alpine = None def isAlpineLinux(): if os.name == "posix": # Avoid repeated file system lookup, pylint: disable=global-statement global _is_alpine if _is_alpine is None: _is_alpine = os.path.isfile("/etc/alpine-release") return _is_alpine else: return False def getArchitecture(): if getOS() == "Windows": if "AMD64" in sys.version: return "x86_64" else: return "x86" else: return os.uname()[4] def getCoreCount(): cpu_count = 0 if getOS() != "Windows": # Try to sum up the CPU cores, if the kernel shows them, getting the number # of logical processors try: # Encoding is not needed, pylint: disable=unspecified-encoding with open("/proc/cpuinfo") as cpuinfo_file: cpu_count = cpuinfo_file.read().count("processor\t:") except IOError: pass # Multiprocessing knows the way. if not cpu_count: import multiprocessing cpu_count = multiprocessing.cpu_count() return cpu_count def encodeNonAscii(var_name): """Encode variable name that is potentially not ASCII to ASCII only. For Python3, unicode identifiers can be used, but these are not possible in C, so we need to replace them. """ if str is bytes: return var_name else: # Using a escaping here, because that makes it safe in terms of not # to occur in the encoding escape sequence for unicode use. var_name = var_name.replace("$$", "$_$") var_name = var_name.encode("ascii", "xmlcharrefreplace") var_name = var_name.decode("ascii") return var_name.replace("&#", "$$").replace(";", "") def hasOnefileSupportedOS(): return getOS() in ("Linux", "Windows", "Darwin", "FreeBSD") def hasStandaloneSupportedOS(): return getOS() in ("Linux", "Windows", "Darwin", "FreeBSD", "OpenBSD") def getUserName(): """Return the user name. Notes: Currently doesn't work on Windows. """ import pwd # pylint: disable=I0021,import-error return pwd.getpwuid(os.getuid())[0] @contextmanager def withNoDeprecationWarning(): import warnings with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) # These do not inherit from DeprecationWarning by some decision we # are not to care about. if "pkg_resources" in sys.modules: try: from pkg_resources import PkgResourcesDeprecationWarning except ImportError: pass else: warnings.filterwarnings( "ignore", category=PkgResourcesDeprecationWarning ) yield Nuitka-0.6.19.1/nuitka/utils/Yaml.py0000600000372100037210000000346114166627112024202 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nuitka yaml utility functions. Because we want to work with Python2.6 or higher, we play a few tricks with what library to use for what Python. We have an inline copy of PyYAML that still does 2.6, on other Pythons, we expect the system to have it installed. Also we put loading for specific packages in here and a few helpers to work with these config files. """ import pkgutil from .Importing import importFromInlineCopy class Yaml(object): def __init__(self, filename, data): self.filename = filename self.data = data def get(self, name): return self.data.get(name) def parseYaml(data): try: import yaml except ImportError: yaml = importFromInlineCopy("yaml", must_exist=True) try: yaml_load_function = yaml.safe_load except AttributeError: yaml_load_function = yaml.load return yaml_load_function(data) def parsePackageYaml(package_name, filename): return Yaml( filename=filename, data=parseYaml(pkgutil.get_data(package_name, filename)) ) Nuitka-0.6.19.1/nuitka/utils/WindowsResources.py0000600000372100037210000004756414166627112026641 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Module for handling Windows resources. Nuitka needs to do a couple of things with Windows resources, e.g. adding and removing manifests amd copying icon image resources into the created binary. For this purpose, we need to list, remove, add resources and extract their data. Previously we used the Windows SDK tools for this purpose, but for some tasks, e.g. deleting unwanted manifest resources for include into the distribution, we needed to do it manually. Also setting icon resources with images for multiple resources proved to be not possible. """ import ctypes import os import struct import time from nuitka import TreeXML # SxS manifest files resource kind RT_MANIFEST = 24 # Version info RT_VERSION = 16 # Data resource kind RT_RCDATA = 10 # Icon group resource kind RT_GROUP_ICON = 14 # Icon resource kind RT_ICON = 3 def getResourcesFromDLL(filename, resource_kinds, with_data=False): """Get the resources of a specific kind from a Windows DLL. Args: filename - filename where the resources are taken from resource_kinds - tuple of numeric values indicating types of resources with_data - Return value includes data or only the name, lang pairs Returns: List of resources in the DLL, see with_data which controls scope. """ # Quite complex stuff, pylint: disable=too-many-locals import ctypes.wintypes # Not really redefined, but extended, pylint: disable=redefined-outer-name if type(filename) is str and str is not bytes: LoadLibraryEx = ctypes.windll.kernel32.LoadLibraryExW else: LoadLibraryEx = ctypes.windll.kernel32.LoadLibraryExA EnumResourceLanguages = ctypes.windll.kernel32.EnumResourceLanguagesA FreeLibrary = ctypes.windll.kernel32.FreeLibrary EnumResourceNameCallback = ctypes.WINFUNCTYPE( ctypes.wintypes.BOOL, ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, ctypes.wintypes.LONG, ctypes.wintypes.LONG, ) EnumResourceNames = ctypes.windll.kernel32.EnumResourceNamesA EnumResourceNames.argtypes = [ ctypes.wintypes.HMODULE, ctypes.wintypes.LPVOID, EnumResourceNameCallback, ctypes.wintypes.LPARAM, ] DONT_RESOLVE_DLL_REFERENCES = 0x1 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x40 LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x20 hmodule = LoadLibraryEx( filename, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE, ) if hmodule == 0: raise ctypes.WinError() EnumResourceLanguagesCallback = ctypes.WINFUNCTYPE( ctypes.wintypes.BOOL, ctypes.wintypes.HMODULE, ctypes.wintypes.LONG, ctypes.wintypes.LONG, ctypes.wintypes.WORD, ctypes.wintypes.LONG, ) result = [] def callback(hModule, lpType, lpName, _lParam): langs = [] def callback2(hModule2, lpType2, lpName2, wLang, _lParam): assert hModule2 == hModule assert lpType2 == lpType assert lpName2 == lpName langs.append(wLang) return True EnumResourceLanguages( hModule, lpType, lpName, EnumResourceLanguagesCallback(callback2), 0 ) # Always pick first one, we should get away with that. lang_id = langs[0] if with_data: hResource = ctypes.windll.kernel32.FindResourceA(hModule, lpName, lpType) size = ctypes.windll.kernel32.SizeofResource(hModule, hResource) hData = ctypes.windll.kernel32.LoadResource(hModule, hResource) try: ptr = ctypes.windll.kernel32.LockResource(hData) result.append((lpType, lpName, lang_id, ctypes.string_at(ptr, size))) finally: ctypes.windll.kernel32.FreeResource(hData) else: result.append((lpName, lang_id)) return True for resource_kind in resource_kinds: EnumResourceNames(hmodule, resource_kind, EnumResourceNameCallback(callback), 0) FreeLibrary(hmodule) return result def _openFileWindowsResources(filename): fullpath = os.path.abspath(filename) if type(filename) is str and str is bytes: BeginUpdateResource = ctypes.windll.kernel32.BeginUpdateResourceA BeginUpdateResource.argtypes = [ctypes.wintypes.LPCSTR, ctypes.wintypes.BOOL] else: BeginUpdateResource = ctypes.windll.kernel32.BeginUpdateResourceW BeginUpdateResource.argtypes = [ctypes.wintypes.LPCWSTR, ctypes.wintypes.BOOL] BeginUpdateResource.restype = ctypes.wintypes.HANDLE update_handle = BeginUpdateResource(fullpath, False) if not update_handle: raise ctypes.WinError() return update_handle def _closeFileWindowsResources(update_handle): EndUpdateResource = ctypes.windll.kernel32.EndUpdateResourceA EndUpdateResource.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.BOOL] EndUpdateResource.restype = ctypes.wintypes.BOOL ret = EndUpdateResource(update_handle, False) if not ret: raise ctypes.WinError() def _updateWindowsResource(update_handle, resource_kind, res_name, lang_id, data): if data is None: size = 0 else: size = len(data) assert type(data) is bytes UpdateResourceA = ctypes.windll.kernel32.UpdateResourceA UpdateResourceA.argtypes = [ ctypes.wintypes.HANDLE, ctypes.wintypes.LPVOID, ctypes.wintypes.LPVOID, ctypes.wintypes.WORD, ctypes.wintypes.LPVOID, ctypes.wintypes.DWORD, ] ret = UpdateResourceA(update_handle, resource_kind, res_name, lang_id, data, size) if not ret: raise ctypes.WinError() def deleteWindowsResources(filename, resource_kind, res_names): update_handle = _openFileWindowsResources(filename) for res_name, lang_id in res_names: _updateWindowsResource(update_handle, resource_kind, res_name, lang_id, None) _closeFileWindowsResources(update_handle) def copyResourcesFromFileToFile(source_filename, target_filename, resource_kinds): """Copy resources from one file to another. Args: source_filename - filename where the resources are taken from target_filename - filename where the resources are added to resource_kinds - tuple of numeric values indicating types of resources Returns: int - amount of resources copied, in case you want report Notes: Only windows resources are handled. Will not touch target filename unless there are resources in the source. """ res_data = getResourcesFromDLL( filename=source_filename, resource_kinds=resource_kinds, with_data=True ) if res_data: update_handle = _openFileWindowsResources(target_filename) for resource_kind, res_name, lang_id, data in res_data: assert resource_kind in resource_kinds # Not seeing the point at this time really, but seems to cause troubles otherwise. lang_id = 0 _updateWindowsResource( update_handle, resource_kind, res_name, lang_id, data ) _closeFileWindowsResources(update_handle) return len(res_data) def addResourceToFile(target_filename, data, resource_kind, lang_id, res_name, logger): max_attempts = 5 for attempt in range(1, max_attempts + 1): update_handle = _openFileWindowsResources(target_filename) _updateWindowsResource(update_handle, resource_kind, res_name, lang_id, data) try: _closeFileWindowsResources(update_handle) except OSError as e: if e.errno == 110: logger.warning( """ Failed to add resources to file %r in attempt %d. Disable Anti-Virus, e.g. Windows Defender for build folders. Retrying after a second of delay.""" % (target_filename, attempt) ) else: logger.warning( """ Failed to add resources to file %r in attempt %d with error code %d. Disable Anti-Virus, e.g. Windows Defender for build folders. Retrying after a second of delay.""" % (target_filename, attempt, e.errno) ) time.sleep(1) continue else: if attempt != 1: logger.warning( "Succeeded with resource update in attempt %d." % attempt ) break else: logger.sysexit("Failed to update resources, the result is unusable.") class WindowsExecutableManifest(object): def __init__(self, template): self.tree = TreeXML.fromString(template) def addResourceToFile(self, filename, logger): manifest_data = TreeXML.toBytes(self.tree, indent=False) addResourceToFile( target_filename=filename, data=manifest_data, resource_kind=RT_MANIFEST, res_name=1, lang_id=0, logger=logger, ) def addUacAdmin(self): """Add indication, the binary should request admin rights.""" self._getRequestedExecutionLevelNode().attrib["level"] = "requireAdministrator" def addUacUiAccess(self): """Add indication, the binary be allowed for remote desktop.""" self._getRequestedExecutionLevelNode().attrib["uiAccess"] = "true" def _getTrustInfoNode(self): # To lazy to figure out proper usage of namespaces, this is good enough for now. for child in self.tree: if child.tag == "{urn:schemas-microsoft-com:asm.v3}trustInfo": return child def _getTrustInfoSecurityNode(self): return self._getTrustInfoNode()[0] def _getRequestedPrivilegesNode(self): # To lazy to figure out proper usage of namespaces, this is good enough for now. for child in self._getTrustInfoSecurityNode(): if child.tag == "{urn:schemas-microsoft-com:asm.v3}requestedPrivileges": return child def _getRequestedExecutionLevelNode(self): # To lazy to figure out proper usage of namespaces, this is good enough for now. for child in self._getRequestedPrivilegesNode(): if child.tag == "{urn:schemas-microsoft-com:asm.v3}requestedExecutionLevel": return child def getWindowsExecutableManifest(filename): manifests_data = getResourcesFromDLL( filename=filename, resource_kinds=(RT_MANIFEST,), with_data=True ) if manifests_data: return WindowsExecutableManifest(manifests_data[0][-1]) else: return None def _getDefaultWindowsExecutableTrustInfo(): return """\ """ def getDefaultWindowsExecutableManifest(): # Note: Supported OS are lied about by CPython. template = ( """\ %s """ % _getDefaultWindowsExecutableTrustInfo() ) return WindowsExecutableManifest(template) class VsFixedFileInfoStructure(ctypes.Structure): _fields_ = [ ("dwSignature", ctypes.c_uint32), # 0xFEEF04BD ("dwStructVersion", ctypes.c_uint32), ("dwFileVersionMS", ctypes.c_uint32), ("dwFileVersionLS", ctypes.c_uint32), ("dwProductVersionMS", ctypes.c_uint32), ("dwProductVersionLS", ctypes.c_uint32), ("dwFileFlagsMask", ctypes.c_uint32), ("dwFileFlags", ctypes.c_uint32), ("dwFileOS", ctypes.c_uint32), ("dwFileType", ctypes.c_uint32), ("dwFileSubtype", ctypes.c_uint32), ("dwFileDateMS", ctypes.c_uint32), ("dwFileDateLS", ctypes.c_uint32), ] def convertStructureToBytes(c_value): """Convert ctypes structure to bytes for output.""" result = (ctypes.c_char * ctypes.sizeof(c_value)).from_buffer_copy(c_value) r = b"".join(result) assert len(result) == ctypes.sizeof(c_value) return r def _makeVersionInfoStructure(product_version, file_version, file_date, is_exe): return VsFixedFileInfoStructure( dwSignature=0xFEEF04BD, dwFileVersionMS=file_version[0] << 16 | (file_version[1] & 0xFFFF), dwFileVersionLS=file_version[2] << 16 | (file_version[3] & 0xFFFF), dwProductVersionMS=product_version[0] << 16 | (product_version[1] & 0xFFFF), dwProductVersionLS=product_version[2] << 16 | (product_version[3] & 0xFFFF), dwFileFlagsMask=0x3F, dwFileFlags=0, # TODO: Could be interesting VS_FF_DEBUG and VS_FF_PRERELEASE. dwFileOS=4, # NT or higher, hasn't been changed in a long time. dwFileType=1 if is_exe else 2, # dwFileSubtype=0, # Not applicable for DLL or EXE, only drivers use this. dwFileDateMS=file_date[0], dwFileDateLS=file_date[1], ) def _getVersionString(value): """Encodes string for version information string tables. Arguments: value - string to encode Returns: bytes - value encoded as utf-16le """ return value.encode("utf-16le") class VersionResourceHeader(ctypes.Structure): _fields_ = [ ("full_length", ctypes.c_short), ("item_size", ctypes.c_short), ("type", ctypes.c_short), ] def _makeVersionStringEntry(key, value): key_data = _getVersionString(key) value_data = _getVersionString(value) value_size = len(value_data) + 2 key_size = 6 + len(key_data) + 2 pad = b"\0\0" if key_size % 4 else b"" full_size = key_size + len(pad) + value_size header_data = convertStructureToBytes( VersionResourceHeader( full_length=full_size, item_size=value_size, type=1, ) ) return header_data + key_data + b"\0\0" + pad + value_data + b"\0\0" def _makeVersionStringTable(values): block_name = _getVersionString("000004b0") size = 6 + len(block_name) + 2 pad = b"\0\0" if size % 4 else b"" parts = [] for key, value in values.items(): chunk = _makeVersionStringEntry(key, value) if len(chunk) % 4: chunk += b"\0\0" parts.append(chunk) block_data = b"".join(parts) size += len(block_data) header_data = convertStructureToBytes( VersionResourceHeader( full_length=size, item_size=0, type=1, ) ) return header_data + block_name + b"\0\0" + pad + block_data def _makeVersionStringBlock(values): block_name = _getVersionString("StringFileInfo") size = 6 + len(block_name) + 2 pad = b"\0\0" if size % 4 else b"" block_data = _makeVersionStringTable(values) size = size + len(pad) + len(block_data) header_data = convertStructureToBytes( VersionResourceHeader( full_length=size, item_size=0, type=1, ) ) return header_data + block_name + b"\0\0" + pad + block_data def _makeVarFileInfoStruct(): block_name = _getVersionString("Translation") size = 6 + len(block_name) + 2 pad = b"\0\0" if size % 4 else b"" values = [0, 1200] # Language and code page block_data = struct.pack("hh", *values) block_size = len(block_data) size += len(pad) + block_size header_data = convertStructureToBytes( VersionResourceHeader( full_length=size, item_size=block_size, type=0, ) ) return header_data + block_name + b"\0\0" + pad + block_data def _makeVarFileInfoBlock(): block_name = _getVersionString("VarFileInfo") size = 6 + len(block_name) + 2 pad = b"\0\0" if size % 4 else b"" block_data = _makeVarFileInfoStruct() size += len(pad) + len(block_data) header_data = convertStructureToBytes( VersionResourceHeader( full_length=size, item_size=0, type=1, ) ) return header_data + block_name + b"\0\0" + pad + block_data def makeVersionInfoResource( string_values, product_version, file_version, file_date, is_exe ): # Every item has name and gets padded. block_name = _getVersionString("VS_VERSION_INFO") size = 6 + len(block_name) + 2 pad1 = b"\0\0" if size % 4 else b"" # First create the static C structure data version_info = _makeVersionInfoStructure( product_version=product_version, file_version=file_version, file_date=file_date, is_exe=is_exe, ) version_data = convertStructureToBytes(version_info) version_size = len(version_data) size += len(pad1) + version_size pad2 = b"\0\0" if size % 4 else b"" block_data = _makeVersionStringBlock(string_values) + _makeVarFileInfoBlock() size += len(pad2) + len(block_data) header_data = convertStructureToBytes( VersionResourceHeader( full_length=size, item_size=version_size, type=0, ) ) return header_data + block_name + b"\0\0" + pad1 + version_data + pad2 + block_data def addVersionInfoResource( string_values, product_version, file_version, file_date, is_exe, result_filename, logger, ): if product_version is None: product_version = file_version if file_version is None: file_version = product_version assert product_version assert file_version assert "CompanyName" in string_values if "FileDescription" not in string_values: string_values["FileDescription"] = "Description" if "ProductVersion" not in string_values: string_values["ProductVersion"] = ".".join(str(d) for d in product_version) if "FileVersion" not in string_values: string_values["FileVersion"] = ".".join(str(d) for d in file_version) if "OriginalFilename" not in string_values: string_values["OriginalFilename"] = os.path.basename(result_filename) if "InternalName" not in string_values: string_values["InternalName"] = string_values["OriginalFilename"].rsplit( ".", 1 )[0] if "ProductName" not in string_values: string_values["ProductName"] = string_values["InternalName"] if "FileDescription" not in string_values: string_values["FileDescription"] = string_values["OriginalFilename"] ver_info = makeVersionInfoResource( string_values=string_values, product_version=product_version, file_version=file_version, file_date=file_date, is_exe=is_exe, ) addResourceToFile( target_filename=result_filename, data=ver_info, resource_kind=RT_VERSION, res_name=1, lang_id=0, logger=logger, ) return string_values Nuitka-0.6.19.1/nuitka/utils/Importing.py0000600000372100037210000001430214166627112025244 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Helper to import a file as a module. Used for Nuitka plugins and for test code. """ import os import sys from nuitka.PythonVersions import python_version from nuitka.Tracing import general def _importFilePy3NewWay(filename): """Import a file for Python versions 3.5+.""" import importlib.util # pylint: disable=I0021,import-error,no-name-in-module spec = importlib.util.spec_from_file_location( os.path.basename(filename).split(".")[0], filename ) user_plugin_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(user_plugin_module) return user_plugin_module def _importFilePy3OldWay(filename): """Import a file for Python versions before 3.5.""" from importlib.machinery import ( # pylint: disable=I0021,import-error,no-name-in-module SourceFileLoader, ) # pylint: disable=I0021,deprecated-method return SourceFileLoader(filename, filename).load_module(filename) def importFilePy2(filename): """Import a file for Python version 2.""" import imp basename = os.path.splitext(os.path.basename(filename))[0] return imp.load_source(basename, filename) def importFileAsModule(filename): """Import Python module given as a file name. Notes: Provides a Python version independent way to import any script files. Args: filename: complete path of a Python script Returns: Imported Python module with code from the filename. """ if python_version < 0x300: return importFilePy2(filename) elif python_version < 0x350: return _importFilePy3OldWay(filename) else: return _importFilePy3NewWay(filename) _all_suffixes = None def getAllModuleSuffixes(): # Using global here, as this is for caching only # pylint: disable=global-statement global _all_suffixes if _all_suffixes is None: if python_version < 0x300: import imp _all_suffixes = [] for suffix, _mode, _module_type in imp.get_suffixes(): _all_suffixes.append(suffix) else: import importlib.machinery # pylint: disable=I0021,import-error,no-name-in-module _all_suffixes = ( importlib.machinery.EXTENSION_SUFFIXES + importlib.machinery.SOURCE_SUFFIXES + importlib.machinery.BYTECODE_SUFFIXES ) _all_suffixes = tuple(_all_suffixes) return _all_suffixes _shared_library_suffixes = None def getSharedLibrarySuffixes(): # Using global here, as this is for caching only # pylint: disable=global-statement global _shared_library_suffixes if _shared_library_suffixes is None: if python_version < 0x300: import imp _shared_library_suffixes = [] for suffix, _mode, module_type in imp.get_suffixes(): if module_type == imp.C_EXTENSION: _shared_library_suffixes.append(suffix) else: import importlib.machinery # pylint: disable=I0021,import-error,no-name-in-module _shared_library_suffixes = importlib.machinery.EXTENSION_SUFFIXES _shared_library_suffixes = tuple(_shared_library_suffixes) return _shared_library_suffixes def getSharedLibrarySuffix(preferred): if preferred and python_version >= 0x300: return getSharedLibrarySuffixes()[0] result = None for suffix in getSharedLibrarySuffixes(): if result is None or len(suffix) < len(result): result = suffix return result def importFromFolder(logger, module_name, path, must_exist, message): """Import a module from a folder by adding it temporarily to sys.path""" # Circular dependency here from .FileOperations import isPathBelow if module_name in sys.modules: # May already be loaded, but the wrong one from a pth of clcache if module_name != "clcache" or isPathBelow( path=path, filename=sys.modules[module_name].__file__ ): return sys.modules[module_name] else: del sys.modules[module_name] # Temporarily add the inline path of the module to the import path. sys.path.insert(0, path) # Handle case without inline copy too. try: return __import__(module_name) except (ImportError, SyntaxError) as e: if not must_exist: return None exit_message = ( "Error, expected inline copy of %r to be in %r, error was: %r." % (module_name, path, e) ) if message is not None: exit_message += "\n" + message logger.sysexit(exit_message) finally: # Do not forget to remove it from sys.path again. del sys.path[0] def importFromInlineCopy(module_name, must_exist): """Import a module from the inline copy stage.""" folder_name = os.path.normpath( os.path.join( os.path.dirname(__file__), "..", "build", "inline_copy", module_name ) ) candidate_27 = folder_name + "_27" candidate_35 = folder_name + "_35" # Use specific versions if needed. if python_version < 0x300 and os.path.exists(candidate_27): folder_name = candidate_27 elif python_version < 0x360 and os.path.exists(candidate_35): folder_name = candidate_35 return importFromFolder( module_name=module_name, path=folder_name, must_exist=must_exist, message=None, logger=general, ) Nuitka-0.6.19.1/nuitka/utils/Execution.py0000600000372100037210000003350514166627112025245 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Program execution related stuff. Basically a layer for os, subprocess, shutil to come together. It can find binaries (needed for exec) and run them capturing outputs. """ import os from contextlib import contextmanager from nuitka.__past__ import ( # pylint: disable=I0021,redefined-builtin WindowsError, subprocess, ) from nuitka.PythonVersions import python_version from nuitka.Tracing import general from .Download import getCachedDownloadedMinGW64 from .FileOperations import getExternalUsePath from .Utils import getArchitecture, getOS, isWin32Windows # Cache, so we avoid repeated command lookups. _executable_command_cache = {} def _getExecutablePath(filename, search_path): # Append ".exe" suffix on Windows if not already present. if getOS() == "Windows" and not filename.lower().endswith(".exe"): filename += ".exe" # Now check in each path element, much like the shell will. path_elements = search_path.split(os.pathsep) for path_element in path_elements: path_element = path_element.strip('"') full = os.path.join(path_element, filename) if os.path.exists(full): return full def getExecutablePath(filename): """Find an execute in PATH environment.""" # Search in PATH environment. search_path = os.environ.get("PATH", "") key = (filename, search_path) if key not in _executable_command_cache: _executable_command_cache[key] = _getExecutablePath(filename, search_path) return _executable_command_cache[key] def isExecutableCommand(command): return getExecutablePath(command) is not None def getPythonExePathWindows(search, arch): """Find Python on Windows.""" # Shortcuts for the default installation directories, to avoid going to # registry at all unless necessary. Any Python2 will do for Scons, so it # might be avoided entirely. # Windows only code, pylint: disable=I0021,import-error,undefined-variable try: import _winreg as winreg except ImportError: import winreg # lint:ok if arch is None: if getArchitecture() == "x86": arches = (winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY) else: arches = (winreg.KEY_WOW64_64KEY, winreg.KEY_WOW64_32KEY) elif arch == "x86": arches = (winreg.KEY_WOW64_32KEY,) elif arch == "x86_64": arches = (winreg.KEY_WOW64_64KEY,) else: assert False, arch for hkey_branch in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER): for arch_key in arches: try: key = winreg.OpenKey( hkey_branch, r"SOFTWARE\Python\PythonCore\%s\InstallPath" % search, 0, winreg.KEY_READ | arch_key, ) candidate = os.path.join(winreg.QueryValue(key, ""), "python.exe") except WindowsError: continue if os.path.exists(candidate): return candidate class NuitkaCalledProcessError(subprocess.CalledProcessError): def __init__(self, retcode, cmd, output, stderr): # False alarm, pylint: disable=super-init-not-called subprocess.CalledProcessError(self, retcode, cmd) # Python2 doesn't have this otherwise, but needs it. self.stderr = stderr self.output = output self.cmd = cmd self.returncode = retcode def __str__(self): result = subprocess.CalledProcessError.__str__(self) if self.output: result += " Output was %r." % self.output.strip() if self.stderr: result += " Error was %r." % self.stderr.strip() return result def check_output(*popenargs, **kwargs): """Call a process and check result code. This is for Python 2.6 compatibility, which doesn't have that in its standard library. Note: We use same name as in Python stdlib, violating our rules to make it more recognizable what this does. """ if "stdout" in kwargs: raise ValueError("stdout argument not allowed, it will be overridden.") if "stderr" not in kwargs: kwargs["stderr"] = subprocess.PIPE process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) output, stderr = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise NuitkaCalledProcessError(retcode, cmd, output=output, stderr=stderr) return output def check_call(*popenargs, **kwargs): """Call a process and check result code. Note: This catches the error, and makes it nicer, and an error exit. So this is for tooling only. Note: We use same name as in Python stdlib, violating our rules to make it more recognizable what this does. """ try: subprocess.check_call(*popenargs, **kwargs) except OSError: general.sysexit( "Error, failed to execute '%s'. Is it installed?" % popenargs[0] ) def callProcess(*popenargs, **kwargs): """Call a process and return result code.""" subprocess.call(*popenargs, **kwargs) @contextmanager def withEnvironmentPathAdded(env_var_name, *paths): assert os.path.sep not in env_var_name paths = [path for path in paths if path] path = os.pathsep.join(paths) if path: if str is not bytes and type(path) is bytes: path = path.decode("utf8") if env_var_name in os.environ: old_path = os.environ[env_var_name] os.environ[env_var_name] += os.pathsep + path else: old_path = None os.environ[env_var_name] = path yield if path: if old_path is None: del os.environ[env_var_name] else: os.environ[env_var_name] = old_path @contextmanager def withEnvironmentVarOverriden(env_var_name, value): """Change an environment and restore it after context.""" if env_var_name in os.environ: old_value = os.environ[env_var_name] else: old_value = None if value is not None: os.environ[env_var_name] = value elif old_value is not None: del os.environ[env_var_name] yield if old_value is None: if value is not None: del os.environ[env_var_name] else: os.environ[env_var_name] = old_value @contextmanager def withEnvironmentVarsOverriden(mapping): """Change multiple environment variables and restore them after context.""" old_values = {} for env_var_name, value in mapping.items(): if env_var_name in os.environ: old_values[env_var_name] = os.environ[env_var_name] else: old_values[env_var_name] = None if value is not None: os.environ[env_var_name] = value elif old_values[env_var_name] is not None: del os.environ[env_var_name] yield for env_var_name, value in mapping.items(): if old_values[env_var_name] is None: if value is not None: del os.environ[env_var_name] else: os.environ[env_var_name] = old_values[env_var_name] def wrapCommandForDebuggerForExec(*args): """Wrap a command for system debugger to call exec Args: args: (list of str) args for call to be debugged Returns: args tuple with debugger command inserted Notes: Currently only gdb and lldb are supported, but adding more debuggers would be very welcome. """ gdb_path = getExecutablePath("gdb") # Windows extra ball, attempt the downloaded one. if isWin32Windows(): from nuitka.Options import assumeYesForDownloads mingw64_gcc_path = getCachedDownloadedMinGW64( target_arch=getArchitecture(), assume_yes_for_downloads=assumeYesForDownloads(), ) with withEnvironmentPathAdded("PATH", os.path.dirname(mingw64_gcc_path)): gdb_path = getExecutablePath("gdb") if gdb_path is None: lldb_path = getExecutablePath("lldb") if lldb_path is None: general.sysexit("Error, no 'gdb' or 'lldb' binary found in path.") if gdb_path is not None: args = (gdb_path, "gdb", "-ex=run", "-ex=where", "-ex=quit", "--args") + args else: args = (lldb_path, "lldb", "-o", "run", "-o", "bt", "-o", "quit", "--") + args return args def wrapCommandForDebuggerForSubprocess(*args): """Wrap a command for system debugger with subprocess module. Args: args: (list of str) args for call to be debugged Returns: args tuple with debugger command inserted Notes: Currently only gdb and lldb are supported, but adding more debuggers would be very welcome. """ args = wrapCommandForDebuggerForExec(*args) # Discard exec only argument. args = args[0:1] + args[2:] return args def getPythonInstallPathWindows(supported, decider=lambda x: True): """Find suitable Python on Windows. Go over a list of provided, supported versions, and first try a few guesses for their paths, then look into registry for user or system wide installations. The decider may reject a Python, then the search is continued, otherwise it's returned. """ # Many cases to deal with, due to arches, caching, etc. # pylint: disable=too-many-branches seen = set() # Shortcuts for the default installation directories, to avoid going to # registry at all unless necessary. Any Python2 will do for Scons, so it # might be avoided entirely. for search in supported: candidate = r"C:\Python%s\python.exe" % search.replace(".", "") if os.path.isfile(candidate): install_dir = os.path.normcase(os.path.dirname(candidate)) if decider(install_dir): return install_dir seen.add(install_dir) # Windows only code, pylint: disable=I0021,import-error,undefined-variable if python_version < 0x300: import _winreg as winreg # pylint: disable=I0021,import-error,no-name-in-module else: import winreg # pylint: disable=I0021,import-error,no-name-in-module for search in supported: for hkey_branch in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER): for arch_key in (0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY): for suffix in "", "-32": try: key = winreg.OpenKey( hkey_branch, r"SOFTWARE\Python\PythonCore\%s%s\InstallPath" % (search, suffix), 0, winreg.KEY_READ | arch_key, ) install_dir = os.path.normpath(winreg.QueryValue(key, "")) except WindowsError: pass else: if install_dir not in seen: if decider(install_dir): return install_dir seen.add(install_dir) def getNullOutput(): try: return subprocess.NULLDEV except AttributeError: return open(os.devnull, "wb") def getNullInput(): try: return subprocess.NULLDEV except AttributeError: # File is supposed to stay open, pylint: disable=consider-using-with subprocess.NULLDEV = open(os.devnull, "rb") return subprocess.NULLDEV def executeToolChecked(logger, command, absence_message, stderr_filter=None): """Execute external tool, checking for success and no error outputs, returning result.""" tool = command[0] if not isExecutableCommand(tool): logger.sysexit(absence_message) # Allow to avoid repeated scans in PATH for the tool. command[0] = getExecutablePath(tool) process = subprocess.Popen( command, stdin=getNullInput(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, ) stdout, stderr = process.communicate() result = process.poll() if stderr_filter is not None: stderr = stderr_filter(stderr) if result != 0: logger.sysexit("Error, call to %r failed: %s -> %s." % (tool, command, stderr)) elif stderr: logger.sysexit( "Error, call to %r gave warnings: %s -> %s." % (tool, command, stderr) ) return stdout def executeProcess( command, env=None, needs_stdin=False, shell=False, external_cwd=False ): if not env: env = os.environ process = subprocess.Popen( command, stdin=subprocess.PIPE if needs_stdin else getNullInput(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, # On Windows, closing file descriptions is now working with capturing outputs. close_fds=not isWin32Windows(), env=env, # For tools that want short paths to work. cwd=getExternalUsePath(os.getcwd()) if external_cwd else None, ) stdout, stderr = process.communicate() exit_code = process.wait() return stdout, stderr, exit_code Nuitka-0.6.19.1/nuitka/utils/CStrings.py0000600000372100037210000000557714166627112025046 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ C string encoding This contains the code to create string literals for C to represent the given values. """ import codecs import re def _identifierEncode(c): """Nuitka handler to encode unicode to ASCII identifiers for C compiler.""" return "$%02x$" % ord(c.object[c.end - 1]), c.end codecs.register_error("c_identifier", _identifierEncode) def _encodePythonStringToC(value): """Encode a string, so that it gives a C string literal. This doesn't handle limits. """ assert type(value) is bytes, type(value) result = "" octal = False for c in value: if str is bytes: cv = ord(c) else: cv = c if c in b'\\\t\r\n"?': result += r"\%o" % cv octal = True elif 32 <= cv <= 127: if octal and c in b"0123456789": result += '" "' result += chr(cv) octal = False else: result += r"\%o" % cv octal = True result = result.replace('" "\\', "\\") return '"%s"' % result def encodePythonStringToC(value): """Encode a string, so that it gives a C string literal.""" # Not all compilers allow arbitrary large C strings, therefore split it up # into chunks. That changes nothing to the meanings, but is easier on the # parser. Currently only MSVC is known to have this issue, but the # workaround can be used universally. result = _encodePythonStringToC(value[:16000]) value = value[16000:] while value: result += " " result += _encodePythonStringToC(value[:16000]) value = value[16000:] return result def encodePythonIdentifierToC(value): """Encode an identifier from a given Python string.""" # Python identifiers allow almost of characters except a very # few, much more than C identifiers support. This attempts to # be bi-directional, so we can reverse it. def r(match): c = match.group() if c == ".": return "$" else: return "$$%d$" % ord(c) return "".join(re.sub("[^a-zA-Z0-9_]", r, c) for c in value) Nuitka-0.6.19.1/nuitka/utils/Jinja2.py0000600000372100037210000001036014166627112024411 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Jinja folklore wrappers and handling of inline copy usage. """ import sys from nuitka.__past__ import unicode from .Importing import importFromInlineCopy environments = {} def unlikely_if(value): if value: return "unlikely" else: return "" def unlikely_or_likely_from(value): if value: return "unlikely" else: return "likely" _jinja2 = None # For pkg resources, we need to keep a reference, after we delete it from # "sys.modules" again. _loaded_pkg_resources = None def getJinja2Package(): global _jinja2, _loaded_pkg_resources # singleton package using a cache, pylint: disable=global-statement # Import dependencies, sadly we get to manage this ourselves. importFromInlineCopy("markupsafe", must_exist=True) # Newer Jinja2 may not use it, but we load it and remove it, so it # does not interfere with anything else. if "pkg_resources" not in sys.modules: _loaded_pkg_resources = importFromInlineCopy("pkg_resources", must_exist=False) _jinja2 = importFromInlineCopy("jinja2", must_exist=True) # Unload if it was us loading it, as the inline copy is incomplete. if _loaded_pkg_resources is not None: del sys.modules["pkg_resources"] return _jinja2 def getEnvironment(package_name, template_subdir, extensions): key = package_name, template_subdir, extensions if key not in environments: jinja2 = getJinja2Package() if package_name is not None: loader = jinja2.PackageLoader(package_name, template_subdir) elif template_subdir is not None: loader = jinja2.FileSystemLoader(template_subdir) else: loader = jinja2.BaseLoader() env = jinja2.Environment( loader=loader, extensions=extensions, trim_blocks=True, lstrip_blocks=True, ) # For shared global functions. env.globals.update( { "unlikely_if": unlikely_if, "unlikely_or_likely_from": unlikely_or_likely_from, } ) env.undefined = jinja2.StrictUndefined environments[key] = env return environments[key] def getTemplate( package_name, template_name, template_subdir="templates", extensions=() ): return getEnvironment( package_name=package_name, template_subdir=template_subdir, extensions=extensions, ).get_template(template_name) def getTemplateC( package_name, template_name, template_subdir="templates_c", extensions=() ): return getEnvironment( package_name=package_name, template_subdir=template_subdir, extensions=extensions, ).get_template(template_name) def getTemplateFromString(template_str): return getEnvironment( package_name=None, template_subdir=None, extensions=() ).from_string(template_str.strip()) _template_cache = {} def renderTemplateFromString(template_str, **kwargs): # Avoid recreating templates, hoping to save some time. if template_str not in _template_cache: _template_cache[template_str] = getTemplateFromString(template_str) result = _template_cache[template_str].render(**kwargs) # Jinja produces unicode value, but our emission wants str, or else # it messes up. TODO: We might switch to unicode one day or bytes # for Python3 one day, but that seems to much work. if str is not unicode: return result.encode("utf8") else: return result Nuitka-0.6.19.1/nuitka/utils/MemoryUsage.py0000600000372100037210000001025514166627112025534 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tools for tracing memory usage at compiled time. """ from nuitka.Tracing import printLine from .Utils import isMacOS, isWin32Windows def getOwnProcessMemoryUsage(): """Memory usage of own process in bytes.""" if isWin32Windows(): # adapted from http://code.activestate.com/recipes/578513 import ctypes.wintypes # Lets allow this to match Windows API it reflects, # pylint: disable=invalid-name class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): _fields_ = [ ("cb", ctypes.wintypes.DWORD), ("PageFaultCount", ctypes.wintypes.DWORD), ("PeakWorkingSetSize", ctypes.c_size_t), ("WorkingSetSize", ctypes.c_size_t), ("QuotaPeakPagedPoolUsage", ctypes.c_size_t), ("QuotaPagedPoolUsage", ctypes.c_size_t), ("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t), ("QuotaNonPagedPoolUsage", ctypes.c_size_t), ("PagefileUsage", ctypes.c_size_t), ("PeakPagefileUsage", ctypes.c_size_t), ("PrivateUsage", ctypes.c_size_t), ] GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo GetProcessMemoryInfo.argtypes = [ ctypes.wintypes.HANDLE, ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX), ctypes.wintypes.DWORD, ] GetProcessMemoryInfo.restype = ctypes.wintypes.BOOL counters = PROCESS_MEMORY_COUNTERS_EX() rv = GetProcessMemoryInfo( ctypes.windll.kernel32.GetCurrentProcess(), ctypes.byref(counters), ctypes.sizeof(counters), ) if not rv: raise ctypes.WinError() return counters.PrivateUsage else: import resource # Posix only code, pylint: disable=I0021,import-error # The value is from "getrusage", which has OS dependent scaling, at least # macOS and Linux are different. Others maybe too. if isMacOS(): factor = 1 else: factor = 1024 return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * factor def getHumanReadableProcessMemoryUsage(value=None): if value is None: value = getOwnProcessMemoryUsage() if abs(value) < 1024 * 1014: return "%.2f KB (%d bytes)" % (value / 1024.0, value) elif abs(value) < 1024 * 1014 * 1024: return "%.2f MB (%d bytes)" % (value / (1024 * 1024.0), value) elif abs(value) < 1024 * 1014 * 1024 * 1024: return "%.2f GB (%d bytes)" % (value / (1024 * 1024 * 1024.0), value) else: return "%d bytes" % value class MemoryWatch(object): def __init__(self): self.start = getOwnProcessMemoryUsage() self.stop = None def finish(self): self.stop = getOwnProcessMemoryUsage() def asStr(self): return getHumanReadableProcessMemoryUsage(self.stop - self.start) def startMemoryTracing(): try: import tracemalloc except ImportError: pass else: tracemalloc.start() def showMemoryTrace(): try: import tracemalloc except ImportError: pass else: snapshot = tracemalloc.take_snapshot() stats = snapshot.statistics("lineno") printLine("Top 50 memory allocations:") for count, stat in enumerate(stats): if count == 50: break printLine(stat) Nuitka-0.6.19.1/nuitka/utils/Download.py0000600000372100037210000001246514166627112025053 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Download utilities and extract locally when allowed. Mostly used on Windows, for dependency walker and ccache binaries. """ import os from nuitka import Tracing from nuitka.__past__ import raw_input, urlretrieve from .AppDirs import getAppDir from .FileOperations import addFileExecutablePermission, deleteFile, makePath def getCachedDownload( url, binary, flatten, is_arch_specific, specifity, message, reject, assume_yes_for_downloads, ): # Many branches to deal with, pylint: disable=too-many-branches,too-many-statements nuitka_app_dir = getAppDir() nuitka_app_dir = os.path.join( nuitka_app_dir, os.path.basename(binary).replace(".exe", "") ) if is_arch_specific: nuitka_app_dir = os.path.join(nuitka_app_dir, is_arch_specific) if specifity: nuitka_app_dir = os.path.join(nuitka_app_dir, specifity) download_path = os.path.join(nuitka_app_dir, os.path.basename(url)) exe_path = os.path.join(nuitka_app_dir, binary) makePath(nuitka_app_dir) if not os.path.isfile(download_path) and not os.path.isfile(exe_path): if assume_yes_for_downloads: reply = "y" else: Tracing.printLine( """\ %s Is it OK to download and put it in '%s'. No installer needed, cached, one time question. Proceed and download? [Yes]/No """ % (message, nuitka_app_dir) ) Tracing.flushStandardOutputs() try: reply = raw_input() except EOFError: reply = "no" if reply.lower() in ("no", "n"): if reject is not None: Tracing.general.sysexit(reject) else: Tracing.general.info("Downloading '%s'." % url) try: urlretrieve(url, download_path) except Exception: # Any kind of error, pylint: disable=broad-except try: urlretrieve(url.replace("https://", "http://"), download_path) except Exception: # Any kind of error, pylint: disable=broad-except Tracing.general.sysexit( "Failed to download '%s'. Contents should manually be copied to '%s'." % (url, download_path) ) if not os.path.isfile(exe_path) and os.path.isfile(download_path): Tracing.general.info("Extracting to '%s'" % exe_path) import zipfile try: # Not all Python versions support using it as a context manager, pylint: disable=consider-using-with zip_file = zipfile.ZipFile(download_path) for zip_info in zip_file.infolist(): if zip_info.filename[-1] == "/": continue if flatten: zip_info.filename = os.path.basename(zip_info.filename) zip_file.extract(zip_info, nuitka_app_dir) except Exception: # Catching anything zip throws, pylint: disable=broad-except Tracing.general.info("Problem with the downloaded zip file, deleting it.") deleteFile(binary, must_exist=False) deleteFile(download_path, must_exist=True) Tracing.general.sysexit( "Error, need %r as extracted from %r." % (binary, url) ) # Check success here, and make sure it's executable. if os.path.isfile(exe_path): addFileExecutablePermission(exe_path) else: if reject: Tracing.general.sysexit(reject) exe_path = None return exe_path def getCachedDownloadedMinGW64(target_arch, assume_yes_for_downloads): # Large URLs, pylint: disable=line-too-long if target_arch == "x86_64": url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/11.2.0-12.0.1-9.0.0-r1/winlibs-x86_64-posix-seh-gcc-11.2.0-llvm-12.0.1-mingw-w64-9.0.0-r1.zip" binary = r"mingw64\bin\gcc.exe" else: url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/11.2.0-12.0.1-9.0.0-r1/winlibs-i686-posix-dwarf-gcc-11.2.0-llvm-12.0.1-mingw-w64-9.0.0-r1.zip" binary = r"mingw32\bin\gcc.exe" gcc_binary = getCachedDownload( url=url, is_arch_specific=target_arch, specifity=url.rsplit("/", 2)[1], binary=binary, flatten=False, message="Nuitka will use gcc from MinGW64 of winlibs to compile on Windows.", reject="Only this specific gcc is supported with Nuitka.", assume_yes_for_downloads=assume_yes_for_downloads, ) return gcc_binary Nuitka-0.6.19.1/nuitka/utils/InstanceCounters.py0000600000372100037210000000426014166627112026565 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Instance counter primitives We don't use a meta class as it's unnecessary complex, and portable meta classes have their difficulties, and want to count classes, who already have a meta class. This is going to expanded with time. """ from nuitka.Options import isShowMemory from nuitka.Tracing import printIndented, printLine counted_inits = {} counted_dels = {} def isCountingInstances(): return isShowMemory() def counted_init(init): if isShowMemory(): def wrapped_init(self, *args, **kw): name = self.__class__.__name__ assert type(name) is str if name not in counted_inits: counted_inits[name] = 0 counted_inits[name] += 1 init(self, *args, **kw) return wrapped_init else: return init def _wrapped_del(self): # This cannot be necessary, because in program finalization, the # global variables were assign to None. if counted_dels is None: return name = self.__class__.__name__ assert type(name) is str if name not in counted_dels: counted_dels[name] = 0 counted_dels[name] += 1 def counted_del(): assert isShowMemory() return _wrapped_del def printStats(): printLine("Init/del/alive calls:") for name, count in sorted(counted_inits.items()): dels = counted_dels.get(name, 0) printIndented(1, name, count, dels, count - dels) Nuitka-0.6.19.1/nuitka/utils/Shebang.py0000600000372100037210000000712014166627112024643 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Utils to work with shebang lines. """ import os import re def getShebangFromSource(source_code): """Given source code, extract the shebang (#!) part. Notes: This function is less relevant on Windows, because it will not use this method of determining the execution. Still scripts aimed at multiple platforms will contain it and it can be used to e.g. guess the Python version expected, if it is a Python script at all. There are variants of the function that will work on filenames instead. Args: source_code: The source code as a unicode string Returns: The binary and arguments that the kernel will use (Linux and compatible). """ if source_code.startswith("#!"): shebang = re.match(r"^#!\s*(.*?)\n", source_code) if shebang is not None: shebang = shebang.group(0).rstrip("\n") else: shebang = None return shebang def getShebangFromFile(filename): """Given a filename, extract the shebang (#!) part from it. Notes: This function is less relevant on Windows, because it will not use this method of determining the execution. Still scripts aimed at multiple platforms will contain it and it can be used to e.g. guess the Python version expected, if it is a Python script at all. There are variants of the function that will work on file content instead. Args: filename: The filename to get the shebang of Returns: The binary that the kernel will use (Linux and compatible). """ with open(filename, "rb") as f: source_code = f.readline() if str is not bytes: try: source_code = source_code.decode("utf8") except UnicodeDecodeError: source_code = "" return getShebangFromSource(source_code) def parseShebang(shebang): """Given a concrete shebang value, it will extract the binary used. Notes: This function is less relevant on Windows, because it will not use this method of determining the execution. This handles that many times people use `env` binary to search the PATH for an actual binary, e.g. `/usr/bin/env python3.7` where we would care most about the `python3.7` part and want to see through the `env` usage. Args: shebang: The shebang extracted with one of the methods to do so. Returns: The binary the kernel will use (Linux and compatible). """ parts = shebang.split() if os.path.basename(parts[0]) == "env": # This attempts to handle env with arguments and options. del parts[0] while parts[0].startswith("-"): del parts[0] while "=" in parts[0]: del parts[0] return parts[0][2:].lstrip(), parts[1:] Nuitka-0.6.19.1/nuitka/utils/WindowsFileUsage.py0000600000372100037210000002451614166627112026523 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This is work in progress and hangs unfortunately on some file handles. """ import ctypes.wintypes import os from nuitka.Tracing import my_print STATUS_INFO_LENGTH_MISMATCH = 0xC0000004 STATUS_BUFFER_OVERFLOW = 0x80000005 STATUS_INVALID_HANDLE = 0xC0000008 STATUS_BUFFER_TOO_SMALL = 0xC0000023 def getWindowsAllProcessandles(): """Return all process system handles.""" i = 2048 # Lets allow this to match Windows API it reflects, # pylint: disable=invalid-name class SYSTEM_HANDLE(ctypes.Structure): _fields_ = [ ("dwProcessId", ctypes.wintypes.DWORD), ("bObjectType", ctypes.wintypes.BYTE), ("bFlags", ctypes.wintypes.BYTE), ("wValue", ctypes.wintypes.WORD), ("pAddress", ctypes.wintypes.LPVOID), ("GrantedAccess", ctypes.wintypes.DWORD), ] ctypes.windll.ntdll.ZwQuerySystemInformation.argtypes = ( ctypes.c_ulong, ctypes.wintypes.LPVOID, ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong), ) ctypes.windll.ntdll.ZwQuerySystemInformation.restype = ctypes.c_ulong return_length = ctypes.c_ulong() while True: # Unknown ahead of time, we escalate size structure in order to work on older # Windows versions, that do not return a needed size indication. class SYSTEM_HANDLE_INFORMATION(ctypes.Structure): _fields_ = [("HandleCount", ctypes.c_ulong), ("Handles", SYSTEM_HANDLE * i)] buf = SYSTEM_HANDLE_INFORMATION() rc = ctypes.windll.ntdll.ZwQuerySystemInformation( 16, # SYSTEM_PROCESS_INFORMATION ctypes.byref(buf), ctypes.sizeof(buf), ctypes.byref(return_length), ) # Retry until it's large enough. if rc == STATUS_INFO_LENGTH_MISMATCH: i *= 2 continue if rc == 0: handles = {} for handle in buf.Handles[: buf.HandleCount]: if handle.dwProcessId in handles: handles[handle.dwProcessId].append(handle.wValue) else: handles[handle.dwProcessId] = [handle.wValue] return handles else: raise ctypes.WinError() def getWindowsFileHandleFilename(handle): # Lets allow this to match Windows API it reflects, # pylint: disable=invalid-name class FILE_NAME_INFORMATION(ctypes.Structure): _fields_ = [ ("FileNameLength", ctypes.wintypes.ULONG), ("FileName", ctypes.wintypes.WCHAR * 2048), ] class IO_STATUS_BLOCK(ctypes.Structure): class _STATUS(ctypes.Union): _fields_ = ( ("Status", ctypes.wintypes.DWORD), ("Pointer", ctypes.wintypes.LPVOID), ) _anonymous_ = ("_Status",) _fields_ = (("_Status", _STATUS), ("Information", ctypes.wintypes.WPARAM)) PIO_STATUS_BLOCK = ctypes.POINTER(IO_STATUS_BLOCK) ctypes.windll.ntdll.NtQueryInformationFile.argtypes = ( ctypes.wintypes.HANDLE, PIO_STATUS_BLOCK, ctypes.wintypes.LPVOID, ctypes.wintypes.ULONG, ctypes.wintypes.ULONG, ) ctypes.windll.ntdll.NtQueryInformationFile.restype = ctypes.wintypes.DWORD file_name_information = FILE_NAME_INFORMATION() iosb = IO_STATUS_BLOCK() rv = ctypes.windll.ntdll.NtQueryInformationFile( handle, ctypes.byref(iosb), ctypes.byref(file_name_information), 2048, 9, # FileNameInformation ) if rv == 0: return file_name_information.FileName else: return None def getWindowsAllProcessFileHandles(): # Incredibly complicated details, pylint: disable=too-many-branches,too-many-locals,too-many-statements # Lets allow this to match Windows API it reflects, # pylint: disable=invalid-name class LSA_UNICODE_STRING(ctypes.Structure): _fields_ = [ ("Length", ctypes.wintypes.USHORT), ("MaximumLength", ctypes.wintypes.USHORT), ("Buffer", ctypes.wintypes.LPWSTR), ] class PUBLIC_OBJECT_TYPE_INFORMATION(ctypes.Structure): _fields_ = [ ("Name", LSA_UNICODE_STRING), ("Reserved", ctypes.wintypes.ULONG * 100), ] ctypes.windll.ntdll.NtQueryObject.argtypes = [ ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.POINTER(PUBLIC_OBJECT_TYPE_INFORMATION), ctypes.wintypes.ULONG, ctypes.POINTER(ctypes.wintypes.ULONG), ] ctypes.windll.ntdll.NtQueryObject.restype = ctypes.wintypes.DWORD ctypes.windll.kernel32.OpenProcess.argtypes = [ ctypes.wintypes.DWORD, ctypes.wintypes.BOOL, ctypes.wintypes.DWORD, ] ctypes.windll.kernel32.OpenProcess.restype = ctypes.wintypes.HANDLE ctypes.windll.kernel32.GetCurrentProcess.restype = ctypes.wintypes.HANDLE ctypes.windll.kernel32.GetFileType.restype = ctypes.wintypes.DWORD ctypes.windll.kernel32.DuplicateHandle.argtypes = [ ctypes.wintypes.HANDLE, ctypes.wintypes.HANDLE, ctypes.wintypes.HANDLE, ctypes.wintypes.LPHANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.BOOL, ctypes.wintypes.DWORD, ] ctypes.windll.kernel32.DuplicateHandle.restype = ctypes.wintypes.BOOL DUPLICATE_SAME_ACCESS = 0x2 PROCESS_DUP_HANDLE = 0x0040 PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 ObjectTypeInformation = 2 psapi = ctypes.WinDLL("Psapi.dll") psapi.GetProcessImageFileNameW.restype = ctypes.wintypes.DWORD this_process = ctypes.windll.kernel32.GetCurrentProcess() this_process_id = ctypes.windll.kernel32.GetCurrentProcessId() for process, handles in getWindowsAllProcessandles().items(): # Ignore ourselves, we do not matter normally. if this_process_id == process: continue # Need to open processes first process_handle = ctypes.windll.kernel32.OpenProcess( PROCESS_DUP_HANDLE | PROCESS_QUERY_LIMITED_INFORMATION, True, process ) # Might fail it that ceased to exist. if not process_handle: continue ImageFileName = (ctypes.c_wchar * 2048)() rv = psapi.GetProcessImageFileNameW(process_handle, ImageFileName, 2048) if rv == 0: # Note: Could also just ignore those. raise ctypes.WinError() process_name = os.path.basename(ImageFileName.value) # Ignore programs that will be irrelevant, e.g.g Epic launcher, Firefox as they # don't have interesting stuff. This will only improve performance. if process_name in ( "Code.exe", "CodeHelper.exe", "RadeonSoftware.exe", "vsls-agent.exe", "firefox.exe", "EpicGamesLauncher.exe", "Amazon Music Helper.exe", "EpicWebHelper.exe", "RuntimeBroker.exe", "ShellExperienceHost.exe", "StartMenuExperienceHost.exe", "devenv.exe", "ApplicationFrameHost.exe", "cpptools-srv.exe", "CompPkgSrv.exe", "SettingSyncHost.exe", "SecurityHealthSystray.exe", "vcpkgsrv.exe", "UserOOBEBroker.exe", "TextInputHost.exe", "sihost.exe", "taskhostw.exe", "RAVCpl64.exe", "PerfWatson2.exe", "conhost.exe", "bash.exe", "cpptools.exe", "SystemSettings.exe", "LockApp.exe", "SearchApp.exe", "dllhost.exe", "vctip.exe", ): continue if process_name.startswith("ServiceHub."): continue my_print("Process: %s (%d files)" % (process_name, len(handles))) for h in handles: # Create local handles for remote handles first. handle = ctypes.wintypes.HANDLE() rv = ctypes.windll.kernel32.DuplicateHandle( process_handle, h, this_process, ctypes.byref(handle), 0, 0, DUPLICATE_SAME_ACCESS, ) if rv == 0: # Process or handle might long be invalid, which is OK for us. continue if not handle: continue public_object_type_information = PUBLIC_OBJECT_TYPE_INFORMATION() size = ctypes.wintypes.DWORD(ctypes.sizeof(public_object_type_information)) file_type = ctypes.windll.kernel32.GetFileType(handle) if file_type != 1: continue # my_print(handle) rv = ctypes.windll.ntdll.NtQueryObject( handle, ObjectTypeInformation, ctypes.byref(public_object_type_information), size, None, ) if rv == 0: kind = public_object_type_information.Name.Buffer if kind != "File": continue elif rv == STATUS_INVALID_HANDLE: continue else: assert rv != STATUS_BUFFER_TOO_SMALL assert rv != STATUS_BUFFER_OVERFLOW assert rv != STATUS_INFO_LENGTH_MISMATCH assert False, hex(rv) r = getWindowsFileHandleFilename(handle) ctypes.windll.kernel32.CloseHandle(handle) if r: my_print(r) ctypes.windll.kernel32.CloseHandle(process_handle) if __name__ == "__main__": getWindowsAllProcessFileHandles() Nuitka-0.6.19.1/nuitka/utils/__init__.py0000600000372100037210000000150114166627112025030 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/utils/Images.py0000600000372100037210000000322214166627112024500 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Handling of images, esp. format conversions for icons. """ from .FileOperations import hasFilenameExtension def convertImageToIconFormat(logger, image_filename, icon_filename): """Convert image file to icon file.""" icon_format = icon_filename.rsplit(".", 1)[1].lower() # Limit to supported icon formats. assert hasFilenameExtension(icon_filename, (".ico", ".icns")), icon_format try: import imageio except ImportError: logger.sysexit( "Need to install 'imageio' to automatically convert non-%s icon image file in '%s'." % (icon_format, image_filename) ) try: image = imageio.imread(image_filename) except ValueError: logger.sysexit( "Unsupported file format for imageio in '%s', use e.g. PNG files." % image_filename ) imageio.imwrite(icon_filename, image) Nuitka-0.6.19.1/nuitka/utils/SharedLibraries.py0000600000372100037210000003444714166627112026353 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module deals with finding and information about shared libraries. """ import os import re import sys from nuitka import Options from nuitka.__past__ import unicode from nuitka.PythonVersions import python_version from nuitka.Tracing import inclusion_logger, postprocessing_logger from .Execution import ( executeProcess, executeToolChecked, withEnvironmentVarOverriden, ) from .FileOperations import getFileList, withMadeWritableFileMode from .Utils import isAlpineLinux, isMacOS, isWin32Windows from .WindowsResources import ( RT_MANIFEST, VsFixedFileInfoStructure, deleteWindowsResources, getResourcesFromDLL, ) def locateDLLFromFilesystem(name, paths): for path in paths: for root, _dirs, files in os.walk(path): if name in files: return os.path.join(root, name) _ldconfig_usage = "The 'ldconfig' is used to analyse dependencies on ELF using systems and required to be found." def locateDLL(dll_name): # This function is a case driven by returns, pylint: disable=too-many-return-statements import ctypes.util dll_name = ctypes.util.find_library(dll_name) if dll_name is None: return None if isWin32Windows(): return os.path.normpath(dll_name) if isMacOS(): return dll_name if os.path.sep in dll_name: # Use this from ctypes instead of rolling our own. # pylint: disable=protected-access so_name = ctypes.util._get_soname(dll_name) if so_name is not None: return os.path.join(os.path.dirname(dll_name), so_name) else: return dll_name if isAlpineLinux(): return locateDLLFromFilesystem( name=dll_name, paths=["/lib", "/usr/lib", "/usr/local/lib"] ) with withEnvironmentVarOverriden("LANG", "C"): # TODO: Could cache ldconfig output output = executeToolChecked( logger=postprocessing_logger, command=["/sbin/ldconfig", "-p"], absence_message=_ldconfig_usage, ) dll_map = {} for line in output.splitlines()[1:]: if line.startswith(b"Cache generated by:"): continue assert line.count(b"=>") == 1, line left, right = line.strip().split(b" => ") assert b" (" in left, line left = left[: left.rfind(b" (")] if python_version >= 0x300: left = left.decode(sys.getfilesystemencoding()) right = right.decode(sys.getfilesystemencoding()) if left not in dll_map: dll_map[left] = right return dll_map[dll_name] def getSxsFromDLL(filename, with_data=False): """List the SxS manifests of a Windows DLL. Args: filename: Filename of DLL to investigate Returns: List of resource names that are manifests. """ return getResourcesFromDLL( filename=filename, resource_kinds=(RT_MANIFEST,), with_data=with_data ) def removeSxsFromDLL(filename): """Remove the Windows DLL SxS manifest. Args: filename: Filename to remove SxS manifests from """ # There may be more files that need this treatment, these are from scans # with the "find_sxs_modules" tool. if os.path.normcase(os.path.basename(filename)) not in ( "sip.pyd", "win32ui.pyd", "winxpgui.pyd", ): return res_names = getSxsFromDLL(filename) if res_names: deleteWindowsResources(filename, RT_MANIFEST, res_names) def getWindowsDLLVersion(filename): """Return DLL version information from a file. If not present, it will be (0, 0, 0, 0), otherwise it will be a tuple of 4 numbers. """ # Get size needed for buffer (0 if no info) import ctypes.wintypes if type(filename) is unicode: GetFileVersionInfoSizeW = ctypes.windll.version.GetFileVersionInfoSizeW GetFileVersionInfoSizeW.argtypes = [ ctypes.wintypes.LPCWSTR, ctypes.wintypes.LPDWORD, ] GetFileVersionInfoSizeW.restype = ctypes.wintypes.HANDLE size = GetFileVersionInfoSizeW(filename, None) else: size = ctypes.windll.version.GetFileVersionInfoSizeA(filename, None) if not size: return (0, 0, 0, 0) # Create buffer res = ctypes.create_string_buffer(size) # Load file information into buffer res if type(filename) is unicode: # Python3 needs our help here. GetFileVersionInfo = ctypes.windll.version.GetFileVersionInfoW GetFileVersionInfo.argtypes = [ ctypes.wintypes.LPCWSTR, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD, ctypes.wintypes.LPVOID, ] GetFileVersionInfo.restype = ctypes.wintypes.BOOL else: # Python2 just works. GetFileVersionInfo = ctypes.windll.version.GetFileVersionInfoA success = GetFileVersionInfo(filename, 0, size, res) # This cannot really fail anymore. assert success # Look for codepages VerQueryValueA = ctypes.windll.version.VerQueryValueA VerQueryValueA.argtypes = [ ctypes.wintypes.LPCVOID, ctypes.wintypes.LPCSTR, ctypes.wintypes.LPVOID, ctypes.POINTER(ctypes.c_uint32), ] VerQueryValueA.restype = ctypes.wintypes.BOOL file_info = ctypes.POINTER(VsFixedFileInfoStructure)() uLen = ctypes.c_uint32(ctypes.sizeof(file_info)) b = VerQueryValueA(res, br"\\", ctypes.byref(file_info), ctypes.byref(uLen)) if not b: return (0, 0, 0, 0) if not file_info.contents.dwSignature == 0xFEEF04BD: return (0, 0, 0, 0) ms = file_info.contents.dwFileVersionMS ls = file_info.contents.dwFileVersionLS return (ms >> 16) & 0xFFFF, ms & 0xFFFF, (ls >> 16) & 0xFFFF, ls & 0xFFFF _readelf_usage = "The 'readelf' is used to analyse dependencies on ELF using systems and required to be found." def _getSharedLibraryRPATHElf(filename): output = executeToolChecked( logger=postprocessing_logger, command=["readelf", "-d", filename], absence_message=_readelf_usage, ) for line in output.split(b"\n"): if b"RPATH" in line or b"RUNPATH" in line: result = line[line.find(b"[") + 1 : line.rfind(b"]")] if str is not bytes: result = result.decode("utf8") return result return None _otool_usage = ( "The 'otool' is used to analyse dependencies on macOS and required to be found." ) def _getSharedLibraryRPATHDarwin(filename): output = executeToolChecked( logger=postprocessing_logger, command=["otool", "-l", filename], absence_message=_otool_usage, ) cmd = b"" last_was_load_command = False for line in output.split(b"\n"): line = line.strip() if cmd == b"LC_RPATH": if line.startswith(b"path "): result = line[5 : line.rfind(b"(") - 1] if str is not bytes: result = result.decode("utf8") return result if last_was_load_command and line.startswith(b"cmd "): cmd = line.split()[1] last_was_load_command = line.startswith(b"Load command") return None def getSharedLibraryRPATH(filename): if isMacOS(): return _getSharedLibraryRPATHDarwin(filename) else: return _getSharedLibraryRPATHElf(filename) def _removeSharedLibraryRPATHElf(filename): executeToolChecked( logger=postprocessing_logger, command=["chrpath", "-d", filename], absence_message="""\ Error, needs 'chrpath' on your system, due to 'RPATH' settings in used shared libraries that need to be removed.""", ) def _filterPatchelfErrorOutput(stderr): stderr = b"\n".join( line for line in stderr.splitlines() if line if b"warning: working around" not in line ) return stderr def _setSharedLibraryRPATHElf(filename, rpath): # TODO: Might write something that makes a shell script replacement # in case no rpath is present, or use patchelf, for now our use # case seems to use rpaths for executables. # patchelf --set-rpath "$ORIGIN/path/to/library" with withEnvironmentVarOverriden("LANG", "C"): executeToolChecked( logger=postprocessing_logger, command=["patchelf", "--set-rpath", rpath, filename], stderr_filter=_filterPatchelfErrorOutput, absence_message="""\ Error, needs 'patchelf' on your system, due to 'RPATH' settings that need to be set.""", ) def _filterInstallNameToolErrorOutput(stderr): stderr = b"\n".join( line for line in stderr.splitlines() if line if b"invalidate the code signature" not in line ) return stderr _installnametool_usage = "The 'install_name_tool' is used to make binaries portable on macOS and required to be found." def _removeSharedLibraryRPATHDarwin(filename, rpath): executeToolChecked( logger=postprocessing_logger, command=["install_name_tool", "-delete_rpath", rpath, filename], absence_message=_installnametool_usage, stderr_filter=_filterInstallNameToolErrorOutput, ) def _setSharedLibraryRPATHDarwin(filename, rpath): executeToolChecked( logger=postprocessing_logger, command=["install_name_tool", "-add_rpath", rpath, filename], absence_message=_installnametool_usage, stderr_filter=_filterInstallNameToolErrorOutput, ) def removeSharedLibraryRPATH(filename): rpath = getSharedLibraryRPATH(filename) if rpath is not None: if Options.isShowInclusion(): inclusion_logger.info( "Removing 'RPATH' value '%s' from '%s'." % (rpath, filename) ) with withMadeWritableFileMode(filename): if isMacOS(): return _removeSharedLibraryRPATHDarwin(filename, rpath) else: return _removeSharedLibraryRPATHElf(filename) def setSharedLibraryRPATH(filename, rpath): if Options.isShowInclusion(): inclusion_logger.info( "Setting 'RPATH' value '%s' for '%s'." % (rpath, filename) ) with withMadeWritableFileMode(filename): if isMacOS(): return _setSharedLibraryRPATHDarwin(filename, rpath) else: return _setSharedLibraryRPATHElf(filename, rpath) def callInstallNameTool(filename, mapping, rpath): """Update the macOS shared library information for a binary or shared library. Adds the rpath path name `rpath` in the specified `filename` Mach-O binary or shared library. If the Mach-O binary already contains the new `rpath` path name, it is an error. Args: filename - The file to be modified. mapping - old_path, new_path pairs of values that should be changed rpath - Set this as an rpath if not None, delete if False Returns: None Notes: This is obviously macOS specific. """ command = ["install_name_tool"] for old_path, new_path in mapping: command += ("-change", old_path, new_path) if rpath is not None: command += ("-add_rpath", os.path.join(rpath, ".")) command.append(filename) with withMadeWritableFileMode(filename): executeToolChecked( logger=postprocessing_logger, command=command, absence_message=_installnametool_usage, stderr_filter=_filterInstallNameToolErrorOutput, ) def getPyWin32Dir(): """Find the pywin32 DLL directory Args: None Returns: path to the pywin32 DLL directory or None Notes: This is needed for standalone mode only. """ for path_element in sys.path: if not path_element: continue candidate = os.path.join(path_element, "pywin32_system32") if os.path.isdir(candidate): return candidate def detectBinaryMinMacOS(binary_filename): """Detect the minimum required macOS version of a binary. Args: binary_filename - path of the binary to check Returns: str - minimum OS version that the binary will run on """ stdout, _stderr, exit_code = executeProcess(["otool", "-l", binary_filename]) if exit_code != 0: postprocessing_logger.sysexit( "Unexpected failure to execute otool -l '%s'." % binary_filename ) lines = stdout.split(b"\n") for i, line in enumerate(lines): # Form one, used by CPython builds. if line.endswith(b"cmd LC_VERSION_MIN_MACOSX"): line = lines[i + 2] if str is not bytes: line = line.decode("utf8") return line.split("version ", 1)[1] # Form two, used by Apple Python builds. elif line.strip().startswith(b"minos"): if str is not bytes: line = line.decode("utf8") return line.split("minos ", 1)[1] return None _re_anylib = re.compile(r"^.*(\.(?:dll|so(?:\..*)|dylib))$", re.IGNORECASE) def locateDLLsInDirectory(directory): """Locate all DLLs in a folder Returns: list of (filename, filename_relative, dll_extension) """ # This needs to be done a bit more manually, because DLLs on Linux can have no # defined suffix, cannot use e.g. only_suffixes for this. result = [] for filename in getFileList(path=directory): filename_relative = os.path.relpath(filename, start=directory) # TODO: Might want to be OS specific on what to match. match = _re_anylib.match(filename_relative) if match: result.append((filename, filename_relative, match.group(1))) return result Nuitka-0.6.19.1/nuitka/utils/Timing.py0000600000372100037210000000514014166627112024523 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Time taking. Mostly for measurements of Nuitka of itself, e.g. how long did it take to call an external tool. """ from timeit import default_timer as timer from nuitka.Tracing import general class StopWatch(object): __slots__ = ("start_time", "end_time") def __init__(self): self.start_time = None self.end_time = None def start(self): self.start_time = timer() def restart(self): self.start() def end(self): self.end_time = timer() stop = end def getDelta(self): if self.end_time is not None: return self.end_time - self.start_time else: return timer() - self.start_time class TimerReport(object): """Timer that reports how long things took. Mostly intended as a wrapper for external process calls. """ __slots__ = ("message", "decider", "logger", "timer", "min_report_time") def __init__(self, message, logger=None, decider=True, min_report_time=None): self.message = message if decider is True: decider = lambda: True if logger is None: logger = general self.logger = logger self.decider = decider self.min_report_time = min_report_time self.timer = None def getTimer(self): return self.timer def __enter__(self): self.timer = StopWatch() self.timer.start() def __exit__(self, exception_type, exception_value, exception_tb): self.timer.end() delta_time = self.timer.getDelta() # Check if its above the provided limit. above_threshold = ( self.min_report_time is None or delta_time >= self.min_report_time ) if exception_type is None and above_threshold and self.decider(): self.logger.info(self.message % self.timer.getDelta()) Nuitka-0.6.19.1/nuitka/utils/AppDirs.py0000600000372100037210000000505614166627112024644 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Wrapper around appdir from PyPI We do not assume to be installed and fallback to an inline copy and if that is not installed, we use our own code for best effort. """ from __future__ import absolute_import import os import tempfile from .FileOperations import makePath from .Importing import importFromInlineCopy try: import appdirs # pylint: disable=I0021,import-error except ImportError: # We handle the case without inline copy too. appdirs = importFromInlineCopy("appdirs", must_exist=False) _cache_dir = None def getCacheDir(): global _cache_dir # singleton, pylint: disable=global-statement if _cache_dir is None: _cache_dir = os.getenv("NUITKA_CACHE_DIR") if _cache_dir: _cache_dir = os.path.expanduser(_cache_dir) elif appdirs is not None: _cache_dir = appdirs.user_cache_dir("Nuitka", None) else: _cache_dir = os.path.join(os.path.expanduser("~"), ".cache", "Nuitka") # For people that build with HOME set this, e.g. Debian. if _cache_dir.startswith(("/nonexistent/", "/sbuild-nonexistent/")): _cache_dir = os.path.join(tempfile.gettempdir(), "Nuitka") makePath(_cache_dir) return _cache_dir _app_dir = None def getAppDir(): global _app_dir # singleton, pylint: disable=global-statement if _app_dir is None: if appdirs is not None: _app_dir = appdirs.user_data_dir("Nuitka", None) else: _app_dir = os.path.join(os.path.expanduser("~"), ".config", "Nuitka") # For people that build with HOME set this, e.g. Debian. if _app_dir.startswith(("/nonexistent/", "/sbuild-nonexistent/")): _app_dir = os.path.join(tempfile.gettempdir(), "Nuitka") makePath(_app_dir) return _app_dir Nuitka-0.6.19.1/nuitka/utils/Rest.py0000600000372100037210000000734514166627112024222 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Work with ReST documentations. This e.g. creates PDF documentations during release and tables from data for the web site, e.g. downloads. """ import functools import os import tempfile from .Execution import check_call, withEnvironmentVarOverriden from .FileOperations import ( changeFilenameExtension, deleteFile, getFileContents, putTextFileContents, ) def createPDF(document): pdf_filename = changeFilenameExtension(document, ".pdf") args = ["-o", pdf_filename] with tempfile.NamedTemporaryFile(delete=False) as style_file: style_filename = style_file.name style_file.write( b""" "pageSetup" : { "firstTemplate": "coverPage" } "styles" : [ [ "title" , { "fontName": "NanumGothic-Bold", "fontSize": 40 } ], [ "heading1" , { "fontName": "NanumGothic-Bold" } ], [ "heading2" , { "fontName": "NanumGothic" } ] ] """ ) if document != "Changelog.rst": args.append("-s") args.append(style_filename) args.append('--header="###Title### - ###Section###"') args.append('--footer="###Title### - page ###Page### - ###Section###"') # Workaround for rst2pdf not support ..code:: without language. old_contents = getFileContents(document) new_contents = old_contents.replace(".. code::\n", "::\n") # Add page counter reset right after TOC for PDF. new_contents = new_contents.replace( ".. contents::", """.. contents:: .. raw:: pdf PageBreak oneColumn SetPageCounter 1 """, ) try: if new_contents != old_contents: document += ".tmp" putTextFileContents(filename=document, contents=new_contents) with withEnvironmentVarOverriden("PYTHONWARNINGS", "ignore"): check_call(["rst2pdf"] + args + [document]) finally: if new_contents != old_contents: deleteFile(document, must_exist=False) deleteFile(style_filename, must_exist=True) assert os.path.exists(pdf_filename) return pdf_filename def makeTable(grid): """Create a REST table.""" def makeSeparator(num_cols, col_width, header_flag): if header_flag == 1: return num_cols * ("+" + (col_width) * "=") + "+\n" else: return num_cols * ("+" + (col_width) * "-") + "+\n" def normalizeCell(string, length): return string + ((length - len(string)) * " ") cell_width = 2 + max( functools.reduce( lambda x, y: x + y, [[len(item) for item in row] for row in grid], [] ) ) num_cols = len(grid[0]) rst = makeSeparator(num_cols, cell_width, 0) header_flag = 1 for row in grid: rst = ( rst + "| " + "| ".join([normalizeCell(x, cell_width - 1) for x in row]) + "|\n" ) rst = rst + makeSeparator(num_cols, cell_width, header_flag) header_flag = 0 return rst Nuitka-0.6.19.1/nuitka/importing/0000700000372100037210000000000014167275622023576 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/importing/IgnoreListing.py0000600000372100037210000002526614166627112026734 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Ignore listing of modules that are not found, but probably that's acceptable. """ import sys from nuitka.Errors import NuitkaOptimizationError def getModuleIgnoreList(): return ( "mac", "nt", "os2", "posix", "_emx_link", "riscos", "ce", "riscospath", "riscosenviron", "Carbon.File", "org.python.core", "_sha", "_sha256", "array", "_sha512", "_md5", "_subprocess", "msvcrt", "cPickle", "marshal", "imp", "sys", "itertools", "cStringIO", "time", "zlib", "thread", "math", "errno", "operator", "signal", "gc", "exceptions", "win32process", "unicodedata", "__builtin__", "fcntl", "_socket", "_ssl", "pwd", "spwd", "_random", "grp", "_io", "_string", "select", "__main__", "_winreg", "_warnings", "_sre", "_functools", "_hashlib", "_collections", "_locale", "_codecs", "_weakref", "_struct", "_dummy_threading", "binascii", "datetime", "_ast", "xxsubtype", "_bytesio", "cmath", "_fileio", "aetypes", "aepack", "MacOS", "cd", "cl", "gdbm", "gl", "GL", "aetools", "_bisect", "_heapq", "_symtable", "syslog", "_datetime", "_elementtree", "_pickle", "_posixsubprocess", "_thread", "atexit", "pyexpat", "_imp", "_sha1", "faulthandler", "_osx_support", "sysconfig", "copyreg", "ipaddress", "reprlib", "win32event", "win32file", # Python-Qt4 does these if missing python3 parts: "PyQt4.uic.port_v3.string_io", "PyQt4.uic.port_v3.load_plugin", "PyQt4.uic.port_v3.ascii_upper", "PyQt4.uic.port_v3.proxy_base", "PyQt4.uic.port_v3.as_string", # CPython3 does these: "builtins", "UserDict", "os.path", "StringIO", # "test_array", "_testcapi", # test_applesingle.py "applesingle", # test_buffer.py "_testbuffer", # test_bsddb.py "bsddb.test", # test_collections.py "collections.abc", # test_compile.py "__package__.module", "__mangled_mod", "__package__", # test_ctypes "ctypes.test", # test_dbm.py "dbm.dumb", # test_dbm_ndbm.py "dbm.ndbm", # test_distutils.py "distutils.tests", "distutils.mwerkscompiler", # test_docxmlrpc.py "xmlrpc", # test_emails.py "email.test.test_email", "email.test.test_email_renamed", "email.test.test_email_codecs", # test_email_codecs.py "email.test", # test_enum.py "enum", # test_file.py "_pyio", # test_frozen.py "__hello__", "__phello__", "__phello__.spam", "__phello__.foo", # test_fork1.py "fake test module", # test_html.py "html", "html.entities", # test_http_cookiejar.py "urllib.request", "http", # test_imp.py "importlib.test.import_", "pep3147.foo", "pep3147", # test_import.py "RAnDoM", "infinite_reload", "test_trailing_slash", "nonexistent_xyzzy", "_parent_foo.bar", "_parent_foo", "test_unc_path", # test_importhooks.py "hooktestmodule", "hooktestpackage", "hooktestpackage.sub", "reloadmodule", "hooktestpackage.sub.subber", "hooktestpackage.oldabs", "hooktestpackage.newrel", "hooktestpackage.sub.subber.subest", "hooktestpackage.futrel", "sub", "hooktestpackage.newabs", # test_imporlib.py" "importlib.test.__main__", "importlib", # test_inspect.py "inspect_fodder3", "test.test_import", # test_imageop.py "imgfile", # test_json.py "json.tests", # test_lib2to3.py "lib2to3.tests", # test_logging.py "win32evtlog", "win32evtlogutil", "pywintypes", # test_lzma.py "lzma", # test_macostools.py "macostools", # test_msilib.py "msilib", # test_namespace_pkgs.py "foo.one", "foo.two", "parent.child.one", "parent.child.two", "parent.child.three", "bar.two", "a_test", "parent.child", "parent", "bar", # test_new.py "Spam", # test_ossaudiodev.py "ossaudiodev", # test_pathlib.py "pathlib", # test_platform.py "gestalt", # test_pickleable.py "email.headerregistry", # test_pkg.py "t1", "t2", "t2.sub", "t2.sub.subsub", "t3.sub.subsub", "t5", "t6", "t7", "t7.sub", "t7.sub.subsub", "t8", "t3.sub", "t3", # test_pkgutil.py "foo", "foo.bar", "foo.baz", "zipimport", "pkg", "pkg.subpkg", "pkg.subpkg.c", "pkg.subpkg.d", # test_policy.py "email.policy", # test_urllib.py "urllib.parse", # test_urllib_response.py "urllib.response", # test_repr.py """areallylongpackageandmodulenametotestreprtruncation.\ areallylongpackageandmodulenametotestreprtruncation""", "areallylongpackageandmodulenametotestreprtruncation", # test_robotparser.py "urllib.error", "urllib.robotparser", # test_runpy.py "test.script_helper", # test_secrets.py "secrets", # test_selectors.py "selectors", # test_statistics.py "statistics", # test_shelve.py "test.test_dbm", # test_strftime.py "java", # test_strop.py "strop", # test_sqlite3.py "sqlite3.test", # test_sundry.py "distutils.emxccompiler", "os2emxpath", # test_tcl.py "tkinter", # test_tk.py "runtktests", "tkinter.test", "tkinter.test.support", # test_tools.py "analyze_dxp", "test_unparse", "importlib.machinery", # test_traceback.py "test_bug737473", # test_tracemalloc "tracemalloc", # test_typing.py "mock", "typing.io", "typing.re", # test_unittest.py "unittest.test", # test_wsgiref.py "test.test_httpservers", # test_xml_etree.py "xml.parsers.expat.errors", # test_xmlrpc.py "xmlrpc.client", # test_zipimport_support.py "test_zipped_doctest", "zip_pkg", # test/test_zipimport_support.py "test.test_cmd_line_script", # test_winconsoleio.py "_testconsole", # Python3: modules that no longer exist "commands", "dummy_thread", "_dummy_thread", "httplib", "Queue", "sets", # Python2: modules that don't yet exit "http.client", "queue", "winreg", # Very old modules with older names "simplejson", "sets", # Standalone mode "site" import flexibilities "sitecustomize", "usercustomize", "apport_python_hook", "_frozen_importlib", # Standard library stuff that is optional "comtypes.server.inprocserver", "_tkinter", "_scproxy", "EasyDialogs", "SOCKS", "rourl2path", "_winapi", "win32api", "win32con", "_gestalt", "java.lang", "vms_lib", "ic", "readline", "termios", "_sysconfigdata", "al", "AL", "sunaudiodev", "SUNAUDIODEV", "Audio_mac", "nis", "test.test_MimeWriter", "dos", "win32pipe", "Carbon", "Carbon.Files", "sgi", "ctypes.macholib.dyld", "bsddb3", "_pybsddb", "_xmlrpclib", "netbios", "win32wnet", "email.Parser", "elementree.cElementTree", "elementree.ElementTree", "_gbdm", "resource", "crypt", "bz2", "dbm", "mmap", "Mailman", # Mercurial test "statprof", "email.Generator", "email.Utils", # setuptools does a lot of speculative stuff "wincertstore", "setuptools_svn", # reportlab does use this if present only and warns about itself. "pyfribidi2", "macfs", # psutils "_psutil_windows", # nose "unittest2", "IronPython", "clr", "compiler.consts", "new", # pkg_resources "pkg_resources.extern", "ordereddict", # appdirs "com", "win32com", # gtk "gdk", # six "six.moves", # Python3 namespace packages. "_frozen_importlib_external", # Garbage from PyWin32 "pywin32_bootstrap", ) def isIgnoreListedNotExistingModule(module_name): if module_name in sys.builtin_module_names: raise NuitkaOptimizationError( """ Your CPython version has a built-in module '%s', that is not ignore listed please report this as a bug.""" % module_name, ) return module_name.hasOneOfNamespaces(getModuleIgnoreList()) Nuitka-0.6.19.1/nuitka/importing/Importing.py0000600000372100037210000006216114166627112026122 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Locating modules and package source on disk. The actual import of a module would already execute code that changes things. Imagine a module that does ``os.system()``, it would be done during compilation. People often connect to databases, and these kind of things, at import time. Therefore CPython exhibits the interfaces in an ``imp`` module in standard library, which one can use those to know ahead of time, what file import would load. For us unfortunately there is nothing in CPython that is easily accessible and gives us this functionality for packages and search paths exactly like CPython does, so we implement here a multi step search process that is compatible. This approach is much safer of course and there is no loss. To determine if it's from the standard library, one can abuse the attribute ``__file__`` of the ``os`` module like it's done in ``isStandardLibraryPath`` of this module. """ import collections import hashlib import imp import os import sys import zipfile from nuitka import Options, SourceCodeReferences from nuitka.__past__ import iter_modules from nuitka.containers.oset import OrderedSet from nuitka.importing import StandardLibrary from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version from nuitka.Tracing import my_print, recursion_logger from nuitka.utils.AppDirs import getCacheDir from nuitka.utils.FileOperations import listDir, removeDirectory from nuitka.utils.Importing import getSharedLibrarySuffixes from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.Utils import getOS, isMacOS from .IgnoreListing import isIgnoreListedNotExistingModule from .PreloadedPackages import getPreloadedPackagePath, isPreloadedPackagePath _debug_module_finding = Options.shallExplainImports() warned_about = set() # Directory where the main script lives. Should attempt to import from there. main_path = None def setMainScriptDirectory(main_dir): """Initialize the main script directory. We use this as part of the search path for modules. """ # We need to set this from the outside, pylint: disable=global-statement global main_path main_path = main_dir def getMainScriptDirectory(): return main_path def isPackageDir(dirname): """Decide if a directory is a package. Before Python3.3 it's required to have a "__init__.py" file, but then it became impossible to decide, and for extra fun, there is also the extra packages provided via "*.pth" file tricks by "site.py" loading. """ return ( "." not in os.path.basename(dirname) and os.path.isdir(dirname) and ( python_version >= 0x300 or os.path.isfile(os.path.join(dirname, "__init__.py")) or isPreloadedPackagePath(dirname) ) ) def getModuleNameAndKindFromFilename(module_filename): """Given a filename, decide the module name and kind. Args: module_name - file path of the module Returns: Tuple with the name of the module basename, and the kind of the module derived from the file suffix. Can be None, None if is is not a known file suffix. Notes: This doesn't concern itself with packages, that needs to be tracked by the using code. It cannot be decided from the filename at all. """ # TODO: This does not handle ".pyw" files it seems. if os.path.isdir(module_filename): module_name = ModuleName(os.path.basename(module_filename)) module_kind = "py" elif module_filename.endswith(".py"): module_name = ModuleName(os.path.basename(module_filename)[:-3]) module_kind = "py" else: for suffix in getSharedLibrarySuffixes(): if module_filename.endswith(suffix): module_name = ModuleName( os.path.basename(module_filename)[: -len(suffix)] ) module_kind = "shlib" break else: module_kind = None module_name = None return module_name, module_kind def isIgnoreListedImportMaker(source_ref): return StandardLibrary.isStandardLibraryPath(source_ref.getFilename()) def warnAbout(importing, module_name, level, source_ref): # This probably should not be dealt with here if module_name == "": return if not isIgnoreListedNotExistingModule( module_name ) and not isIgnoreListedImportMaker(source_ref): key = module_name, level if key not in warned_about: warned_about.add(key) if Plugins.suppressUnknownImportWarning( importing=importing, source_ref=source_ref, module_name=module_name ): return if level == 0: level_desc = "as absolute import" elif level == -1: level_desc = "as relative or absolute import" elif level == 1: level_desc = "%d package level up" % level else: level_desc = "%d package levels up" % level if _debug_module_finding: if importing.getPackageName() is not None: recursion_logger.warning( "%s: Cannot find '%s' in package '%s' %s." % ( importing.getSourceReference().getAsString(), module_name, importing.getPackageName().asString(), level_desc, ) ) else: recursion_logger.warning( "%s: Cannot find '%s' %s." % ( importing.getSourceReference().getAsString(), module_name, level_desc, ) ) def normalizePackageName(module_name): # The "os.path" is strangely hacked into the "os" module, dispatching per # platform, we either cannot look into it, or we require that we resolve it # here correctly. if module_name == "os.path": module_name = ModuleName(os.path.basename(os.path.__name__)) return module_name def findModule(module_name, parent_package, level): """Find a module with given package name as parent. The package name can be None of course. Level is the same as with "__import__" built-in. Warnings are optional. Returns: Returns a triple of package name the module is in, filename of it, which can be a directory for packages, and the location method used. """ # We have many branches here, because there are a lot of cases to try. # pylint: disable=too-many-branches,too-many-return-statements,too-many-statements assert type(module_name) is ModuleName, module_name if _debug_module_finding: my_print( "findModule: Enter to search %r in package %r level %s." % (module_name, parent_package, level) ) # Do not allow star imports to get here. We just won't find modules with # that name, but it would be wasteful. assert module_name != "*" tried_names = [] if level > 1: # TODO: Should give a warning and return not found if the levels # exceed the package name. if parent_package is not None: parent_package = parent_package.getRelativePackageName(level) else: return None, None, "not-found" # Try relative imports first if we have a parent package. if level != 0 and parent_package is not None: if module_name: full_name = ModuleName(parent_package + "." + module_name) else: full_name = ModuleName(parent_package) full_name = normalizePackageName(full_name) tried_names.append(full_name) preloaded_path = getPreloadedPackagePath(module_name) if preloaded_path is not None: for module_filename in preloaded_path: if os.path.exists(module_filename): break else: module_filename = None return full_name.getPackageName(), module_filename, "pth" try: module_filename = _findModule(module_name=full_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: my_print( "findModule: Relative imported module '%s' as '%s' in filename '%s':" % (module_name, full_name, module_filename) ) return full_name.getPackageName(), module_filename, "relative" if level <= 1 and module_name != "": module_name = normalizePackageName(module_name) tried_names.append(module_name) package_name = module_name.getPackageName() # Built-in module names must not be searched any further. if module_name in sys.builtin_module_names: if _debug_module_finding: my_print( "findModule: Absolute imported module '%s' in as built-in':" % (module_name,) ) return package_name, None, "built-in" # Frozen module names are similar to built-in, but there is no list of # them, therefore check loader name. Not useful at this time # to make a difference with built-in. if python_version >= 0x300 and module_name in sys.modules: loader = getattr(sys.modules[module_name], "__loader__", None) if ( loader is not None and getattr(loader, "__name__", "") == "FrozenImporter" ): if _debug_module_finding: my_print( "findModule: Absolute imported module '%s' in as frozen':" % (module_name,) ) return package_name, None, "built-in" preloaded_path = getPreloadedPackagePath(module_name) if preloaded_path is not None: for module_filename in preloaded_path: if os.path.exists(module_filename): break else: module_filename = None return package_name, module_filename, "pth" try: module_filename = _findModule(module_name=module_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: my_print( "findModule: Found absolute imported module '%s' in filename '%s':" % (module_name, module_filename) ) return package_name, module_filename, "absolute" return None, None, "not-found" # Some platforms are case insensitive. case_sensitive = not isMacOS() and getOS() != "Windows" ImportScanFinding = collections.namedtuple( "ImportScanFinding", ("found_in", "priority", "full_path", "search_order") ) # We put here things that are not worth it (Cython is not really used by # anything really, or where it's know to not have a big # impact, e.g. lxml. unworthy_namespaces = ("Cython", "lxml") def _reportCandidates(package_name, module_name, candidate, candidates): module_name = ( package_name.getChildNamed(module_name) if package_name is not None else module_name ) if ( candidate.priority == 1 and Options.shallPreferSourcecodeOverExtensionModules() is None ): for c in candidates: # Don't compare to itself and don't consider unused bytecode a problem. if c is candidate or c.priority == 3: continue if c.search_order == candidate.search_order: if not module_name.hasOneOfNamespaces(unworthy_namespaces): recursion_logger.info( """\ Should decide '--prefer-source-code' vs. '--no-prefer-source-code', using \ existing '%s' extension module by default. Candidates were: %s <-> %s.""" % (module_name, candidate, c) ) def _findModuleInPath2(package_name, module_name, search_path): """This is out own module finding low level implementation. Just the full module name and search path are given. This is then tasked to raise "ImportError" or return a path if it finds it, or None, if it is a built-in. """ # We have many branches here, because there are a lot of cases to try. # pylint: disable=too-many-branches,too-many-locals # We may have to decide between package and module, therefore build # a list of candidates. candidates = OrderedSet() considered = set() # Higher values are lower priority. priority_map = { imp.PY_COMPILED: 3, imp.PY_SOURCE: 0 if Options.shallPreferSourcecodeOverExtensionModules() else 2, imp.C_EXTENSION: 1, } for count, entry in enumerate(search_path): # Don't try again, just with an entry of different casing or complete # duplicate. if os.path.normcase(entry) in considered: continue considered.add(os.path.normcase(entry)) package_directory = os.path.join(entry, module_name.asPath()) # First, check for a package with an init file, that would be the # first choice. if os.path.isdir(package_directory): found = False for suffix, _mode, mtype in imp.get_suffixes(): if mtype == imp.C_EXTENSION: continue package_file_name = "__init__" + suffix file_path = os.path.join(package_directory, package_file_name) if os.path.isfile(file_path): candidates.add( ImportScanFinding( found_in=entry, priority=priority_map[mtype], full_path=package_directory, search_order=count, ) ) found = True if not found and python_version >= 0x300: candidates.add( ImportScanFinding( found_in=entry, priority=10, full_path=package_directory, search_order=count + len(search_path), ) ) # Then, check out suffixes of all kinds, but only for one directory. last_mtype = 0 for suffix, _mode, mtype in imp.get_suffixes(): # Use first match per kind only. if mtype == last_mtype: continue full_path = os.path.join(entry, module_name + suffix) if os.path.isfile(full_path): candidates.add( ImportScanFinding( found_in=entry, priority=4 + priority_map[mtype], full_path=full_path, search_order=count, ) ) last_mtype = mtype if _debug_module_finding: my_print("Candidates:", candidates) if candidates: # Sort by priority, with entries from same path element coming first, then desired type. candidates = sorted(candidates, key=lambda c: (c.search_order, c.priority)) # On case sensitive systems, no resolution needed. if case_sensitive: _reportCandidates( package_name=package_name, module_name=module_name, candidate=candidates[0], candidates=candidates, ) return candidates[0].full_path else: for candidate in candidates: for fullname, _filename in listDir(candidate[0]): if fullname == candidate.full_path: _reportCandidates( package_name=package_name, module_name=module_name, candidate=candidate, candidates=candidates, ) return candidate.full_path # Only exact case matches matter, all candidates were ignored, # lets just fall through to raising the import error. # Nothing found. raise ImportError _egg_files = {} def _unpackPathElement(path_entry): if not path_entry: return "." # empty means current directory if os.path.isfile(path_entry) and path_entry.lower().endswith(".egg"): if path_entry not in _egg_files: with open(path_entry, "rb") as f: checksum = hashlib.md5(f.read()).hexdigest() target_dir = os.path.join(getCacheDir(), "egg-content", checksum) if not os.path.exists(target_dir): try: # Not all Python versions allow using with here, pylint: disable=consider-using-with zip_ref = zipfile.ZipFile(path_entry, "r") zip_ref.extractall(target_dir) zip_ref.close() except BaseException: removeDirectory(target_dir, ignore_errors=True) raise _egg_files[path_entry] = target_dir return _egg_files[path_entry] return path_entry def getPackageSearchPath(package_name): assert main_path is not None if package_name is None: return [os.getcwd(), main_path] + [ _unpackPathElement(path_element) for path_element in sys.path ] elif "." in package_name: parent_package_name, child_package_name = package_name.splitModuleBasename() result = [] for element in getPackageSearchPath(parent_package_name): package_dir = os.path.join(element, child_package_name.asPath()) if isPackageDir(package_dir): result.append(package_dir) # Hack for "uniconverter". TODO: Move this to plug-in decision. This # fails the above test, but at run time should be a package. elif package_name == "uniconvertor.app.modules": result.append(package_dir) return result else: preloaded_path = getPreloadedPackagePath(package_name) if preloaded_path is not None: return preloaded_path def getPackageDirCandidates(element): yield os.path.join(element, package_name.asPath()), False # Hack for PyWin32. TODO: Move this "__path__" extensions to be # plug-in decisions. if package_name == "win32com": yield os.path.join(element, "win32comext"), True result = [] for element in getPackageSearchPath(None): for package_dir, force_package in getPackageDirCandidates(element): if isPackageDir(package_dir) or force_package: result.append(package_dir) return result def _findModuleInPath(module_name): package_name, module_name = module_name.splitModuleBasename() if _debug_module_finding: my_print("_findModuleInPath: Enter", module_name, "in", package_name) # The "site" module must be located based on PYTHONPATH before it was # executed, while we normally search in PYTHONPATH after it was executed, # and on some systems, that fails. if package_name is None and module_name == "site": candidate = os.environ.get("NUITKA_SITE_FILENAME", "") if candidate: return candidate # Free pass for built-in modules, the need not exist. if package_name is None and imp.is_builtin(module_name): return None search_path = getPackageSearchPath(package_name) if _debug_module_finding: my_print( "_findModuleInPath: Using search path", search_path, "for", package_name ) try: module_filename = _findModuleInPath2( package_name=package_name, module_name=module_name, search_path=search_path ) except SyntaxError: # Warn user, as this is kind of unusual. recursion_logger.warning( "%s: Module cannot be imported due to syntax errors.", module_name if package_name is None else package_name + "." + module_name, ) return None if _debug_module_finding: my_print("_findModuleInPath: _findModuleInPath2 gave", module_filename) return module_filename module_search_cache = {} def _findModule(module_name): # Not a good module name. TODO: Push this to ModuleName() creation maybe. assert module_name != "" if _debug_module_finding: my_print("_findModule: Enter to search '%s'." % (module_name,)) assert module_name.getBasename(), module_name key = module_name if key in module_search_cache: result = module_search_cache[key] if _debug_module_finding: my_print("_findModule: Cached result (see previous call).") if result is ImportError: raise ImportError return result module_search_cache[key] = _findModuleInPath(module_name) return module_search_cache[key] def locateModule(module_name, parent_package, level): """Locate a module with given package name as parent. The package name can be None of course. Level is the same as with "__import__" built-in. Returns: Returns a triple of module name the module has considering package containing it, and filename of it which can be a directory for packages, and the location method used. """ module_package, module_filename, finding = findModule( module_name=module_name, parent_package=parent_package, level=level, ) assert module_package is None or ( type(module_package) is ModuleName and module_package != "" ), repr(module_package) if module_filename is not None: module_filename = os.path.normpath(module_filename) module_name, module_kind = getModuleNameAndKindFromFilename(module_filename) assert module_kind is not None, module_filename module_name = ModuleName.makeModuleNameInPackage(module_name, module_package) return module_name, module_filename, finding def locateModules(package_name): """Determine child module names. Return: generator of ModuleName objects """ package_name = ModuleName(package_name) module_filename = locateModule( module_name=ModuleName(package_name), parent_package=None, level=0 )[1] if module_filename is not None: for sub_module in iter_modules([module_filename]): yield package_name.getChildNamed(sub_module.name) def decideModuleSourceRef(filename, module_name, is_main, is_fake, logger): # Many branches due to the many cases assert type(module_name) is ModuleName assert filename is not None is_namespace = False is_package = False if is_main and os.path.isdir(filename): source_filename = os.path.join(filename, "__main__.py") if not os.path.isfile(source_filename): sys.stderr.write( "%s: can't find '__main__' module in '%s'\n" % (os.path.basename(sys.argv[0]), filename) ) sys.exit(2) filename = source_filename main_added = True else: main_added = False if is_fake: source_filename = filename source_ref = SourceCodeReferences.fromFilename(filename=filename) module_name = is_fake elif os.path.isfile(filename): source_filename = filename source_ref = SourceCodeReferences.fromFilename(filename=filename) elif isPackageDir(filename): is_package = True source_filename = os.path.join(filename, "__init__.py") if not os.path.isfile(source_filename): source_ref = SourceCodeReferences.fromFilename( filename=filename ).atInternal() is_namespace = True else: source_ref = SourceCodeReferences.fromFilename( filename=os.path.abspath(source_filename) ) else: logger.sysexit( "%s: can't open file '%s'." % (os.path.basename(sys.argv[0]), filename), exit_code=2, ) return ( main_added, is_package, is_namespace, source_ref, source_filename, ) Nuitka-0.6.19.1/nuitka/importing/Recursion.py0000600000372100037210000003237314166627112026125 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Recursion into other modules. """ import glob import os from nuitka import ModuleRegistry, Options from nuitka.Errors import NuitkaForbiddenImportEncounter from nuitka.importing import ImportCache, Importing, StandardLibrary from nuitka.ModuleRegistry import addUsedModule, getRootTopModule from nuitka.pgo.PGO import decideInclusionFromPGO from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version from nuitka.Tracing import recursion_logger from nuitka.utils.FileOperations import listDir from nuitka.utils.ModuleNames import ModuleName from .Importing import getModuleNameAndKindFromFilename def _recurseTo(module_name, module_filename, module_kind): from nuitka.tree import Building module, is_added = Building.buildModule( module_filename=module_filename, module_name=module_name, source_code=None, is_top=False, is_main=False, is_shlib=module_kind == "shlib", is_fake=False, hide_syntax_error=True, ) ImportCache.addImportedModule(module) return module, is_added def recurseTo(signal_change, module_name, module_filename, module_kind, reason): try: module = ImportCache.getImportedModuleByNameAndPath( module_name, module_filename ) except KeyError: module = None if module is None: module, added_flag = _recurseTo( module_name=module_name, module_filename=module_filename, module_kind=module_kind, ) if added_flag and signal_change is not None: signal_change("new_code", module.getSourceReference(), reason) return module def decideRecursion(module_filename, module_name, module_kind, extra_recursion=False): # Many branches, which make decisions immediately, by returning # pylint: disable=too-many-branches,too-many-return-statements if module_name == "__main__": return False, "Main program is not followed to a second time." # In -m mode, when including the package, do not duplicate main program. if ( Options.hasPythonFlagPackageMode() and not Options.shallMakeModule() and module_name.getBasename() == "__main__" ): if module_name.getPackageName() == getRootTopModule().getRuntimePackageValue(): return False, "Main program is already included in package mode." plugin_decision = Plugins.onModuleEncounter( module_filename=module_filename, module_name=module_name, module_kind=module_kind, ) if plugin_decision is not None: return plugin_decision if module_kind == "shlib": if Options.isStandaloneMode(): return True, "Extension module needed for standalone mode." else: return False, "Extension module cannot be inspected." # PGO decisions are not overruling plugins, but all command line options, they are # supposed to be applied alrealdy. is_stdlib = StandardLibrary.isStandardLibraryPath(module_filename) if not is_stdlib or Options.shallFollowStandardLibrary(): # TODO: Bad placement of this function or should PGO also know about # bytecode modules loaded or not. from nuitka.tree.Building import decideCompilationMode if ( decideCompilationMode(is_top=False, module_name=module_name, for_pgo=True) == "compiled" ): pgo_decision = decideInclusionFromPGO( module_name=module_name, module_kind=module_kind, ) if pgo_decision is not None: return pgo_decision, "PGO based decision" no_case, reason = module_name.matchesToShellPatterns( patterns=Options.getShallFollowInNoCase() ) if no_case: return (False, "Module %s instructed by user to not follow to." % reason) any_case, reason = module_name.matchesToShellPatterns( patterns=Options.getShallFollowModules() ) if any_case: return (True, "Module %s instructed by user to follow to." % reason) if Options.shallFollowNoImports(): return (False, "Instructed by user to not follow at all.") if is_stdlib: return ( Options.shallFollowStandardLibrary(), "Instructed by user to %sfollow to standard library." % ("" if Options.shallFollowStandardLibrary() else "not "), ) if Options.shallFollowAllImports(): return ( True, "Instructed by user to follow to all non-standard library modules.", ) # Means, we were not given instructions how to handle things. if extra_recursion: return (True, "Lives in plug-in directory.") if Options.shallMakeModule(): return (False, "Making a module, not following any imports by default.") return (None, "Default behavior, not recursing without request.") def considerFilename(module_filename): module_filename = os.path.normpath(module_filename) if os.path.isdir(module_filename): module_filename = os.path.abspath(module_filename) module_name = os.path.basename(module_filename) return module_filename, module_name elif module_filename.endswith(".py"): module_name = os.path.basename(module_filename)[:-3] return module_filename, module_name elif module_filename.endswith(".pyw"): module_name = os.path.basename(module_filename)[:-4] return module_filename, module_name else: return None def isSameModulePath(path1, path2): if os.path.basename(path1) == "__init__.py": path1 = os.path.dirname(path1) if os.path.basename(path2) == "__init__.py": path2 = os.path.dirname(path2) return os.path.abspath(path1) == os.path.abspath(path2) def checkPluginSinglePath(plugin_filename, module_package): # Many branches, for the decision is very complex, pylint: disable=too-many-branches if Options.isShowInclusion(): recursion_logger.info( "Checking detail plug-in path '%s' '%s':" % (plugin_filename, module_package) ) module_name, module_kind = Importing.getModuleNameAndKindFromFilename( plugin_filename ) module_name = ModuleName.makeModuleNameInPackage(module_name, module_package) if module_kind is not None: decision, reason = decideRecursion( module_filename=plugin_filename, module_name=module_name, module_kind=module_kind, extra_recursion=True, ) if decision: module = recurseTo( signal_change=None, module_filename=plugin_filename, module_name=module_name, module_kind=module_kind, reason=reason, ) if module: if Options.isShowInclusion(): recursion_logger.info( "Included '%s' as '%s'." % ( module.getFullName(), module, ) ) ImportCache.addImportedModule(module) if module.isCompiledPythonPackage(): package_filename = module.getFilename() if os.path.isdir(package_filename): # Must be a namespace package. assert python_version >= 0x300 package_dir = package_filename # Only include it, if it contains actual modules, which will # recurse to this one and find it again. else: package_dir = os.path.dirname(package_filename) # Real packages will always be included. ModuleRegistry.addRootModule(module) if Options.isShowInclusion(): recursion_logger.info("Package directory '%s'." % package_dir) for sub_path, sub_filename in listDir(package_dir): if sub_filename in ("__init__.py", "__pycache__"): continue assert sub_path != plugin_filename if Importing.isPackageDir(sub_path) and not os.path.exists( sub_path + ".py" ): checkPluginSinglePath( sub_path, module_package=module.getFullName() ) elif sub_path.endswith(".py"): checkPluginSinglePath( sub_path, module_package=module.getFullName() ) elif module.isCompiledPythonModule(): ModuleRegistry.addRootModule(module) elif module.isPythonShlibModule(): if Options.isStandaloneMode(): ModuleRegistry.addRootModule(module) else: recursion_logger.warning( "Failed to include module from '%s'." % plugin_filename ) def checkPluginPath(plugin_filename, module_package): plugin_filename = os.path.normpath(plugin_filename) if Options.isShowInclusion(): recursion_logger.info( "Checking top level plug-in path %s %s" % (plugin_filename, module_package) ) plugin_info = considerFilename(module_filename=plugin_filename) if plugin_info is not None: # File or package makes a difference, handle that if os.path.isfile(plugin_info[0]) or Importing.isPackageDir(plugin_info[0]): checkPluginSinglePath(plugin_filename, module_package=module_package) elif os.path.isdir(plugin_info[0]): for sub_path, sub_filename in listDir(plugin_info[0]): assert sub_filename != "__init__.py" if Importing.isPackageDir(sub_path) or sub_path.endswith(".py"): checkPluginSinglePath(sub_path, module_package=None) else: recursion_logger.warning( "Failed to include module from %r." % plugin_info[0] ) else: recursion_logger.warning("Failed to recurse to directory %r." % plugin_filename) def checkPluginFilenamePattern(pattern): if Options.isShowInclusion(): recursion_logger.info("Checking plug-in pattern '%s':" % pattern) assert not os.path.isdir(pattern), pattern found = False for filename in glob.iglob(pattern): if filename.endswith(".pyc"): continue if not os.path.isfile(filename): continue found = True checkPluginSinglePath(filename, module_package=None) if not found: recursion_logger.warning("Didn't match any files against pattern %r." % pattern) def considerUsedModules(module, signal_change): for ( used_module_name, used_module_filename, finding, level, source_ref, ) in module.getUsedModules(): if finding == "not-found": Importing.warnAbout( importing=module, source_ref=source_ref, module_name=used_module_name, level=level, ) try: if used_module_filename is None: continue _module_name, module_kind = getModuleNameAndKindFromFilename( used_module_filename ) decision, reason = decideRecursion( module_filename=used_module_filename, module_name=used_module_name, module_kind=module_kind, ) if decision: used_module = recurseTo( signal_change=signal_change, module_name=used_module_name, module_filename=used_module_filename, module_kind=module_kind, reason=reason, ) addUsedModule( module=used_module, using_module=module, usage_tag="import", reason=reason, source_ref=source_ref, ) except NuitkaForbiddenImportEncounter as e: recursion_logger.sysexit( "Error, forbidden import of '%s' in module '%s' encountered." % (e, module.getFullName().asString()) ) Plugins.considerImplicitImports(module=module, signal_change=signal_change) Nuitka-0.6.19.1/nuitka/importing/ImportResolving.py0000600000372100037210000001407214166627112027313 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This cares about resolving module names at compile time compensating meta path based importers. """ from nuitka.__past__ import unicode from nuitka.PythonVersions import python_version from nuitka.utils.ModuleNames import ModuleName _six_moves = { "six.moves.builtins": "__builtin__" if python_version < 0x300 else "builtins", "six.moves.configparser": "ConfigParser" if python_version < 0x300 else "configparser", "six.moves.copyreg": "copy_reg" if python_version < 0x300 else "copyreg", "six.moves.dbm_gnu": "gdbm" if python_version < 0x300 else "dbm.gnu", "six.moves._dummy_thread": "dummy_thread" if python_version < 0x300 else "_dummy_thread", "six.moves.http_cookiejar": "cookielib" if python_version < 0x300 else "http.cookiejar", "six.moves.http_cookies": "Cookie" if python_version < 0x300 else "http.cookies", "six.moves.html_entities": "htmlentitydefs" if python_version < 0x300 else "html.entities", "six.moves.html_parser": "HTMLParser" if python_version < 0x300 else "html.parser", "six.moves.http_client": "httplib" if python_version < 0x300 else "http.client", "six.moves.email_mime_multipart": "email.MIMEMultipart" if python_version < 0x300 else "email.mime.multipart", "six.moves.email_mime_nonmultipart": "email.MIMENonMultipart" if python_version < 0x300 else "email.mime.nonmultipart", "six.moves.email_mime_text": "email.MIMEText" if python_version < 0x300 else "email.mime.text", "six.moves.email_mime_base": "email.MIMEBase" if python_version < 0x300 else "email.mime.base", "six.moves.BaseHTTPServer": "BaseHTTPServer" if python_version < 0x300 else "http.server", "six.moves.CGIHTTPServer": "CGIHTTPServer" if python_version < 0x300 else "http.server", "six.moves.SimpleHTTPServer": "SimpleHTTPServer" if python_version < 0x300 else "http.server", "six.moves.cPickle": "cPickle" if python_version < 0x300 else "pickle", "six.moves.queue": "Queue" if python_version < 0x300 else "queue", "six.moves.reprlib": "repr" if python_version < 0x300 else "reprlib", "six.moves.socketserver": "SocketServer" if python_version < 0x300 else "socketserver", "six.moves._thread": "thread" if python_version < 0x300 else "_thread", "six.moves.tkinter": "Tkinter" if python_version < 0x300 else "tkinter", "six.moves.tkinter_dialog": "Dialog" if python_version < 0x300 else "tkinter.dialog", "six.moves.tkinter_filedialog": "FileDialog" if python_version < 0x300 else "tkinter.filedialog", "six.moves.tkinter_scrolledtext": "ScrolledText" if python_version < 0x300 else "tkinter.scrolledtext", "six.moves.tkinter_simpledialog": "SimpleDialog" if python_version < 0x300 else "tkinter.simpledialog", "six.moves.tkinter_tix": "Tix" if python_version < 0x300 else "tkinter.tix", "six.moves.tkinter_ttk": "ttk" if python_version < 0x300 else "tkinter.ttk", "six.moves.tkinter_constants": "Tkconstants" if python_version < 0x300 else "tkinter.constants", "six.moves.tkinter_dnd": "Tkdnd" if python_version < 0x300 else "tkinter.dnd", "six.moves.tkinter_colorchooser": "tkColorChooser" if python_version < 0x300 else "tkinter_colorchooser", "six.moves.tkinter_commondialog": "tkCommonDialog" if python_version < 0x300 else "tkinter_commondialog", "six.moves.tkinter_tkfiledialog": "tkFileDialog" if python_version < 0x300 else "tkinter.filedialog", "six.moves.tkinter_font": "tkFont" if python_version < 0x300 else "tkinter.font", "six.moves.tkinter_messagebox": "tkMessageBox" if python_version < 0x300 else "tkinter.messagebox", "six.moves.tkinter_tksimpledialog": "tkSimpleDialog" if python_version < 0x300 else "tkinter_tksimpledialog", "six.moves.urllib_parse": None if python_version < 0x300 else "urllib.parse", "six.moves.urllib_error": None if python_version < 0x300 else "urllib.error", "six.moves.urllib_robotparser": "robotparser" if python_version < 0x300 else "urllib.robotparser", "six.moves.xmlrpc_client": "xmlrpclib" if python_version < 0x300 else "xmlrpc.client", "six.moves.xmlrpc_server": "SimpleXMLRPCServer" if python_version < 0x300 else "xmlrpc.server", "six.moves.winreg": "_winreg" if python_version < 0x300 else "winreg", } def resolveModuleName(module_name): """Resolve a module name to its real module name.""" # TODO: This is not handling decoding errors all that well. if str is not unicode and type(module_name) is unicode: module_name = str(module_name) module_name = ModuleName(module_name) # TODO: Allow this to be done by plugins. We compensate meta path based # importer effects here. if module_name.isBelowNamespace("bottle.ext"): # bottle.ext.something -> bottle_something return ModuleName( "bottle_" + module_name.splitPackageName()[1].splitPackageName()[1].asString() ) elif module_name.isBelowNamespace("requests.packages"): # requests.packages.something -> something return module_name.splitPackageName()[1].splitPackageName()[1] elif module_name in _six_moves: # six moves replicated return ModuleName(_six_moves[module_name]) else: return module_name Nuitka-0.6.19.1/nuitka/importing/ImportCache.py0000600000372100037210000000531514166627112026346 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Import cache. This is not about caching the search of modules in the file system, but about maintaining a cache of module trees built. It can happen that modules become unused, and then dropped from active modules, and then later active again, via another import, and in this case, we should not start anew, but reuse what we already found out about it. """ import os from nuitka.plugins.Plugins import Plugins imported_modules = {} imported_by_name = {} def addImportedModule(imported_module): module_filename = os.path.abspath(imported_module.getFilename()) if os.path.basename(module_filename) == "__init__.py": module_filename = os.path.dirname(module_filename) key = (module_filename, imported_module.getFullName()) if key in imported_modules: assert imported_module is imported_modules[key], key else: Plugins.onModuleDiscovered(imported_module) imported_modules[key] = imported_module imported_by_name[imported_module.getFullName()] = imported_module # We don't expect that to happen. assert not imported_module.isMainModule() def isImportedModuleByName(full_name): return full_name in imported_by_name def getImportedModuleByName(full_name): return imported_by_name[full_name] def getImportedModuleByNameAndPath(full_name, module_filename): if module_filename is None: # pyi deps only return getImportedModuleByName(full_name) if os.path.basename(module_filename) == "__init__.py": module_filename = os.path.dirname(module_filename) return imported_modules[module_filename, full_name] def replaceImportedModule(old, new): for key, value in imported_by_name.items(): if value == old: imported_by_name[key] = new break else: assert False for key, value in imported_modules.items(): if value == old: imported_modules[key] = new break else: assert False Nuitka-0.6.19.1/nuitka/importing/StandardLibrary.py0000600000372100037210000001133714166627112027236 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Access to standard library distinction. For code to be in the standard library means that it's not written by the user for sure. We treat code differently based on that information, by e.g. including as byte code. To determine if a module from the standard library, we can abuse the attribute "__file__" of the "os" module like it's done in "isStandardLibraryPath" of this module. """ import os from nuitka.Options import shallUseStaticLibPython from nuitka.utils.FileOperations import getFileContents, isPathBelow from nuitka.utils.Utils import getOS def getStandardLibraryPaths(): """Get the standard library paths.""" # Using the function object to cache its result, avoiding global variable # usage. if not hasattr(getStandardLibraryPaths, "result"): os_filename = os.__file__ if os_filename.endswith(".pyc"): os_filename = os_filename[:-1] os_path = os.path.normcase(os.path.dirname(os_filename)) stdlib_paths = set([os_path]) # Happens for virtualenv situation, some modules will come from the link # this points to. if os.path.islink(os_filename): os_filename = os.readlink(os_filename) stdlib_paths.add(os.path.normcase(os.path.dirname(os_filename))) # Another possibility is "orig-prefix.txt" file near the os.py, which # points to the original install. orig_prefix_filename = os.path.join(os_path, "orig-prefix.txt") if os.path.isfile(orig_prefix_filename): # Scan upwards, until we find a "bin" folder, with "activate" to # locate the structural path to be added. We do not know for sure # if there is a sub-directory under "lib" to use or not. So we try # to detect it. search = os_path lib_part = "" while os.path.splitdrive(search)[1] not in (os.path.sep, ""): if os.path.isfile( os.path.join(search, "bin/activate") ) or os.path.isfile(os.path.join(search, "scripts/activate")): break lib_part = os.path.join(os.path.basename(search), lib_part) search = os.path.dirname(search) assert search and lib_part stdlib_paths.add( os.path.normcase( os.path.join(getFileContents(orig_prefix_filename), lib_part) ) ) # And yet another possibility, for macOS Homebrew created virtualenv # at least is a link ".Python", which points to the original install. python_link_filename = os.path.join(os_path, "..", ".Python") if os.path.islink(python_link_filename): stdlib_paths.add( os.path.normcase(os.path.join(os.readlink(python_link_filename), "lib")) ) for stdlib_path in set(stdlib_paths): candidate = os.path.join(stdlib_path, "lib-tk") if os.path.isdir(candidate): stdlib_paths.add(candidate) if getOS() == "Windows" and not shallUseStaticLibPython(): import _ctypes stdlib_paths.add(os.path.dirname(_ctypes.__file__)) getStandardLibraryPaths.result = [ os.path.normcase(os.path.normpath(stdlib_path)) for stdlib_path in stdlib_paths ] return getStandardLibraryPaths.result def isStandardLibraryPath(filename): """Check if a path is in the standard library.""" filename = os.path.normcase(os.path.normpath(filename)) # In virtualenv, the "site.py" lives in a place that suggests it is not in # standard library, although it is. if os.path.basename(filename) == "site.py": return True # These never are in standard library paths. if "dist-packages" in filename or "site-packages" in filename: return False for candidate in getStandardLibraryPaths(): if isPathBelow(path=candidate, filename=filename): return True return False Nuitka-0.6.19.1/nuitka/importing/__init__.py0000600000372100037210000000150114166627112025700 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/importing/PreloadedPackages.py0000600000372100037210000001001014166627112027472 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This module abstracts what site.py is normally doing in .pth files. This tries to extract "namespaces" packages that were manually created and point to package directories, which need no "__init__.py" to count as a package. Nuitka will pretend for those that there be one, but without content. """ import os import sys from nuitka.Tracing import recursion_logger from nuitka.utils.FileOperations import getFileContentByLine, listDir def getLoadedPackages(): """Extract packages with no __file__, i.e. they got added manually. They are frequently created with "*.pth" files that then check for the "__init__.py" to exist, and when it doesn't, then they create during the loading of "site.py" an package with "__path__" set. """ for module_name, module in sys.modules.items(): if not getattr(module, "__path__", None): continue if hasattr(module, "__file__"): continue yield module_name, module def detectPreLoadedPackagePaths(): result = {} for package_name, module in getLoadedPackages(): result[package_name] = list(module.__path__) return result preloaded_packages = None def getPreloadedPackagePaths(): """Return dictionrary with preloaded package paths from .pth files""" # We need to set this from the outside, pylint: disable=global-statement global preloaded_packages if preloaded_packages is None: preloaded_packages = detectPreLoadedPackagePaths() return preloaded_packages def setPreloadedPackagePaths(value): # We need to set this from the outside, pylint: disable=global-statement global preloaded_packages preloaded_packages = value def getPreloadedPackagePath(package_name): return getPreloadedPackagePaths().get(package_name) def isPreloadedPackagePath(path): path = os.path.normcase(path) for paths in getPreloadedPackagePaths().values(): for element in paths: if os.path.normcase(element) == path: return True return False def detectPthImportedPackages(): if not hasattr(sys.modules["site"], "getsitepackages"): return () pth_imports = set() for prefix in sys.modules["site"].getsitepackages(): if not os.path.isdir(prefix): continue for path, filename in listDir(prefix): if filename.endswith(".pth"): try: for line in getFileContentByLine(path, "rU"): if line.startswith("import "): if ";" in line: line = line[: line.find(";")] for part in line[7:].split(","): pth_import = part.strip() pth_imports.add(pth_import) except OSError: recursion_logger.warning( "Python installation problem, cannot read file '%s'." ) return tuple(sorted(pth_imports)) pth_imported_packages = () def setPthImportedPackages(value): # We need to set this from the outside, pylint: disable=global-statement global pth_imported_packages pth_imported_packages = value def getPthImportedPackages(): return pth_imported_packages Nuitka-0.6.19.1/nuitka/Builtins.py0000600000372100037210000001554414166627112023736 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Built-ins module. Information about built-ins of the running Python. """ import sys from types import BuiltinFunctionType, FunctionType, GeneratorType from nuitka.__past__ import builtins from nuitka.containers.odict import OrderedDict from nuitka.PythonVersions import python_version def _getBuiltinExceptionNames(): def isExceptionName(builtin_name): if builtin_name.endswith("Error") or builtin_name.endswith("Exception"): return True elif builtin_name in ( "StopIteration", "GeneratorExit", "SystemExit", "NotImplemented", "KeyboardInterrupt", "StopAsyncIteration", ): return True else: return False exceptions = OrderedDict() # Hide Python3 changes for built-in exception names if python_version < 0x300: import exceptions as builtin_exceptions # python2 code, pylint: disable=import-error for key in sorted(dir(builtin_exceptions)): name = str(key) if isExceptionName(name): exceptions[name] = getattr(builtin_exceptions, key) for key in sorted(dir(builtins)): name = str(key) if isExceptionName(name): exceptions[name] = getattr(builtins, key) else: for key in sorted(dir(builtins)): if isExceptionName(key): exceptions[key] = getattr(builtins, key) return list(exceptions.keys()), exceptions builtin_exception_names, builtin_exception_values = _getBuiltinExceptionNames() builtin_exception_values_list = tuple(builtin_exception_values.values()) # Just to make sure it's covering these cases correctly. assert "TypeError" in builtin_exception_names assert "ValueError" in builtin_exception_names assert "StopIteration" in builtin_exception_names assert "GeneratorExit" in builtin_exception_names assert "AssertionError" in builtin_exception_names assert "BaseException" in builtin_exception_names assert "Exception" in builtin_exception_names assert "NotImplemented" in builtin_exception_names assert "StopAsyncIteration" in builtin_exception_names or python_version < 0x350 def _getBuiltinNames(): names = [str(x) for x in dir(builtins)] names.sort() for builtin_exception_name in builtin_exception_names: if builtin_exception_name in names: names.remove(builtin_exception_name) names.remove("__doc__") names.remove("__name__") names.remove("__package__") if "__loader__" in names: names.remove("__loader__") if "__spec__" in names: names.remove("__spec__") warnings = [] for builtin_name in names: if builtin_name.endswith("Warning"): warnings.append(builtin_name) for builtin_name in warnings: names.remove(builtin_name) return names, warnings builtin_names, builtin_warnings = _getBuiltinNames() builtin_named_values = dict((getattr(builtins, x), x) for x in builtin_names) builtin_named_values_list = tuple(builtin_named_values) assert type in builtin_named_values assert "__import__" in builtin_names assert "int" in builtin_names assert "type" in builtin_names assert "__doc__" not in builtin_names assert "sys" not in builtin_names builtin_all_names = builtin_names + builtin_exception_names + builtin_warnings def getBuiltinTypeNames(): result = [] for builtin_name in builtin_names: if isinstance(getattr(builtins, builtin_name), type): result.append(builtin_name) return tuple(sorted(result)) builtin_type_names = getBuiltinTypeNames() def _getAnonBuiltins(): # We use the order when encoding in the constants blob. Therefore it is imported # to not reorder these values, the C side uses the absolute indexes. anon_names = OrderedDict() anon_codes = OrderedDict() # Strangely these are not in Python3 types module anon_names["NoneType"] = type(None) anon_codes["NoneType"] = "Py_TYPE(Py_None)" anon_names["ellipsis"] = type(Ellipsis) # see above anon_codes["ellipsis"] = "&PyEllipsis_Type" anon_names["NotImplementedType"] = type(NotImplemented) anon_codes["NotImplementedType"] = "Py_TYPE(Py_NotImplemented)" anon_names["function"] = FunctionType anon_codes["function"] = "&PyFunction_Type" anon_names["generator"] = GeneratorType anon_codes["generator"] = "&PyGenerator_Type" anon_names["builtin_function_or_method"] = BuiltinFunctionType anon_codes["builtin_function_or_method"] = "&PyCFunction_Type" # Can't really have it until we have __nuitka__ # "compiled_function" : BuiltinFunctionType, # "compiled_generator" : GeneratorType, # see above # anon_codes["compiled_function"] = "&Nuitka_Function_Type" # anon_codes["compiled_generator"] = "&Nuitka_Generator_Type" anon_names["code"] = type(_getAnonBuiltins.__code__) anon_codes["code"] = "&PyCode_Type" if python_version < 0x300: # There are only there for Python2, # pylint: disable=I0021,no-name-in-module from types import ClassType, InstanceType, MethodType # We can to be sure of the type here, so use open without encoding, pylint: disable=unspecified-encoding with open(sys.executable) as any_file: anon_names["file"] = type(any_file) anon_codes["file"] = "&PyFile_Type" anon_names["classobj"] = ClassType anon_codes["classobj"] = "&PyClass_Type" anon_names["instance"] = InstanceType anon_codes["instance"] = "&PyInstance_Type" anon_names["instancemethod"] = MethodType anon_codes["instancemethod"] = "&PyMethod_Type" if python_version >= 0x270: anon_names["version_info"] = type(sys.version_info) anon_codes["version_info"] = 'Py_TYPE(Nuitka_SysGetObject("version_info"))' return anon_names, anon_codes builtin_anon_names, builtin_anon_codes = _getAnonBuiltins() builtin_anon_values = OrderedDict((b, a) for a, b in builtin_anon_names.items()) # For being able to check if it's not hashable, we need something not using # a hash. builtin_anon_value_list = tuple(builtin_anon_values) Nuitka-0.6.19.1/nuitka/Variables.py0000600000372100037210000002750514166627112024055 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Variables link the storage and use of a Python variable together. Different kinds of variables represent different scopes and owners types, and their links between each other, i.e. references as in closure or module variable references. """ from abc import abstractmethod from nuitka.__past__ import getMetaClassBase, iterItems from nuitka.nodes.shapes.StandardShapes import tshape_unknown from nuitka.utils import Utils from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) complete = False class Variable(getMetaClassBase("Variable")): # We will need all of these attributes, since we track the global # state and cache some decisions as attributes. TODO: But in some # cases, part of the these might be moved to the outside. __slots__ = ( "variable_name", "owner", "version_number", "shared_users", "traces", "users", "writers", ) @counted_init def __init__(self, owner, variable_name): assert type(variable_name) is str, variable_name assert type(owner) not in (tuple, list), owner self.variable_name = variable_name self.owner = owner self.version_number = 0 self.shared_users = False self.traces = set() # Derived from all traces. self.users = None self.writers = None if isCountingInstances(): __del__ = counted_del() def finalize(self): del self.users del self.writers del self.traces del self.owner def __repr__(self): return "<%s '%s' of '%s'>" % ( self.__class__.__name__, self.variable_name, self.owner.getName(), ) @abstractmethod def getVariableType(self): pass def getDescription(self): return "variable '%s'" % self.variable_name def getName(self): return self.variable_name def getOwner(self): return self.owner def getEntryPoint(self): return self.owner.getEntryPoint() def getCodeName(self): var_name = self.variable_name var_name = var_name.replace(".", "$") var_name = Utils.encodeNonAscii(var_name) return var_name def allocateTargetNumber(self): self.version_number += 1 return self.version_number @staticmethod def isLocalVariable(): return False @staticmethod def isParameterVariable(): return False @staticmethod def isModuleVariable(): return False @staticmethod def isIncompleteModuleVariable(): return False @staticmethod def isTempVariable(): return False @staticmethod def isTempVariableBool(): return False @staticmethod def isLocalsDictVariable(): return False def addVariableUser(self, user): # Update the shared scopes flag. if user is not self.owner: self.shared_users = True # These are not really scopes, just shared uses. if ( user.isExpressionGeneratorObjectBody() or user.isExpressionCoroutineObjectBody() or user.isExpressionAsyncgenObjectBody() ): if self.owner is user.getParentVariableProvider(): return _variables_in_shared_scopes.add(self) def isSharedTechnically(self): if not self.shared_users: return False if not self.users: return False owner = self.owner.getEntryPoint() for user in self.users: user = user.getEntryPoint() while user is not owner and ( (user.isExpressionFunctionBody() and not user.needsCreation()) or user.isExpressionClassBody() ): user = user.getParentVariableProvider() if user is not owner: return True return False def addTrace(self, variable_trace): self.traces.add(variable_trace) def removeTrace(self, variable_trace): self.traces.remove(variable_trace) def getTraces(self): """For debugging only""" return self.traces def updateUsageState(self): writers = set() users = set() for trace in self.traces: owner = trace.owner users.add(owner) if trace.isAssignTrace(): writers.add(owner) elif trace.isDeletedTrace() and owner is not self.owner: writers.add(owner) self.writers = writers self.users = users def hasAccessesOutsideOf(self, provider): if not self.owner.locals_scope.complete: return None elif self.users is None: return False elif provider in self.users: return len(self.users) > 1 else: return bool(self.users) def hasWritersOutsideOf(self, provider): if not self.owner.locals_scope.complete: return None elif self.writers is None: return False elif provider in self.writers: return len(self.writers) > 1 else: return bool(self.writers) def getMatchingAssignTrace(self, assign_node): for trace in self.traces: if trace.isAssignTrace() and trace.getAssignNode() is assign_node: return trace return None def getMatchingDelTrace(self, del_node): for trace in self.traces: if trace.isDeletedTrace() and trace.getDelNode() is del_node: return trace return None def getTypeShapes(self): result = set() for trace in self.traces: if trace.isAssignTrace(): result.add(trace.getAssignNode().getTypeShape()) elif trace.isUnknownTrace(): result.add(tshape_unknown) elif trace.isEscapeTrace(): result.add(tshape_unknown) elif trace.isInitTrace(): result.add(tshape_unknown) elif trace.isUnassignedTrace(): pass elif trace.isMergeTrace(): pass # TODO: Remove this and be not unknown. elif trace.isLoopTrace(): trace.getTypeShape().emitAlternatives(result.add) else: assert False, trace return result class LocalVariable(Variable): __slots__ = () def __init__(self, owner, variable_name): Variable.__init__(self, owner=owner, variable_name=variable_name) @staticmethod def isLocalVariable(): return True @staticmethod def getVariableType(): return "object" class ParameterVariable(LocalVariable): __slots__ = () def __init__(self, owner, parameter_name): LocalVariable.__init__(self, owner=owner, variable_name=parameter_name) def getDescription(self): return "parameter variable '%s'" % self.variable_name @staticmethod def isParameterVariable(): return True class ModuleVariable(Variable): __slots__ = () def __init__(self, module, variable_name): assert type(variable_name) is str, repr(variable_name) assert module.isCompiledPythonModule() Variable.__init__(self, owner=module, variable_name=variable_name) def __repr__(self): return "" % ( self.variable_name, self.owner.getFullName(), ) def getDescription(self): return "global variable '%s'" % self.variable_name @staticmethod def isModuleVariable(): return True def isIncompleteModuleVariable(self): return not self.owner.locals_scope.complete def hasDefiniteWrites(self): if not self.owner.locals_scope.complete: return None else: return bool(self.writers) def getModule(self): return self.owner @staticmethod def getVariableType(): return "object" class TempVariable(Variable): __slots__ = () def __init__(self, owner, variable_name): Variable.__init__(self, owner=owner, variable_name=variable_name) def getDescription(self): return "temp variable '%s'" % self.variable_name @staticmethod def isTempVariable(): return True @staticmethod def getVariableType(): return "object" class TempVariableBool(TempVariable): __slots__ = () def getDescription(self): return "temp bool variable '%s'" % self.variable_name @staticmethod def isTempVariableBool(): return True @staticmethod def getVariableType(): return "bool" class LocalsDictVariable(Variable): __slots__ = () def __init__(self, owner, variable_name): Variable.__init__(self, owner=owner, variable_name=variable_name) @staticmethod def isLocalsDictVariable(): return True @staticmethod def getVariableType(): return "object" def updateVariablesFromCollection(old_collection, new_collection, source_ref): # After removing/adding traces, we need to pre-compute the users state # information. touched_variables = set() loop_trace_removal = set() if old_collection is not None: for (variable, _version), variable_trace in iterItems( old_collection.getVariableTracesAll() ): variable.removeTrace(variable_trace) touched_variables.add(variable) if variable_trace.isLoopTrace(): loop_trace_removal.add(variable) if new_collection is not None: for (variable, _version), variable_trace in iterItems( new_collection.getVariableTracesAll() ): variable.addTrace(variable_trace) touched_variables.add(variable) if variable_trace.isLoopTrace(): if variable in loop_trace_removal: loop_trace_removal.remove(variable) # Release the memory, and prevent the "active" state from being ever # inspected, it's useless now. new_collection.variable_actives.clear() del new_collection.variable_actives for variable in touched_variables: variable.updateUsageState() if loop_trace_removal: if new_collection is not None: new_collection.signalChange( "var_usage", source_ref, lambda: "Loop variable '%s' usage ceased." % ",".join(variable.getName() for variable in loop_trace_removal), ) # To detect the Python2 shared variable deletion, that would be a syntax # error _variables_in_shared_scopes = set() def isSharedAmongScopes(variable): return variable in _variables_in_shared_scopes def releaseSharedScopeInformation(tree): # Singleton, pylint: disable=global-statement assert tree.isCompiledPythonModule() global _variables_in_shared_scopes _variables_in_shared_scopes = set( variable for variable in _variables_in_shared_scopes if variable.getOwner().getParentModule() is not tree ) Nuitka-0.6.19.1/nuitka/Options.py0000600000372100037210000013100214166627112023564 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Options module This exposes the choices made by the user. Defaults will be applied here, and some handling of defaults. """ import os import shlex import sys from nuitka import Progress, Tracing from nuitka.containers.oset import OrderedSet from nuitka.OptionParsing import isPyenvPython, parseOptions from nuitka.PythonFlavors import ( isAnacondaPython, isDebianPackagePython, isMSYS2MingwPython, isNuitkaPython, isUninstalledPython, ) from nuitka.PythonVersions import ( getSupportedPythonVersions, python_version_str, ) from nuitka.utils.Execution import getExecutablePath from nuitka.utils.FileOperations import ( isPathExecutable, openTextFile, resolveShellPatternToFilenames, ) from nuitka.utils.StaticLibraries import getSystemStaticLibPythonPath from nuitka.utils.Utils import ( getArchitecture, getCoreCount, getOS, hasOnefileSupportedOS, hasStandaloneSupportedOS, isFreeBSD, isLinux, isMacOS, isOpenBSD, isWin32Windows, ) options = None positional_args = None extra_args = [] is_nuitka_run = None is_debug = None is_nondebug = None is_fullcompat = None is_report_missing = None def parseArgs(): """Parse the command line arguments :meta private: """ # singleton with many cases checking the options right away. # pylint: disable=global-statement,too-many-branches,too-many-locals,too-many-statements global is_nuitka_run, options, positional_args, extra_args, is_debug, is_nondebug, is_fullcompat, is_report_missing if os.name == "nt": # Windows store Python's don't allow looking at the python, catch that. try: with openTextFile(sys.executable, "rb"): pass except OSError: Tracing.general.sysexit( "Error, the Python from Windows store is not supported, check the User Manual of Nuitka ." ) is_nuitka_run, options, positional_args, extra_args = parseOptions( logger=Tracing.options_logger ) is_debug = _isDebug() is_nondebug = not is_debug is_fullcompat = _isFullCompat() # TODO: Have dedicated option for it. is_report_missing = is_debug if options.quiet or int(os.environ.get("NUITKA_QUIET", "0")): Tracing.setQuiet() if not shallDumpBuiltTreeXML(): Tracing.options_logger.info( "Used command line options: %s" % " ".join(sys.argv[1:]) ) if os.environ.get("NUITKA_REEXECUTION") and not isAllowedToReexecute(): Tracing.general.sysexit( "Error, not allowed to re-execute, but that has happened." ) if options.progress_bar: Progress.enableProgressBar() if options.verbose_output: Tracing.optimization_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. openTextFile(options.verbose_output, "w", encoding="utf8") ) options.verbose = True Tracing.optimization_logger.is_quiet = not options.verbose if options.show_inclusion_output: Tracing.inclusion_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. openTextFile(options.show_inclusion_output, "w", encoding="utf8") ) options.show_inclusion = True Tracing.progress_logger.is_quiet = not options.show_progress # Onefile implies standalone build. if options.is_onefile: options.is_standalone = True # Provide a tempdir spec implies onefile tempdir, even on Linux. if options.onefile_tempdir_spec: options.is_onefile_tempdir = True # Standalone mode implies an executable, not importing "site" module, which is # only for this machine, recursing to all modules, and even including the # standard library. if options.is_standalone: if not options.executable: Tracing.options_logger.sysexit( """\ Error, conflicting options, cannot make standalone module, only executable. Modules are supposed to be imported to an existing Python installation, therefore it makes no sense to include a Python runtime.""" ) for any_case_module in getShallFollowModules(): if any_case_module.startswith("."): bad = True else: for char in "/\\:": if char in any_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit( """\ Error, '--follow-import-to' takes only module names or patterns, not directory path '%s'.""" % any_case_module ) for no_case_module in getShallFollowInNoCase(): if no_case_module.startswith("."): bad = True else: for char in "/\\:": if char in no_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit( """\ Error, '--nofollow-import-to' takes only module names or patterns, not directory path '%s'.""" % no_case_module ) scons_python = getPythonPathForScons() if scons_python is not None and not os.path.isfile(scons_python): Tracing.options_logger.sysexit( "Error, no such Python binary %r, should be full path." % scons_python ) if options.output_filename is not None and ( (isStandaloneMode() and not isOnefileMode()) or shallMakeModule() ): Tracing.options_logger.sysexit( """\ Error, may only specify output filename for acceleration and onefile mode, but not for module mode where filenames are mandatory, and not for standalone where there is a sane default used inside the dist folder.""" ) if isLinux(): if len(getIconPaths()) > 1: Tracing.options_logger.sysexit("Error, can only use one icon on Linux.") for icon_path in getIconPaths(): if "#" in icon_path and isWin32Windows(): icon_path, icon_index = icon_path.rsplit("#", 1) if not icon_index.isdigit() or int(icon_index) < 0: Tracing.options_logger.sysexit( "Error, icon number in %r not valid." % (icon_path + "#" + icon_index) ) if not os.path.exists(icon_path): Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_path ) if getWindowsIconExecutablePath(): Tracing.options_logger.sysexit( "Error, can only use icons from template executable or from icon files, but not both." ) icon_exe_path = getWindowsIconExecutablePath() if icon_exe_path is not None and not os.path.exists(icon_exe_path): Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_exe_path ) try: file_version = getWindowsFileVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, file version must be a tuple of up to 4 integer values." ) try: product_version = getWindowsProductVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, product version must be a tuple of up to 4 integer values." ) if getWindowsCompanyName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable company name.""" ) if getWindowsProductName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""" ) splash_screen_filename = getWindowsSplashScreen() if splash_screen_filename is not None: if not os.path.isfile(splash_screen_filename): Tracing.options_logger.sysexit( "Error, specified splash screen image '%s' does not exist." % splash_screen_filename ) if file_version or product_version or getWindowsVersionInfoStrings(): if not (file_version or product_version) and getWindowsCompanyName(): Tracing.options_logger.sysexit( "Error, company name and file or product version need to be given when any version information is given." ) if isOnefileMode() and not hasOnefileSupportedOS(): Tracing.options_logger.sysexit("Error, unsupported OS for onefile %r" % getOS()) if options.follow_none and options.follow_all: Tracing.options_logger.sysexit( "Conflicting options '--follow-imports' and '--nofollow-imports' given." ) if getShallIncludePackageData() and not isStandaloneMode(): Tracing.options_logger.sysexit( "Error, package data files are only included in standalone or onefile mode." ) for module_pattern in getShallIncludePackageData(): if ( module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern ): Tracing.options_logger.sysexit( "Error, '--include-package-data' needs module name or pattern as an argument, not %r." % module_pattern ) for module_pattern in getShallFollowModules(): if ( module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern ): Tracing.options_logger.sysexit( "Error, '--follow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern ) for module_pattern in getShallFollowInNoCase(): if ( module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern ): Tracing.options_logger.sysexit( "Error, '--nofollow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern ) for data_file in options.data_files: if "=" not in data_file: Tracing.options_logger.sysexit( "Error, malformed data file description, must specify relative target path separated with '='." ) if data_file.count("=") == 1: src, dst = data_file.split("=", 1) filenames = resolveShellPatternToFilenames(src) if len(filenames) > 1 and not dst.endswith(("/", os.path.sep)): Tracing.options_logger.sysexit( "Error, pattern '%s' matches more than one file, but target has no trailing slash, not a directory." % src ) else: src, dst, pattern = data_file.split("=", 2) filenames = resolveShellPatternToFilenames(os.path.join(src, pattern)) if not filenames: Tracing.options_logger.sysexit( "Error, '%s' does not match any files." % src ) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data file, not absolute path '%s'." % data_file ) for data_dir in options.data_dirs: if "=" not in data_dir: Tracing.options_logger.sysexit( "Error, malformed data dir description, must specify relative target path with '=' separating it." ) src, dst = data_dir.split("=", 1) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data dir, not %r as in %r." % (dst, data_dir) ) if not os.path.isdir(src): Tracing.options_logger.sysexit( "Error, must specify existing source data directory, not %r as in %r." % (dst, data_dir) ) if (options.data_files or options.data_dirs) and not isStandaloneMode(): Tracing.options_logger.sysexit( "Error, data files are only included in standalone or onefile mode." ) for pattern in getShallFollowExtraFilePatterns(): if os.path.isdir(pattern): Tracing.options_logger.sysexit( "Error, pattern %r given to '--include-plugin-files' cannot be a directory name." % pattern ) if options.static_libpython == "yes" and getSystemStaticLibPythonPath() is None: Tracing.options_logger.sysexit( "Error, static libpython is not found or not supported for this Python installation." ) if shallUseStaticLibPython() and getSystemStaticLibPythonPath() is None: Tracing.options_logger.sysexit( """Error, usable static libpython is not found for this Python installation. You \ might be missing required packages. Disable with --static-libpython=no" if you don't \ want to install it.""" ) if isStandaloneMode() and isMacOS() and sys.executable.startswith("/usr/bin/"): Tracing.options_logger.sysexit( "Error, Apple Python from macOS is not supported, use e.g. CPython instead." ) if isStandaloneMode() and isLinux() and getExecutablePath("patchelf") is None: Tracing.options_logger.sysexit( "Error, standalone mode on Linux requires 'patchelf' to be installed. Use 'apt/dnf/yum install patchelf' first." ) pgo_executable = getPgoExecutable() if pgo_executable and not isPathExecutable(pgo_executable): Tracing.options_logger.sysexit( "Error, path '%s' to binary to use for PGO is not executable." % pgo_executable ) def commentArgs(): """Comment on options, where we know something is not having the intended effect. :meta private: """ # A ton of cases to consider, pylint: disable=too-many-branches,too-many-statements # Inform the user about potential issues with the running version. e.g. unsupported # version. if python_version_str not in getSupportedPythonVersions(): # Do not disturb run of automatic tests with, detected from the presence of # that environment variable. if "PYTHON" not in os.environ: Tracing.general.warning( "The version %r is not currently supported. Expect problems." % python_version_str, ) default_reference_mode = ( "runtime" if shallMakeModule() or isStandaloneMode() else "original" ) if getFileReferenceMode() is None: options.file_reference_mode = default_reference_mode else: if options.file_reference_mode != default_reference_mode: Tracing.options_logger.warning( "Using non-default file reference mode '%s' rather than '%s' may cause runtime issues." % (getFileReferenceMode(), default_reference_mode) ) else: Tracing.options_logger.info( "Using default file reference mode '%s' need not be specified." % default_reference_mode ) # TODO: Not all of these are usable with MSYS2 really, split those off. if getOS() != "Windows": # Too many Windows specific options clearly, pylint: disable=too-many-boolean-expressions if ( getWindowsIconExecutablePath() or shallAskForWindowsAdminRights() or shallAskForWindowsUIAccessRights() or getWindowsCompanyName() or getWindowsProductName() or getWindowsProductVersion() or getWindowsFileVersion() or getForcedStderrPath() # not yet for other platforms or getForcedStdoutPath() or getWindowsSplashScreen() or getIntendedPythonArch() ): Tracing.options_logger.warning( "Using Windows specific options has no effect on other platforms." ) if options.mingw64 or options.msvc_version: Tracing.options_logger.warning( "Requesting Windows specific compilers has no effect on other platforms." ) if isMingw64() and getMsvcVersion(): Tracing.options_logger.sysexit( "Requesting both Windows specific compilers makes no sense." ) if isOnefileMode(): standalone_mode = "onefile" elif isStandaloneMode(): standalone_mode = "standalone" else: standalone_mode = None if standalone_mode and not hasStandaloneSupportedOS(): Tracing.options_logger.warning( "Standalone mode on %s is not known to be supported, might fail to work." % getOS() ) if options.follow_all and standalone_mode: Tracing.options_logger.info( "Following all imports is the default for %s mode and need not be specified." % standalone_mode ) if options.follow_none and standalone_mode: Tracing.options_logger.warning( "Following no imports is unlikely to work for %s mode and should not be specified." % standalone_mode ) if ( not shallDumpBuiltTreeXML() and not standalone_mode and not options.follow_all and not options.follow_none and not options.follow_modules and not options.follow_stdlib and not options.include_modules and not options.include_packages and not options.include_extra and not options.follow_not_modules ): Tracing.options_logger.warning( """You did not specify to follow or include anything but main %s. Check options and \ make sure that is intended.""" % ("module" if shallMakeModule() else "program") ) if options.dependency_tool: Tracing.options_logger.warning( "Using removed option '--windows-dependency-tool' is deprecated and has no impact anymore." ) if shallMakeModule() and options.static_libpython == "yes": Tracing.options_logger.warning( "In module mode, providing '--static-libpython' has no effect, it's not used." ) options.static_libpython = "no" if ( not isPgoMode() and not isPythonPgoMode() and (getPgoArgs() or getPgoExecutable()) ): Tracing.optimization_logger.warning( "Providing PGO arguments without enabling PGO mode has no effect." ) if isPgoMode(): if isStandaloneMode(): Tracing.optimization_logger.warning( "Using PGO with standalone/onefile mode is not currently working. Expect errors." ) if shallMakeModule(): Tracing.optimization_logger.warning( "Using PGO with module mode is not currently working. Expect errors." ) if ( options.static_libpython == "auto" and not shallMakeModule() and not shallDumpBuiltTreeXML() and not shallUseStaticLibPython() and getSystemStaticLibPythonPath() is not None ): Tracing.options_logger.info( """Detected static libpython to exist, consider '--static-libpython=yes' for better performance, \ but errors may happen.""" ) if not shallExecuteImmediately(): if shallRunInDebugger(): Tracing.options_logger.warning( "The '--debugger' option has no effect outside of '--debug' without '--run' option." ) if not shallClearPythonPathEnvironment(): Tracing.options_logger.warning( "The '--execute-with-pythonpath' option has no effect without '--run' option." ) def isVerbose(): """:returns: bool derived from ``--verbose``""" return options is not None and options.verbose def shallTraceExecution(): """:returns: bool derived from ``--trace-execution``""" return options.trace_execution def shallExecuteImmediately(): """:returns: bool derived from ``--run``""" return options.immediate_execution def shallRunInDebugger(): """:returns: bool derived from ``--debug``""" return options.debugger def shallDumpBuiltTreeXML(): """:returns: bool derived from ``--xml``""" return options.dump_xml def shallOnlyExecCCompilerCall(): """:returns: bool derived from ``--recompile-c-only``""" return options.recompile_c_only def shallNotDoExecCCompilerCall(): """:returns: bool derived from ``--generate-c-only``""" return options.generate_c_only def getFileReferenceMode(): """*str*, one of "runtime", "original", "frozen", coming from ``--file-reference-choice`` Notes: Defaults to runtime for modules and packages, as well as standalone binaries, otherwise original is kept. """ return options.file_reference_mode def shallMakeModule(): """:returns: bool derived from ``--module``""" return not options.executable def shallCreatePyiFile(): """*bool* = **not** ``--no-pyi-file``""" return options.pyi_file def isAllowedToReexecute(): """*bool* = **not** ``--must-not-re-execute``""" return options.allow_reexecute def shallFollowStandardLibrary(): """:returns: bool derived from ``--follow-stdlib``""" return options.follow_stdlib def shallFollowNoImports(): """:returns: bool derived from ``--nofollow-imports``""" return options.follow_none def shallFollowAllImports(): """:returns: bool derived from ``--follow-imports``""" return options.is_standalone or options.follow_all def _splitShellPattern(value): return value.split(",") if "{" not in value else [value] def getShallFollowInNoCase(): """*list*, items of ``--nofollow-import-to=``""" return sum([_splitShellPattern(x) for x in options.follow_not_modules], []) def getShallFollowModules(): """*list*, items of ``--follow-import-to=``""" return sum( [ _splitShellPattern(x) for x in options.follow_modules + options.include_modules + options.include_packages ], [], ) def getShallFollowExtra(): """*list*, items of ``--include-plugin-directory=``""" return sum([_splitShellPattern(x) for x in options.include_extra], []) def getShallFollowExtraFilePatterns(): """*list*, items of ``--include-plugin-files=``""" return sum([_splitShellPattern(x) for x in options.include_extra_files], []) def getMustIncludeModules(): """*list*, items of ``--include-module=``""" return sum([_splitShellPattern(x) for x in options.include_modules], []) def getMustIncludePackages(): """*list*, items of ``--include-package=``""" return sum([_splitShellPattern(x) for x in options.include_packages], []) def getShallIncludePackageData(): """*list*, items of ``--include-package-data=``""" return sum([_splitShellPattern(x) for x in options.package_data], []) def getShallIncludeDataFiles(): """*list*, items of ``--include-data-file=``""" for data_file in options.data_files: if data_file.count("=") == 1: src, dest = data_file.split("=", 1) for pattern in _splitShellPattern(src): yield pattern, None, dest, data_file else: src, dest, pattern = data_file.split("=", 2) for pattern in _splitShellPattern(pattern): yield os.path.join(src, pattern), src, dest, data_file def getShallIncludeDataDirs(): """*list*, items of ``--include-data-dir=``""" for data_file in options.data_dirs: src, dest = data_file.split("=", 1) yield src, dest def shallWarnImplicitRaises(): """:returns: bool derived from ``--warn-implicit-exceptions``""" return options.warn_implicit_exceptions def shallWarnUnusualCode(): """:returns: bool derived from ``--warn-unusual-code``""" return options.warn_unusual_code def assumeYesForDownloads(): """:returns: bool derived from ``--assume-yes-for-downloads``""" return options is not None and options.assume_yes_for_downloads def _isDebug(): """:returns: bool derived from ``--debug`` or ``--debugger``""" return options is not None and (options.debug or options.debugger) def isPythonDebug(): """:returns: bool derived from ``--python-debug`` or ``sys.flags.debug`` Passed to Scons as ``python_debug`` so it can consider it when picking link libraries to choose the correct variant. Also enables the define ``Py_DEBUG`` for C headers. Reference counting checks and other debug asserts of Python will happen in this mode. """ return options.python_debug or sys.flags.debug def isUnstripped(): """:returns: bool derived from ``--unstripped`` or ``--profile`` A binary is called stripped when debug information is not present, an unstripped when it is present. For profiling and debugging it will be necessary, but it doesn*t enable debug checks like ``--debug`` does. Passed to Scons as ``unstripped_mode`` to it can ask the linker to include symbol information. """ return options.unstripped or options.profile def isProfile(): """:returns: bool derived from ``--profile``""" return options.profile def shallCreateGraph(): """:returns: bool derived from ``--graph``""" return options.graph def getOutputFilename(): """*str*, value of "-o" """ return options.output_filename def getOutputPath(path): """Return output pathname of a given path (filename).""" if options.output_dir: return os.path.normpath(os.path.join(options.output_dir, path)) else: return path def getOutputDir(): """*str*, value of ``--output-dir`` or "." """ return options.output_dir if options.output_dir else "." def getPositionalArgs(): """*tuple*, command line positional arguments""" return tuple(positional_args) def getMainArgs(): """*tuple*, arguments following the optional arguments""" return tuple(extra_args) def shallOptimizeStringExec(): """Inactive yet""" return False def shallClearPythonPathEnvironment(): """*bool* = **not** ``--execute-with-pythonpath``""" return not options.keep_pythonpath _shall_use_static_lib_python = None def _shallUseStaticLibPython(): # return driven, pylint: disable=too-many-return-statements if shallMakeModule(): return False, "not used in module mode" if options.static_libpython == "auto": # Nuitka-Python is good to to static linking. if isNuitkaPython(): return True, "Nuitka-Python is broken." # Debian packages with are usable if the OS is new enough from nuitka.utils.StaticLibraries import ( isDebianSuitableForStaticLinking, ) if ( isDebianPackagePython() and isDebianSuitableForStaticLinking() and not isPythonDebug() ): return True, "Nuitka on Debian-Python needs package '%s' installed." % ( "python2-dev" if str is bytes else "python3-dev" ) if isMSYS2MingwPython(): return True, "Nuitka on MSYS2 needs package 'python-devel' installed." # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. if isAnacondaPython() and not isMacOS() and not isWin32Windows(): return True, "Nuitka on Anaconda needs package 'libpython' installed." if isPyenvPython(): return True, "Nuitka on pyenv should not use '--enable-shared'." return options.static_libpython == "yes", None def shallUseStaticLibPython(): """:returns: bool derived from ``--static-libpython=yes|auto`` and not module mode Notes: Currently only Anaconda on non-Windows can do this and MSYS2. """ global _shall_use_static_lib_python # singleton, pylint: disable=global-statement if _shall_use_static_lib_python is None: _shall_use_static_lib_python, reason = _shallUseStaticLibPython() if _shall_use_static_lib_python and reason: static_libpython = getSystemStaticLibPythonPath() if not static_libpython: Tracing.options_logger.sysexit( """\ Automatic detection of static libpython failed. %s Disable with '--static-libpython=no' if you don't \ want to install it.""" % reason ) return _shall_use_static_lib_python def shallTreatUninstalledPython(): """*bool* = derived from Python installation and modes Notes: Not done for standalone mode obviously. The Python DLL will be a dependency of the executable and treated that way. Also not done for extension modules, they are loaded with a Python runtime available. Most often uninstalled Python versions are self compiled or from Anaconda. """ if shallMakeModule() or isStandaloneMode(): return False return isUninstalledPython() def isShowScons(): """:returns: bool derived from ``--show-scons``""" return options.show_scons def getJobLimit(): """*int*, value of ``--jobs`` / "-j" or number of CPU kernels""" if options.jobs is None: if options.low_memory: return 1 else: return getCoreCount() return int(options.jobs) def getLtoMode(): """:returns: bool derived from ``--lto`` or ``--pgo``""" return options.lto def isClang(): """:returns: bool derived from ``--clang`` or enforced by platform, e.g. macOS or FreeBSD some targets.""" return ( options.clang or isMacOS() or isOpenBSD() or (isFreeBSD() and getArchitecture() != "powerpc") ) def isMingw64(): """:returns: bool derived from ``--mingw64``, available only on Windows, otherwise false""" if isWin32Windows(): return options.mingw64 or isMSYS2MingwPython() else: return None def getMsvcVersion(): """:returns: str derived from ``--msvc`` on Windows, otherwise None""" if isWin32Windows(): return options.msvc_version else: return None def shallDisableCCacheUsage(): """:returns: bool derived from ``disable-ccache``""" return options.disable_ccache def shallDisableConsoleWindow(): """:returns: bool derived from ``--win-disable-console or ``--macos-disable-console``""" return options.disable_console def _isFullCompat(): """:returns: bool derived from ``--full-compat`` Notes: Code should should use "Options.is_fullcompat" instead, this is only used to initialize that value. """ return options is not None and not options.improved def isShowProgress(): """:returns: bool derived from ``--show-progress``""" return options is not None and options.show_progress def isShowMemory(): """:returns: bool derived from ``--show-memory``""" return options is not None and options.show_memory def isShowInclusion(): """:returns: bool derived from ``--show-modules``""" return options.show_inclusion def isRemoveBuildDir(): """:returns: bool derived from ``--remove-output``""" return options.remove_build and not options.generate_c_only def getIntendedPythonArch(): """:returns: str, one of ``"x86"``, ``"x86_64"`` or ``None`` Notes: This is only available on Windows, on other platforms it will be `None` """ return options.python_arch if isWin32Windows() else None experimental = set() def isExperimental(indication): """Check whether a given experimental feature is enabled. Args: indication: (str) feature name Returns: bool """ return ( indication in experimental or hasattr(options, "experimental") and indication in options.experimental ) def enableExperimental(indication): experimental.add(indication) def disableExperimental(indication): experimental.remove(indication) def getExperimentalIndications(): """*tuple*, items of ``--experimental=``""" if hasattr(options, "experimental"): return options.experimental else: return () def shallExplainImports(): """:returns: bool derived from ``--explain-imports``""" return options is not None and options.explain_imports def isStandaloneMode(): """:returns: bool derived from ``--standalone``""" return options.is_standalone def isOnefileMode(): """:returns: bool derived from ``--onefile``""" return options.is_onefile def isOnefileTempDirMode(): """:returns: bool derived from ``--onefile-tempdir`` and OS Notes: On all but Linux, using a bootstrap binary that does unpack is mandatory, but on Linux, the AppImage tool is used by default, this enforces using a bootstrap binary there too. """ return not isLinux() or options.is_onefile_tempdir def isPgoMode(): """:returns: bool derived from ``--pgo``""" return options.is_c_pgo def isPythonPgoMode(): """:returns: bool derived from ``--pgo-python``""" return options.is_python_pgo def getPythonPgoInput(): """:returns: str derived from ``--pgo-python-input``""" return options.python_pgo_input def shallCreatePgoInput(): return isPythonPgoMode() and getPythonPgoInput() is None def getPgoArgs(): """*list* = ``--pgo-args``""" return shlex.split(options.pgo_args) def getPgoExecutable(): """*str* = ``--pgo-args``""" if options.pgo_executable and os.path.exists(options.pgo_executable): if not os.path.isabs(options.pgo_executable): options.pgo_executable = os.path.normcase( os.path.join(".", options.pgo_executable) ) return options.pgo_executable def getPythonPgoUnseenModulePolicy(): """*str* = ``--python-pgo-unused-module-policy``""" return options.python_pgo_policy_unused_module def getOnefileTempDirSpec(use_default): if use_default: return ( options.onefile_tempdir_spec or "%TEMP%" + os.path.sep + "onefile_%PID%_%TIME%" ) else: return options.onefile_tempdir_spec def getIconPaths(): """*list of str*, values of ``--windows-icon-from-ico`` and ``--linux-onefile-icon``""" result = options.icon_path # Check if Linux icon requirement is met. if isLinux() and not result and isOnefileMode(): default_icons = ( "/usr/share/pixmaps/python%s.xpm" % python_version_str, "/usr/share/pixmaps/python%s.xpm" % sys.version_info[0], "/usr/share/pixmaps/python.xpm", ) for icon in default_icons: if os.path.exists(icon): result.append(icon) break else: Tracing.options_logger.sysexit( """\ Error, none of the default icons '%s' exist, making '--linux-onefile-icon' required.""" % ", ".join(default_icons) ) return result def getWindowsIconExecutablePath(): """*str* or *None* if not given, value of ``--windows-icon-from-exe``""" return options.icon_exe_path def shallAskForWindowsAdminRights(): """*bool*, value of ``--windows-uac-admin`` or ``--windows-uac-uiaccess``""" return options.windows_uac_admin def shallAskForWindowsUIAccessRights(): """*bool*, value of ``--windows-uac-uiaccess``""" return options.windows_uac_uiaccess def getWindowsVersionInfoStrings(): """*dict of str*, values of .""" result = {} company_name = getWindowsCompanyName() if company_name: result["CompanyName"] = company_name product_name = getWindowsProductName() if product_name: result["ProductName"] = product_name if options.windows_file_description: result["FileDescription"] = options.windows_file_description return result def _parseWindowsVersionNumber(value): if value: parts = value.split(".") assert len(parts) <= 4 while len(parts) < 4: parts.append("0") r = tuple(int(d) for d in parts) assert min(r) >= 0 assert max(r) < 2 ** 16 return r else: return None def getWindowsProductVersion(): """:returns: tuple of 4 ints or None, derived from ``--windows-product-version``""" return _parseWindowsVersionNumber(options.windows_product_version) def getWindowsFileVersion(): """:returns tuple of 4 ints or None, derived from ``--windows-file-version``""" return _parseWindowsVersionNumber(options.windows_file_version) def getWindowsSplashScreen(): """:returns: bool derived from ``--onefile-windows-splash-screen-image``""" return options.splash_screen_image def getWindowsCompanyName(): """*str* name of the company to use""" return options.windows_company_name def getWindowsProductName(): """*str* name of the product to use""" return options.windows_product_name def shallCreateAppBundle(): """*bool* shall create an application bundle""" return options.macos_create_bundle def getMacOSAppName(): """*str* name of the app to use bundle""" return options.macos_app_name def getMacOSSignedAppName(): """*str* name of the app to use during signing""" return options.macos_signed_app_name def getMacOSAppVersion(): """*str* version of the app to use for bundle""" return options.macos_app_version _python_flags = None def _getPythonFlags(): """*list*, values of ``--python-flag``""" # There is many flags, pylint: disable=too-many-branches # singleton, pylint: disable=global-statement global _python_flags if _python_flags is None: _python_flags = set() for parts in options.python_flags: for part in parts.split(","): if part in ("-S", "nosite", "no_site"): _python_flags.add("no_site") elif part in ( "-R", "static_hashes", "norandomization", "no_randomization", ): _python_flags.add("no_randomization") elif part in ("-v", "trace_imports", "trace_import"): _python_flags.add("trace_imports") elif part in ("no_warnings", "nowarnings"): _python_flags.add("no_warnings") elif part in ("-O", "no_asserts", "noasserts"): _python_flags.add("no_asserts") elif part in ("no_docstrings", "nodocstrings"): _python_flags.add("no_docstrings") elif part in ("-OO",): _python_flags.add("no_docstrings") _python_flags.add("no_asserts") elif part in ("no_annotations", "noannotations"): _python_flags.add("no_annotations") elif part in ("-m", "package_mode"): _python_flags.add("package_mode") else: Tracing.options_logger.sysexit("Unsupported python flag %r." % part) return _python_flags def hasPythonFlagNoSite(): """*bool* = "no_site" in python flags given""" return "no_site" in _getPythonFlags() def hasPythonFlagNoAnnotations(): """*bool* = "no_annotations" in python flags given""" return "no_annotations" in _getPythonFlags() def hasPythonFlagNoAsserts(): """*bool* = "no_asserts" in python flags given""" return "no_asserts" in _getPythonFlags() def hasPythonFlagNoDocstrings(): """*bool* = "no_docstrings" in python flags given""" return "no_docstrings" in _getPythonFlags() def hasPythonFlagNoWarnings(): """*bool* = "no_docstrings" in python flags given""" return "no_warnings" in _getPythonFlags() def hasPythonFlagTraceImports(): """*bool* = "trace_imports", "-v" in python flags given""" return "trace_imports" in _getPythonFlags() def hasPythonFlagNoRandomization(): """*bool* = "no_randomization", "-R", "static_hashes" in python flags given""" return "no_randomization" in _getPythonFlags() def hasPythonFlagPackageMode(): """*bool* = "package_mode", "-m" in python flags given""" return "package_mode" in _getPythonFlags() def shallFreezeAllStdlib(): """*bool* = **not** shallFollowStandardLibrary""" return not shallFollowStandardLibrary() def getWindowsDependencyTool(): """*str*, value of ``--windows-dependency-tool=``""" return options.dependency_tool def shallNotUseDependsExeCachedResults(): """:returns: bool derived from ``--disable-dll-dependency-cache`` or ``--force-dll-dependency-cache-update``""" return shallNotStoreDependsExeCachedResults() or getattr( options, "update_dependency_cache", False ) def shallNotStoreDependsExeCachedResults(): """:returns: bool derived from ``--disable-dll-dependency-cache``""" return getattr(options, "no_dependency_cache", False) def getPluginNameConsideringRenames(plugin_name): """Name of the plugin with renames considered.""" if plugin_name == "qt-plugins": return "pyqt5" elif plugin_name == "etherium": return "ethereum" else: return plugin_name def getPluginsEnabled(): """*tuple*, user enabled (standard) plugins (not including user plugins) Note: Do not use this outside of main binary, as plugins are allowed to activate plugins themselves and that will not be visible here. """ result = OrderedSet() if options: for plugin_enabled in options.plugins_enabled: result.update( getPluginNameConsideringRenames(plugin_name) for plugin_name in plugin_enabled.split(",") ) return tuple(result) def getPluginsDisabled(): """*tuple*, user disabled (standard) plugins. Note: Do not use this outside of main binary, as other plugins, e.g. hinted compilation will activate plugins themselves and this will not be visible here. """ result = OrderedSet() if options: for plugin_disabled in options.plugins_disabled: result.update( getPluginNameConsideringRenames(plugin_name) for plugin_name in plugin_disabled.split(",") ) return tuple(result) def getUserPlugins(): """*tuple*, items user provided of ``--user-plugin=``""" if not options: return () return tuple(set(options.user_plugins)) def shallDetectMissingPlugins(): """*bool* = **not** ``--plugin-no-detection``""" return options is not None and options.detect_missing_plugins def getPythonPathForScons(): """*str*, value of ``--python-for-scons``""" return options.python_scons def shallCompileWithoutBuildDirectory(): """*bool* currently hard coded, not when using debugger. When this is used, compilation is executed in a fashion that it runs inside the build folder, hiding it, attempting to make results more reproducible across builds of different programs. TODO: Make this not hardcoded, but possible to disable via an options. """ return not shallRunInDebugger() def shallPreferSourcecodeOverExtensionModules(): """*bool* prefer source code over extension modules if both are there""" return options is not None and options.prefer_source_code def shallUseProgressBar(): """*bool* prefer source code over extension modules if both are there""" return options.progress_bar def getForcedStdoutPath(): """*str* force program stdout output into that filename""" return options.force_stdout_spec def getForcedStderrPath(): """*str* force program stderr output into that filename""" return options.force_stderr_spec def shallPersistModifications(): """*bool* write plugin source changes to disk""" return options is not None and options.persist_source_changes def isLowMemory(): """*bool* low memory usage requested""" return options.low_memory def getCompilationReportFilename(): """*str* filename to write XML report of compilation to""" return options.compilation_report_filename Nuitka-0.6.19.1/nuitka/Version.py0000600000372100037210000000264014167275603023570 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Nuitka version related stuff. """ version_string = """\ Nuitka V0.6.19.1 Copyright (C) 2021 Kay Hayen.""" def getNuitkaVersion(): """Return Nuitka version as a string. This should not be used for >= comparisons directly. """ return version_string.split()[1][1:] def getNuitkaVersionYear(): """The year of Nuitka copyright for use in generations.""" return int(version_string.split()[4]) def getCommercialVersion(): """Return Nuitka commercial version if installed.""" try: from nuitka.tools.commercial import Version except ImportError: return None else: return Version.__version__ Nuitka-0.6.19.1/nuitka/TreeXML.py0000600000372100037210000000560714166627112023424 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ XML node tree handling Means to create XML elements from Nuitka tree nodes and to convert the XML tree to ASCII or output it. """ from nuitka.__past__ import StringIO from . import Tracing def _indent(elem, level=0, more_sibs=False): i = "\n" if level: i += (level - 1) * " " num_kids = len(elem) if num_kids: if not elem.text or not elem.text.strip(): elem.text = i + " " if level: elem.text += " " count = 0 for kid in elem: _indent(kid, level + 1, count < num_kids - 1) count += 1 if not elem.tail or not elem.tail.strip(): elem.tail = i if more_sibs: elem.tail += " " else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i if more_sibs: elem.tail += " " return elem def _dedent(elem, level=0): if not elem.text or not elem.text.strip(): elem.text = "" for child in elem: _dedent(child, level + 1) if not elem.tail or not elem.tail.strip(): elem.tail = "" return elem try: import xml.etree.ElementTree xml_module = xml.etree.ElementTree Element = xml.etree.ElementTree.Element def xml_tostring(tree, indent=True): if indent: _indent(tree) elif not indent: _dedent(tree) return xml_module.tostring(tree) except ImportError: xml_module = None Element = None xml_tostring = None # TODO: Use the writer to create the XML we output. That should be more # scalable and/or faster. try: import lxml.xmlfile # pylint: disable=I0021,import-error xml_writer = lxml.xmlfile except ImportError: xml_writer = None def toBytes(tree, indent=True): return xml_tostring(tree, indent=indent) def toString(tree): result = toBytes(tree) if str is not bytes: result = result.decode("utf8") return result def fromString(text): return xml_module.parse(StringIO(text)).getroot() def dump(tree): value = toString(tree).rstrip() Tracing.printLine(value) Nuitka-0.6.19.1/nuitka/build/0000700000372100037210000000000014167275622022665 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/build/SconsProgress.py0000600000372100037210000000256214166627112026052 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Progress bar for Scons compilation part. This does only the interfacing with tracing and collection of information. """ from nuitka.Progress import ( closeProgressBar, enableProgressBar, reportProgressBar, setupProgressBar, ) def enableSconsProgressBar(): enableProgressBar() import atexit atexit.register(closeSconsProgressBar) def setSconsProgressBarTotal(name, total): setupProgressBar(stage="%s C" % name, unit="file", total=total) def updateSconsProgressBar(): reportProgressBar(item=None, update=True) def closeSconsProgressBar(): closeProgressBar() Nuitka-0.6.19.1/nuitka/build/static_src/0000700000372100037210000000000014167275622025023 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonLt.c0000600000372100037210000156317514166627112031142 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<" (LT) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_LT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a < b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_LT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a < b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_LT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a < b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LT_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_LT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LT_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_LT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LT_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_LT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LT_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_LT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_LT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_LT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LT); CHECK_OBJECT(r); return r; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LT_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_LT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LT); CHECK_OBJECT(r); // Convert to target type if necessary bool result = r == Py_True; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LT_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_LT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LT); CHECK_OBJECT(r); // Convert to target type if necessary nuitka_bool result = r == Py_True ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_LT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_LT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_LT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_LT_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_LT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_LT_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_LT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c < 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_LT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_LT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_LT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_LT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LT_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LT_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LT_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_LT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_LT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_LT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_LT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_LT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LT_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LT_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LT_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() < %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a < b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_LT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_LT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a < b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_LT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_LT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a < b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LT_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LT_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LT_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_LT_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_LT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_LT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_LT_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_LT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_LT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_LT_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LT_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LT_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LT_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_LT_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_LT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_LT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_LT_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_LT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_LT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a < len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_LT_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LT_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LT_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_LT_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LT_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LT_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() < list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LT_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LT_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LT_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LT_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LT_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() < %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceAddUtils.c0000600000372100037210000000774114166627112033405 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* These slots are still manually coded and are used by the generated code. * * The plan should be to generate these as well. Currently also naming is * very inconsistent. */ #if PYTHON_VERSION < 0x300 #include #define PyStringObject_SIZE (offsetof(PyStringObject, ob_sval) + 1) NUITKA_MAY_BE_UNUSED static bool STRING_RESIZE(PyObject **value, Py_ssize_t newsize) { PyStringObject *sv; _Py_DEC_REFTOTAL; _Py_ForgetReference(*value); *value = (PyObject *)PyObject_REALLOC((char *)*value, PyStringObject_SIZE + newsize); if (unlikely(*value == NULL)) { PyErr_NoMemory(); return false; } _Py_NewReference(*value); sv = (PyStringObject *)*value; Py_SIZE(sv) = newsize; sv->ob_sval[newsize] = '\0'; sv->ob_shash = -1; return true; } NUITKA_MAY_BE_UNUSED static bool STRING_ADD_INPLACE(PyObject **operand1, PyObject *operand2) { assert(PyString_CheckExact(*operand1)); assert(!PyString_CHECK_INTERNED(*operand1)); assert(PyString_CheckExact(operand2)); Py_ssize_t operand1_size = PyString_GET_SIZE(*operand1); Py_ssize_t operand2_size = PyString_GET_SIZE(operand2); Py_ssize_t new_size = operand1_size + operand2_size; if (unlikely(new_size < 0)) { PyErr_Format(PyExc_OverflowError, "strings are too large to concat"); return false; } if (unlikely(STRING_RESIZE(operand1, new_size) == false)) { return false; } memcpy(PyString_AS_STRING(*operand1) + operand1_size, PyString_AS_STRING(operand2), operand2_size); return true; } #endif #if PYTHON_VERSION >= 0x300 NUITKA_MAY_BE_UNUSED static bool BYTES_ADD_INCREMENTAL(PyObject **operand1, PyObject *operand2) { assert(PyBytes_CheckExact(*operand1)); assert(PyBytes_CheckExact(operand2)); // Buffer of operand2 Py_buffer wb; wb.len = -1; int res = PyObject_GetBuffer(operand2, &wb, PyBUF_SIMPLE); // Has to work. assert(res == 0); Py_ssize_t oldsize = PyBytes_GET_SIZE(*operand1); if (oldsize > PY_SSIZE_T_MAX - wb.len) { PyErr_NoMemory(); PyBuffer_Release(&wb); return false; } if (_PyBytes_Resize(operand1, oldsize + wb.len) < 0) { PyBuffer_Release(&wb); return false; } memcpy(PyBytes_AS_STRING(*operand1) + oldsize, wb.buf, wb.len); PyBuffer_Release(&wb); return true; } #endif NUITKA_MAY_BE_UNUSED static bool UNICODE_ADD_INCREMENTAL(PyObject **operand1, PyObject *operand2) { Py_ssize_t operand2_size = PyUnicode_GET_SIZE(operand2); if (operand2_size == 0) return true; #if PYTHON_VERSION < 0x300 Py_ssize_t operand1_size = PyUnicode_GET_SIZE(*operand1); Py_ssize_t new_size = operand1_size + operand2_size; if (unlikely(new_size < 0)) { PyErr_Format(PyExc_OverflowError, "strings are too large to concat"); return false; } if (unlikely(PyUnicode_Resize(operand1, new_size) != 0)) { return false; } memcpy(PyUnicode_AS_UNICODE(*operand1) + operand1_size, PyUnicode_AS_UNICODE(operand2), operand2_size * sizeof(Py_UNICODE)); return true; #else assert(!PyUnicode_CHECK_INTERNED(*operand1)); return UNICODE_APPEND(operand1, operand2); #endif } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersImportHard.c0000600000372100037210000001105014166627112030554 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperImportHard.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helper for hard import of module "__future__" import. */ PyObject *IMPORT_HARD___FUTURE__(void) { static PyObject *module___future__ = NULL; if (module___future__ == NULL) { module___future__ = PyImport_ImportModule("__future__"); } CHECK_OBJECT(module___future__); return module___future__; } /* C helper for hard import of module "_frozen_importlib" import. */ #if PYTHON_VERSION >= 0x300 PyObject *IMPORT_HARD__FROZEN_IMPORTLIB(void) { static PyObject *module__frozen_importlib = NULL; if (module__frozen_importlib == NULL) { module__frozen_importlib = PyImport_ImportModule("_frozen_importlib"); } CHECK_OBJECT(module__frozen_importlib); return module__frozen_importlib; } #endif /* C helper for hard import of module "_frozen_importlib_external" import. */ #if PYTHON_VERSION >= 0x350 PyObject *IMPORT_HARD__FROZEN_IMPORTLIB_EXTERNAL(void) { static PyObject *module__frozen_importlib_external = NULL; if (module__frozen_importlib_external == NULL) { module__frozen_importlib_external = PyImport_ImportModule("_frozen_importlib_external"); } CHECK_OBJECT(module__frozen_importlib_external); return module__frozen_importlib_external; } #endif /* C helper for hard import of module "functools" import. */ PyObject *IMPORT_HARD_FUNCTOOLS(void) { static PyObject *module_functools = NULL; if (module_functools == NULL) { module_functools = PyImport_ImportModule("functools"); } CHECK_OBJECT(module_functools); return module_functools; } /* C helper for hard import of module "importlib" import. */ PyObject *IMPORT_HARD_IMPORTLIB(void) { static PyObject *module_importlib = NULL; if (module_importlib == NULL) { module_importlib = PyImport_ImportModule("importlib"); } CHECK_OBJECT(module_importlib); return module_importlib; } /* C helper for hard import of module "os" import. */ PyObject *IMPORT_HARD_OS(void) { static PyObject *module_os = NULL; if (module_os == NULL) { module_os = PyImport_ImportModule("os"); } CHECK_OBJECT(module_os); return module_os; } /* C helper for hard import of module "pkgutil" import. */ PyObject *IMPORT_HARD_PKGUTIL(void) { static PyObject *module_pkgutil = NULL; if (module_pkgutil == NULL) { module_pkgutil = PyImport_ImportModule("pkgutil"); } CHECK_OBJECT(module_pkgutil); return module_pkgutil; } /* C helper for hard import of module "site" import. */ PyObject *IMPORT_HARD_SITE(void) { static PyObject *module_site = NULL; if (module_site == NULL) { module_site = PyImport_ImportModule("site"); } CHECK_OBJECT(module_site); return module_site; } /* C helper for hard import of module "sys" import. */ PyObject *IMPORT_HARD_SYS(void) { static PyObject *module_sys = NULL; if (module_sys == NULL) { module_sys = PyImport_ImportModule("sys"); } CHECK_OBJECT(module_sys); return module_sys; } /* C helper for hard import of module "types" import. */ PyObject *IMPORT_HARD_TYPES(void) { static PyObject *module_types = NULL; if (module_types == NULL) { module_types = PyImport_ImportModule("types"); } CHECK_OBJECT(module_types); return module_types; } /* C helper for hard import of module "typing" import. */ PyObject *IMPORT_HARD_TYPING(void) { static PyObject *module_typing = NULL; if (module_typing == NULL) { module_typing = PyImport_ImportModule("typing"); } CHECK_OBJECT(module_typing); return module_typing; } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledCellType.c0000600000372100037210000001615314166627112030367 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "nuitka/prelude.h" #include "nuitka/freelists.h" #define MAX_CELL_FREE_LIST_COUNT 1000 static struct Nuitka_CellObject *free_list_cells = NULL; static int free_list_cells_count = 0; static void Nuitka_Cell_tp_dealloc(struct Nuitka_CellObject *cell) { Nuitka_GC_UnTrack(cell); Py_XDECREF(cell->ob_ref); releaseToFreeList(free_list_cells, cell, MAX_CELL_FREE_LIST_COUNT); } #if PYTHON_VERSION < 0x300 static int Nuitka_Cell_tp_compare(struct Nuitka_CellObject *cell_a, struct Nuitka_CellObject *cell_b) { /* Empty cells compare specifically different. */ if (cell_a->ob_ref == NULL) { if (cell_b->ob_ref == NULL) { return 0; } return -1; } if (cell_b->ob_ref == NULL) { return 1; } return PyObject_Compare(cell_a->ob_ref, cell_b->ob_ref); } #else static PyObject *Nuitka_Cell_tp_richcompare(PyObject *a, PyObject *b, int op) { PyObject *result; CHECK_OBJECT(a); CHECK_OBJECT(b); if (unlikely(!Nuitka_Cell_Check(a) || !Nuitka_Cell_Check(b))) { result = Py_NotImplemented; Py_INCREF(result); return result; } /* Now just dereference, and compare from there by contents. */ a = ((struct Nuitka_CellObject *)a)->ob_ref; b = ((struct Nuitka_CellObject *)b)->ob_ref; if (a != NULL && b != NULL) { return PyObject_RichCompare(a, b, op); } int res = (b == NULL) - (a == NULL); switch (op) { case Py_EQ: result = BOOL_FROM(res == 0); break; case Py_NE: result = BOOL_FROM(res != 0); break; case Py_LE: result = BOOL_FROM(res <= 0); break; case Py_GE: result = BOOL_FROM(res >= 0); break; case Py_LT: result = BOOL_FROM(res < 0); break; case Py_GT: result = BOOL_FROM(res > 0); break; default: PyErr_BadArgument(); return NULL; } Py_INCREF(result); return result; } #endif static PyObject *Nuitka_Cell_tp_repr(struct Nuitka_CellObject *cell) { if (cell->ob_ref == NULL) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif "", cell); } else { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif "", cell, cell->ob_ref->ob_type->tp_name, cell->ob_ref); } } static int Nuitka_Cell_tp_traverse(struct Nuitka_CellObject *cell, visitproc visit, void *arg) { Py_VISIT(cell->ob_ref); return 0; } static int Nuitka_Cell_tp_clear(struct Nuitka_CellObject *cell) { Py_CLEAR(cell->ob_ref); return 0; } static PyObject *Nuitka_Cell_get_contents(struct Nuitka_CellObject *cell, void *closure) { if (cell->ob_ref == NULL) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "Cell is empty"); return NULL; } Py_INCREF(cell->ob_ref); return cell->ob_ref; } #if PYTHON_VERSION >= 0x370 static int Nuitka_Cell_set_contents(struct Nuitka_CellObject *cell, PyObject *value) { PyObject *old = cell->ob_ref; if (old != NULL && value == NULL) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cell_contents cannot be used to delete values Nuitka"); return -1; } cell->ob_ref = value; Py_XINCREF(value); Py_XDECREF(old); return 0; } #endif static PyGetSetDef Nuitka_Cell_getsetlist[] = { #if PYTHON_VERSION < 0x370 {(char *)"cell_contents", (getter)Nuitka_Cell_get_contents, NULL, NULL}, #else {(char *)"cell_contents", (getter)Nuitka_Cell_get_contents, (setter)Nuitka_Cell_set_contents, NULL}, #endif {NULL}}; PyTypeObject Nuitka_Cell_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_cell", sizeof(struct Nuitka_CellObject), 0, (destructor)Nuitka_Cell_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if PYTHON_VERSION < 0x300 (cmpfunc)Nuitka_Cell_tp_compare, /* tp_compare */ #else 0, /* tp_reserved */ #endif (reprfunc)Nuitka_Cell_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Cell_tp_traverse, /* tp_traverse */ (inquiry)Nuitka_Cell_tp_clear, /* tp_clear */ #if PYTHON_VERSION < 0x300 0, /* tp_richcompare */ #else Nuitka_Cell_tp_richcompare, /* tp_richcompare */ #endif 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ Nuitka_Cell_getsetlist, /* tp_getset */ }; void _initCompiledCellType(void) { PyType_Ready(&Nuitka_Cell_Type); } struct Nuitka_CellObject *Nuitka_Cell_Empty(void) { struct Nuitka_CellObject *result; allocateFromFreeListFixed(free_list_cells, struct Nuitka_CellObject, Nuitka_Cell_Type); result->ob_ref = NULL; Nuitka_GC_Track(result); return result; } struct Nuitka_CellObject *Nuitka_Cell_New0(PyObject *value) { CHECK_OBJECT(value); struct Nuitka_CellObject *result; allocateFromFreeListFixed(free_list_cells, struct Nuitka_CellObject, Nuitka_Cell_Type); result->ob_ref = value; Py_INCREF(value); Nuitka_GC_Track(result); return result; } struct Nuitka_CellObject *Nuitka_Cell_New1(PyObject *value) { CHECK_OBJECT(value); struct Nuitka_CellObject *result; allocateFromFreeListFixed(free_list_cells, struct Nuitka_CellObject, Nuitka_Cell_Type); result->ob_ref = value; Nuitka_GC_Track(result); return result; }Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceAdd.c0000600000372100037210000045407214166627112032367 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersOperationInplaceAddUtils.c" /* C helpers for type in-place "+" (ADD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_ADD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_ADD_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_ADD_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_ADD_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_ADD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION < 0x300 if (1 && !PyString_CHECK_INTERNED(*operand1) && 1) { return STRING_ADD_INPLACE(operand1, operand2); } #endif } #if PYTHON_VERSION < 0x300 // Python2 strings are to be treated differently, fall back to Python API here. if (1 && 1) { PyString_Concat(operand1, operand2); return !ERROR_OCCURRED(); } #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_STR_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'str'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(*operand1) && !PyString_CHECK_INTERNED(*operand1) && 1) { return STRING_ADD_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyString_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_STR_STR_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; #if PYTHON_VERSION < 0x300 exit_inplace_exception: return false; #endif } static inline bool _BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION < 0x300 if (1 && !PyString_CHECK_INTERNED(*operand1) && PyString_CheckExact(operand2)) { return STRING_ADD_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_STR_STR_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ static inline bool _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (1 && !PyUnicode_CHECK_INTERNED(*operand1) && 1) { return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'unicode'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'str'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (PyUnicode_CheckExact(*operand1) && !PyUnicode_CHECK_INTERNED(*operand1) && 1) { return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyUnicode_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; #if PYTHON_VERSION < 0x300 exit_inplace_exception: return false; #endif } static inline bool _BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (1 && !PyUnicode_CHECK_INTERNED(*operand1) && PyUnicode_CheckExact(operand2)) { return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ static inline bool _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (1 && 1) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } #endif } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'bytes'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (PyBytes_CheckExact(*operand1) && 1) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyBytes_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; #if PYTHON_VERSION < 0x300 exit_inplace_exception: return false; #endif } static inline bool _BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION >= 0x300 if (1 && PyBytes_CheckExact(operand2)) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } #endif } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyTuple_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (1 && 1) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'tuple'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyTuple_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyTuple_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; #if PYTHON_VERSION < 0x300 exit_inplace_exception: return false; #endif } static inline bool _BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyTuple_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (1 && (PyTuple_CheckExact(operand2) || PySequence_Check(operand2))) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (1 && 1) { return LIST_EXTEND_FROM_LIST(*operand1, operand2); } if (1 && 1) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_ADD_LIST_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'list'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (PyList_CheckExact(*operand1) && 1) { return LIST_EXTEND_FROM_LIST(*operand1, operand2); } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyList_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyList_Type.tp_as_sequence->sq_inplace_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } { PyObject *o = PyList_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; #if PYTHON_VERSION < 0x300 exit_inplace_exception: return false; #endif } static inline bool _BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (1 && PyList_CheckExact(operand2)) { return LIST_EXTEND_FROM_LIST(*operand1, operand2); } if (1 && PySequence_Check(operand2)) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_ADD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_ADD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_ADD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_ADD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_ADD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_ADD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); // No inplace sequence repeat slot sq_inplace_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_FLOAT_LONG_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static inline bool _BINARY_OPERATION_ADD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; } bool BINARY_OPERATION_ADD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_STR_UNICODE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_ADD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; } bool BINARY_OPERATION_ADD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_UNICODE_STR_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_ADD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(*operand1) && !PyString_CHECK_INTERNED(*operand1) && PyString_CheckExact(operand2)) { return STRING_ADD_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 if (PyUnicode_CheckExact(*operand1) && !PyUnicode_CHECK_INTERNED(*operand1) && PyUnicode_CheckExact(operand2)) { return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2); } #endif } #if PYTHON_VERSION < 0x300 // Python2 strings are to be treated differently, fall back to Python API here. if (PyString_CheckExact(*operand1) && PyString_CheckExact(operand2)) { PyString_Concat(operand1, operand2); return !ERROR_OCCURRED(); } #endif #if PYTHON_VERSION >= 0x300 // Python3 Strings are to be treated differently. if (PyUnicode_CheckExact(*operand1) && PyUnicode_CheckExact(operand2)) { PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } #endif PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; } if (sq_slot != NULL) { PyObject *result = sq_slot(*operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_ADD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_ADD_LIST_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (1 && 1) { PyObject *result = PySequence_InPlaceConcat(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_add available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_add == NULL); { assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyList_Type.tp_as_sequence->sq_inplace_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } { PyObject *o = PyList_Type.tp_as_sequence->sq_concat(*operand1, operand2); obj_result = o; goto exit_inplace_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; } bool BINARY_OPERATION_ADD_LIST_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_LIST_TUPLE_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersHeapStorage.c0000600000372100037210000000335614166627112030717 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For making "yield" and "yield from" capable of persisting current C stack. * * These copy objects pointed to into an array foreseen for this task. * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif void Nuitka_PreserveHeap(void *dest, ...) { va_list(ap); va_start(ap, dest); char *w = (char *)dest; for (;;) { void *source = va_arg(ap, void *); if (source == NULL) { break; } size_t size = va_arg(ap, size_t); memcpy(w, source, size); w += size; } } void Nuitka_RestoreHeap(void *source, ...) { va_list(ap); va_start(ap, source); char *w = (char *)source; for (;;) { void *dest = va_arg(ap, void *); if (dest == NULL) { break; } size_t size = va_arg(ap, size_t); memcpy(dest, w, size); w += size; } } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonGt.c0000600000372100037210000156317514166627112031135 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">" (GT) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_GT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a > b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_GT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a > b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_GT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a > b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GT_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_GT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GT_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_GT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GT_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_GT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GT_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_GT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_GT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_GT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GT); CHECK_OBJECT(r); return r; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GT_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_GT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GT); CHECK_OBJECT(r); // Convert to target type if necessary bool result = r == Py_True; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GT_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_GT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GT); CHECK_OBJECT(r); // Convert to target type if necessary nuitka_bool result = r == Py_True ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_GT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_GT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_GT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_GT_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_GT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_GT_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_GT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c > 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_GT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_GT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_GT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_GT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GT_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GT_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GT_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_GT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_GT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_GT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_GT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_GT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GT_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GT_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GT_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() > %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a > b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_GT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_GT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a > b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_GT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_GT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a > b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GT_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GT_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GT_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_GT_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_GT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_GT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_GT_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_GT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_GT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_GT_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GT_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GT_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GT_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_GT_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_GT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_GT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_GT_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_GT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_GT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a > len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_GT_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GT_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GT_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_GT_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GT_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GT_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() > list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GT_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GT_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GT_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GT_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GT_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GT) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LT); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GT) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() > %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryOlddiv.c0000600000372100037210000036525614166627112032776 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "/" (OLDDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_LONG_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_OBJECT(operand1, operand2); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceBitand.c0000600000372100037210000015450214166627112033073 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "&" (BITAND) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_and : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_and available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_and == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITAND_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_BITAND_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_and : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_and available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_and == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITAND_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_and available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_and == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITAND_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITAND_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_and available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_and == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITAND_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_LONG_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static inline bool _BINARY_OPERATION_BITAND_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITAND_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_SET_SET_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_and : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'set'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = PySet_Type.tp_as_number->nb_inplace_and; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = PySet_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'set' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITAND_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_and(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_BITAND_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_and : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITAND_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledGeneratorTypeUncompiledIntegration.c0000600000372100037210000006007514166627112035664 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Uncompiled generator integration * * This is for use in compiled generator, coroutine, async types. The file in * included for compiled generator, and in part exports functions as necessary. * */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif // This function takes no reference to value, and publishes a StopIteration // exception with it. #if PYTHON_VERSION >= 0x300 static void Nuitka_SetStopIterationValue(PyObject *value) { CHECK_OBJECT(value); #if PYTHON_VERSION <= 0x352 PyObject *stop_value = CALL_FUNCTION_WITH_SINGLE_ARG(PyExc_StopIteration, value); if (unlikely(stop_value == NULL)) { return; } Py_INCREF(PyExc_StopIteration); RESTORE_ERROR_OCCURRED(PyExc_StopIteration, stop_value, NULL); #else if (likely(!PyTuple_Check(value) && !PyExceptionInstance_Check(value))) { Py_INCREF(PyExc_StopIteration); Py_INCREF(value); RESTORE_ERROR_OCCURRED(PyExc_StopIteration, value, NULL); } else { PyObject *stop_value = CALL_FUNCTION_WITH_SINGLE_ARG(PyExc_StopIteration, value); if (unlikely(stop_value == NULL)) { return; } Py_INCREF(PyExc_StopIteration); RESTORE_ERROR_OCCURRED(PyExc_StopIteration, stop_value, NULL); } #endif } #endif #if PYTHON_VERSION >= 0x370 static inline void Nuitka_PyGen_exc_state_clear(_PyErr_StackItem *exc_state) { PyObject *t = exc_state->exc_type; PyObject *v = exc_state->exc_value; PyObject *tb = exc_state->exc_traceback; exc_state->exc_type = NULL; exc_state->exc_value = NULL; exc_state->exc_traceback = NULL; Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); } #endif #if PYTHON_VERSION >= 0x300 static inline bool Nuitka_PyFrameHasCompleted(PyFrameObject *const frame) { #if PYTHON_VERSION < 0x3a0 return frame->f_stacktop == NULL; #else return frame->f_state > FRAME_EXECUTING; #endif } static inline bool Nuitka_PyGeneratorIsExecuting(PyGenObject const *gen) { #if PYTHON_VERSION < 0x3a0 return gen->gi_running == 1; #else PyFrameObject *frame = gen->gi_frame; return frame->f_state == FRAME_EXECUTING; #endif } // This is for CPython iterator objects, the respective code is not exported as // API, so we need to redo it. This is an re-implementation that closely follows // what it does. It's unrelated to compiled generators, and used from coroutines // and asyncgen to interact with them. static PyObject *Nuitka_PyGen_Send(PyGenObject *gen, PyObject *arg) { #if PYTHON_VERSION >= 0x3a0 PyObject *result; PySendResult res = PyIter_Send((PyObject *)gen, arg, &result); switch (res) { case PYGEN_RETURN: if (result == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } else { if (result != Py_None) { Nuitka_SetStopIterationValue(result); } Py_DECREF(result); } return NULL; case PYGEN_NEXT: return result; case PYGEN_ERROR: return NULL; default: NUITKA_CANNOT_GET_HERE("invalid PYGEN_ result"); } #else PyFrameObject *f = gen->gi_frame; #if PYTHON_VERSION >= 0x3a0 if (f != NULL && _PyFrame_IsExecuting(f)) { #else if (unlikely(gen->gi_running)) { #endif SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "generator already executing"); return NULL; } if (f == NULL || Nuitka_PyFrameHasCompleted(f)) { // Set exception if called from send() if (arg != NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } return NULL; } #if PYTHON_VERSION < 0x3a0 if (f->f_lasti == -1) { if (unlikely(arg && arg != Py_None)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't send non-None value to a just-started generator"); return NULL; } } else { // Put arg on top of the value stack PyObject *tmp = arg ? arg : Py_None; Py_INCREF(tmp); *(f->f_stacktop++) = tmp; } #else // CPython assertions, check them assert(_PyFrame_IsRunnable(f)); assert(f->f_lasti >= 0 || ((unsigned char *)PyBytes_AS_STRING(f->f_code->co_code))[0] == 129); PyObject *gen_result = arg ? arg : Py_None; Py_INCREF(gen_result); gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth] = gen_result; gen->gi_frame->f_stackdepth++; #endif // Generators always return to their most recent caller, not necessarily // their creator. PyThreadState *tstate = PyThreadState_GET(); Py_XINCREF(tstate->frame); f->f_back = tstate->frame; #if PYTHON_VERSION < 0x3a0 gen->gi_running = 1; #endif #if PYTHON_VERSION >= 0x370 gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; #endif #if PYTHON_VERSION < 0x390 PyObject *result = PyEval_EvalFrameEx(f, 0); #else PyObject *result = _PyEval_EvalFrame(tstate, f, 0); #endif #if PYTHON_VERSION >= 0x370 tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; #endif #if PYTHON_VERSION < 0x3a0 gen->gi_running = 0; #endif // Don't keep the reference to f_back any longer than necessary. It // may keep a chain of frames alive or it could create a reference // cycle. Py_CLEAR(f->f_back); // If the generator just returned (as opposed to yielding), signal that the // generator is exhausted. #if PYTHON_VERSION < 0x3a0 if (result && f->f_stacktop == NULL) { if (result == Py_None) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } else { PyObject *e = PyObject_CallFunctionObjArgs(PyExc_StopIteration, result, NULL); if (e != NULL) { SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyExc_StopIteration, e); } } Py_CLEAR(result); } if (result == NULL || f->f_stacktop == NULL) { #if PYTHON_VERSION < 0x370 // Generator is finished, remove exception from frame before releasing // it. PyObject *type = f->f_exc_type; PyObject *value = f->f_exc_value; PyObject *traceback = f->f_exc_traceback; f->f_exc_type = NULL; f->f_exc_value = NULL; f->f_exc_traceback = NULL; Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); #else Nuitka_PyGen_exc_state_clear(&gen->gi_exc_state); #endif // Now release frame. #if PYTHON_VERSION >= 0x340 gen->gi_frame->f_gen = NULL; #endif gen->gi_frame = NULL; Py_DECREF(f); } #else if (result) { if (!_PyFrameHasCompleted(f)) { return result; } assert(result == Py_None || !PyAsyncGen_CheckExact(gen)); if (result == Py_None && !PyAsyncGen_CheckExact(gen)) { Py_DECREF(result); result = NULL; } } else { if (PyErr_ExceptionMatches(PyExc_StopIteration)) { const char *msg = "generator raised StopIteration"; if (PyCoro_CheckExact(gen)) { msg = "coroutine raised StopIteration"; } else if (PyAsyncGen_CheckExact(gen)) { msg = "async generator raised StopIteration"; } _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg); } else if (PyAsyncGen_CheckExact(gen) && PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) { /* code in `gen` raised a StopAsyncIteration error: raise a RuntimeError. */ const char *msg = "async generator raised StopAsyncIteration"; _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg); } result = NULL; } /* generator can't be rerun, so release the frame */ /* first clean reference cycle through stored exception traceback */ Nuitka_PyGen_exc_state_clear(&gen->gi_exc_state); gen->gi_frame->f_gen = NULL; gen->gi_frame = NULL; Py_DECREF(f); #endif return result; #endif } #endif #if PYTHON_VERSION >= 0x340 #include // Not done for earlier versions yet, indicate usability for compiled generators. #define NUITKA_UNCOMPILED_THROW_INTEGRATION 1 static PyObject *Nuitka_PyGen_gen_close(PyGenObject *gen, PyObject *args); static PyObject *Nuitka_PyGen_yf(PyGenObject *gen) { PyFrameObject *f = gen->gi_frame; #if PYTHON_VERSION < 0x3a0 if (f && f->f_stacktop) { #else if (f) { #endif PyObject *bytecode = f->f_code->co_code; unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); if (f->f_lasti < 0) { return NULL; } #if PYTHON_VERSION < 0x360 if (code[f->f_lasti + 1] != YIELD_FROM) #elif PYTHON_VERSION < 0x3a0 if (code[f->f_lasti + sizeof(_Py_CODEUNIT)] != YIELD_FROM) #else if (code[(f->f_lasti + 1) * sizeof(_Py_CODEUNIT)] != YIELD_FROM) #endif { return NULL; } #if PYTHON_VERSION < 0x3a0 PyObject *yf = f->f_stacktop[-1]; #else assert(f->f_stackdepth > 0); PyObject *yf = f->f_valuestack[f->f_stackdepth - 1]; #endif Py_INCREF(yf); return yf; } else { return NULL; } } static PyObject *Nuitka_PyGen_gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *f = gen->gi_frame; PyObject *result; #if PYTHON_VERSION >= 0x3a0 if (f != NULL && unlikely(_PyFrame_IsExecuting(f))) { #else if (unlikely(gen->gi_running)) { #endif char const *msg = "generator already executing"; #if PYTHON_VERSION >= 0x350 if (PyCoro_CheckExact(gen)) { msg = "coroutine already executing"; } #if PYTHON_VERSION >= 0x360 else if (PyAsyncGen_CheckExact(gen)) { msg = "async generator already executing"; } #endif #endif SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, msg); return NULL; } if (f == NULL || Nuitka_PyFrameHasCompleted(f)) { #if PYTHON_VERSION >= 0x350 if (PyCoro_CheckExact(gen) && !closing) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cannot reuse already awaited coroutine"); } else #endif if (arg && !exc) { #if PYTHON_VERSION >= 0x360 if (PyAsyncGen_CheckExact(gen)) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); } else #endif { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } return NULL; } #if PYTHON_VERSION < 0x3a0 if (f->f_lasti == -1) { if (unlikely(arg != NULL && arg != Py_None)) { char const *msg = "can't send non-None value to a just-started generator"; #if PYTHON_VERSION >= 0x350 if (PyCoro_CheckExact(gen)) { msg = "can't send non-None value to a just-started coroutine"; } #if PYTHON_VERSION >= 0x360 else if (PyAsyncGen_CheckExact(gen)) { msg = "can't send non-None value to a just-started async generator"; } #endif #endif SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, msg); return NULL; } } else { result = arg ? arg : Py_None; Py_INCREF(result); *(f->f_stacktop++) = result; } #else // CPython assertions, check them assert(_PyFrame_IsRunnable(f)); assert(f->f_lasti >= 0 || ((unsigned char *)PyBytes_AS_STRING(f->f_code->co_code))[0] == GEN_START); result = arg ? arg : Py_None; Py_INCREF(result); gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth] = result; gen->gi_frame->f_stackdepth++; #endif Py_XINCREF(tstate->frame); f->f_back = tstate->frame; #if PYTHON_VERSION < 0x3a0 gen->gi_running = 1; #endif #if PYTHON_VERSION >= 0x370 gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; #endif #if PYTHON_VERSION < 0x390 result = PyEval_EvalFrameEx(f, exc); #else result = _PyEval_EvalFrame(tstate, f, exc); #endif #if PYTHON_VERSION >= 0x370 tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; #endif #if PYTHON_VERSION < 0x3a0 gen->gi_running = 0; #endif Py_CLEAR(f->f_back); #if PYTHON_VERSION < 0x3a0 if (result && f->f_stacktop == NULL) { if (result == Py_None) { #if PYTHON_VERSION >= 0x360 if (PyAsyncGen_CheckExact(gen)) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); } else #endif { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } else { Nuitka_SetStopIterationValue(result); } Py_CLEAR(result); } #if PYTHON_VERSION >= 0x350 else if (result == NULL && PyErr_ExceptionMatches(PyExc_StopIteration)) { #if PYTHON_VERSION < 0x370 const int check_stop_iter_error_flags = CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | #if PYTHON_VERSION >= 0x360 CO_ASYNC_GENERATOR | #endif CO_ITERABLE_COROUTINE; if (unlikely(gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags & check_stop_iter_error_flags)) #endif { char const *msg = "generator raised StopIteration"; if (PyCoro_CheckExact(gen)) { msg = "coroutine raised StopIteration"; } #if PYTHON_VERSION >= 0x360 else if (PyAsyncGen_CheckExact(gen)) { msg = "async generator raised StopIteration"; } #endif #if PYTHON_VERSION >= 0x360 _PyErr_FormatFromCause( #else PyErr_Format( #endif PyExc_RuntimeError, "%s", msg); } } #endif #if PYTHON_VERSION >= 0x360 else if (result == NULL && PyAsyncGen_CheckExact(gen) && PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) { char const *msg = "async generator raised StopAsyncIteration"; _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg); } #endif if (!result || f->f_stacktop == NULL) { #if PYTHON_VERSION < 0x370 PyObject *t, *v, *tb; t = f->f_exc_type; v = f->f_exc_value; tb = f->f_exc_traceback; f->f_exc_type = NULL; f->f_exc_value = NULL; f->f_exc_traceback = NULL; Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); #else Nuitka_PyGen_exc_state_clear(&gen->gi_exc_state); #endif gen->gi_frame->f_gen = NULL; gen->gi_frame = NULL; Py_DECREF(f); } #else if (result) { if (!_PyFrameHasCompleted(f)) { return result; } assert(result == Py_None || !PyAsyncGen_CheckExact(gen)); if (result == Py_None && !PyAsyncGen_CheckExact(gen) && !arg) { /* Return NULL if called by gen_iternext() */ Py_CLEAR(result); } } else { if (PyErr_ExceptionMatches(PyExc_StopIteration)) { const char *msg = "generator raised StopIteration"; if (PyCoro_CheckExact(gen)) { msg = "coroutine raised StopIteration"; } else if (PyAsyncGen_CheckExact(gen)) { msg = "async generator raised StopIteration"; } _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg); } else if (PyAsyncGen_CheckExact(gen) && PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) { /* code in `gen` raised a StopAsyncIteration error: raise a RuntimeError. */ const char *msg = "async generator raised StopAsyncIteration"; _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg); } } /* generator can't be rerun, so release the frame */ /* first clean reference cycle through stored exception traceback */ Nuitka_PyGen_exc_state_clear(&gen->gi_exc_state); gen->gi_frame->f_gen = NULL; gen->gi_frame = NULL; Py_DECREF(f); #endif return result; } static int Nuitka_PyGen_gen_close_iter(PyObject *yf) { PyObject *retval = NULL; if (PyGen_CheckExact(yf) #if PYTHON_VERSION >= 0x350 || PyCoro_CheckExact(yf) #endif ) { retval = Nuitka_PyGen_gen_close((PyGenObject *)yf, NULL); if (retval == NULL) { return -1; } } else { PyObject *meth = PyObject_GetAttr(yf, const_str_plain_close); if (meth == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_WriteUnraisable(yf); } CLEAR_ERROR_OCCURRED(); } else { retval = CALL_FUNCTION_NO_ARGS(meth); Py_DECREF(meth); if (retval == NULL) { return -1; } } } Py_XDECREF(retval); return 0; } static PyObject *Nuitka_PyGen_gen_close(PyGenObject *gen, PyObject *args) { PyObject *yf = Nuitka_PyGen_yf(gen); int err = 0; if (yf != NULL) { #if PYTHON_VERSION >= 0x3a0 PyFrameState state = gen->gi_frame->f_state; gen->gi_frame->f_state = FRAME_EXECUTING; #else gen->gi_running = 1; #endif err = Nuitka_PyGen_gen_close_iter(yf); #if PYTHON_VERSION >= 0x3a0 gen->gi_frame->f_state = state; #else gen->gi_running = 0; #endif Py_DECREF(yf); } if (err == 0) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_GeneratorExit); } PyObject *retval = Nuitka_PyGen_gen_send_ex(gen, Py_None, 1, 1); if (retval != NULL) { char const *msg = "generator ignored GeneratorExit"; #if PYTHON_VERSION >= 0x350 if (PyCoro_CheckExact(gen)) { msg = "coroutine ignored GeneratorExit"; } #if PYTHON_VERSION >= 0x360 else if (PyAsyncGen_CheckExact(gen)) { msg = "async generator ignored GeneratorExit"; } #endif #endif Py_DECREF(retval); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, msg); return NULL; } if (PyErr_ExceptionMatches(PyExc_StopIteration) || PyErr_ExceptionMatches(PyExc_GeneratorExit)) { CLEAR_ERROR_OCCURRED(); Py_INCREF(Py_None); return Py_None; } return NULL; } static bool _Nuitka_Generator_check_throw2(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); // This function is called when throwing to an uncompiled generator. Coroutines and generators // do this in their yielding from. // Note: // Exception arguments are passed for ownership and must be released before returning. The // value of exception_type will not be NULL, but the actual exception will not necessarily // be normalized. static PyObject *Nuitka_UncompiledGenerator_throw(PyGenObject *gen, int close_on_genexit, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_UncompiledGenerator_throw: Enter "); PRINT_ITEM((PyObject *)gen); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif PyObject *yf = Nuitka_PyGen_yf(gen); if (yf != NULL) { if (close_on_genexit && EXCEPTION_MATCH_BOOL_SINGLE(exception_type, PyExc_GeneratorExit)) { #if PYTHON_VERSION < 0x3a0 gen->gi_running = 1; #else PyFrameState state = gen->gi_frame->f_state; gen->gi_frame->f_state = FRAME_EXECUTING; #endif int err = Nuitka_PyGen_gen_close_iter(yf); #if PYTHON_VERSION < 0x3a0 gen->gi_running = 0; #else gen->gi_frame->f_state = state; #endif Py_DECREF(yf); if (err < 0) { // Releasing exception, we are done with it, raising instead the error just // occurred. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return Nuitka_PyGen_gen_send_ex(gen, Py_None, 1, 0); } // Handing exception ownership to this code. goto throw_here; } PyObject *ret; if (PyGen_CheckExact(yf) #if PYTHON_VERSION >= 0x350 || PyCoro_CheckExact(yf) #endif ) { #if PYTHON_VERSION < 0x3a0 gen->gi_running = 1; #else PyFrameState state = gen->gi_frame->f_state; gen->gi_frame->f_state = FRAME_EXECUTING; #endif // Handing exception ownership to "Nuitka_UncompiledGenerator_throw". ret = Nuitka_UncompiledGenerator_throw((PyGenObject *)yf, close_on_genexit, exception_type, exception_value, exception_tb); #if PYTHON_VERSION < 0x3a0 gen->gi_running = 0; #else gen->gi_frame->f_state = state; #endif } else { #if 0 // TODO: Add slow mode traces. PRINT_ITEM(yf); PRINT_NEW_LINE(); #endif PyObject *meth = PyObject_GetAttr(yf, const_str_plain_throw); if (meth == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { Py_DECREF(yf); // Releasing exception, we are done with it. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } CLEAR_ERROR_OCCURRED(); Py_DECREF(yf); // Handing exception ownership to this code. goto throw_here; } #if PYTHON_VERSION < 0x3a0 gen->gi_running = 1; #else PyFrameState state = gen->gi_frame->f_state; gen->gi_frame->f_state = FRAME_EXECUTING; #endif ret = PyObject_CallFunctionObjArgs(meth, exception_type, exception_value, exception_tb, NULL); #if PYTHON_VERSION < 0x3a0 gen->gi_running = 0; #else gen->gi_frame->f_state = state; #endif // Releasing exception, we are done with it. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); Py_DECREF(meth); } Py_DECREF(yf); if (ret == NULL) { #if PYTHON_VERSION < 0x3a0 ret = *(--gen->gi_frame->f_stacktop); #else assert(gen->gi_frame->f_stackdepth > 0); gen->gi_frame->f_stackdepth--; ret = gen->gi_frame->f_valuestack[gen->gi_frame->f_stackdepth]; #endif Py_DECREF(ret); #if PYTHON_VERSION >= 0x360 gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT); #else gen->gi_frame->f_lasti += 1; #endif if (_PyGen_FetchStopIterationValue(&exception_value) == 0) { ret = Nuitka_PyGen_gen_send_ex(gen, exception_value, 0, 0); Py_DECREF(exception_value); } else { ret = Nuitka_PyGen_gen_send_ex(gen, Py_None, 1, 0); } } return ret; } throw_here: // We continue to have exception ownership here. if (unlikely(_Nuitka_Generator_check_throw2(&exception_type, &exception_value, &exception_tb) == false)) { // Exception was released by _Nuitka_Generator_check_throw2 already. return NULL; } // Transfer exception ownership to published exception. RESTORE_ERROR_OCCURRED(exception_type, exception_value, (PyTracebackObject *)exception_tb); return Nuitka_PyGen_gen_send_ex(gen, Py_None, 1, 1); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersAttributes.c0000600000372100037210000007234314166627112030645 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #if PYTHON_VERSION < 0x300 PyObject *FIND_ATTRIBUTE_IN_CLASS(PyClassObject *klass, PyObject *attr_name) { CHECK_OBJECT(klass); CHECK_OBJECT(attr_name); assert(PyClass_Check(klass)); assert(PyString_CheckExact(attr_name)); PyObject *result = GET_STRING_DICT_VALUE((PyDictObject *)klass->cl_dict, (PyStringObject *)attr_name); if (result == NULL) { assert(PyTuple_Check(klass->cl_bases)); Py_ssize_t base_count = PyTuple_GET_SIZE(klass->cl_bases); for (Py_ssize_t i = 0; i < base_count; i++) { result = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)PyTuple_GET_ITEM(klass->cl_bases, i), attr_name); if (result != NULL) { break; } } } return result; } #endif #if PYTHON_VERSION < 0x300 static PyObject *LOOKUP_INSTANCE(PyObject *source, PyObject *attr_name) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); assert(PyInstance_Check(source)); assert(PyString_CheckExact(attr_name)); PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *result = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); if (result) { Py_INCREF(result); return result; } // Next see if a class has it result = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); if (result != NULL) { descrgetfunc func = Py_TYPE(result)->tp_descr_get; if (func) { result = func(result, source, (PyObject *)source_instance->in_class); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else { Py_INCREF(result); return result; } } // Finally allow a __getattr__ to handle it or else it's an error. if (unlikely(source_instance->in_class->cl_getattr == NULL)) { PyErr_Format(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { PyObject *args[] = {source, attr_name}; return CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args); } } #endif PyObject *LOOKUP_ATTRIBUTE(PyObject *source, PyObject *attr_name) { /* Note: There are 2 specializations of this function, that need to be * updated in line with this: LOOKUP_ATTRIBUTE_[DICT|CLASS]_SLOT */ CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); // TODO: If this is an exact dict, we don't have to hold a reference, is it? Py_INCREF(dict); PyObject *result = DICT_GET_ITEM1(dict, attr_name); Py_DECREF(dict); if (result != NULL) { Py_XDECREF(descr); CHECK_OBJECT(result); return result; } } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT_X(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyObject *result = LOOKUP_INSTANCE(source, attr_name); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, attr_name); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *LOOKUP_ATTRIBUTE_DICT_SLOT(PyObject *source) { CHECK_OBJECT(source); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, const_str_plain___dict__); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = DICT_GET_ITEM1(dict, const_str_plain___dict__); if (result != NULL) { Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT_X(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__dict__'", type->tp_name); return NULL; } #if PYTHON_VERSION < 0x300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyInstanceObject *source_instance = (PyInstanceObject *)source; PyObject *result = source_instance->in_dict; Py_INCREF(result); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, const_str_plain___dict__); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)"__dict__"); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__dict__'", type->tp_name); return NULL; } } PyObject *LOOKUP_ATTRIBUTE_CLASS_SLOT(PyObject *source) { CHECK_OBJECT(source); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, const_str_plain___class__); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = DICT_GET_ITEM1(dict, const_str_plain___class__); if (result != NULL) { Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT_X(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } #if PYTHON_VERSION < 0x300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyInstanceObject *source_instance = (PyInstanceObject *)source; PyObject *result = (PyObject *)source_instance->in_class; Py_INCREF(result); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, const_str_plain___class__); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)"__class__"); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } } int BUILTIN_HASATTR_BOOL(PyObject *source, PyObject *attr_name) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); #if PYTHON_VERSION < 0x300 if (PyUnicode_Check(attr_name)) { attr_name = _PyUnicode_AsDefaultEncodedString(attr_name, NULL); if (unlikely(attr_name == NULL)) { return -1; } } if (unlikely(!PyString_Check(attr_name))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "hasattr(): attribute name must be string"); return -1; } #else if (unlikely(!PyUnicode_Check(attr_name))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "hasattr(): attribute name must be string"); return -1; } #endif // TODO: This should use what LOOKUP_ATTRIBUTE does and know that the result value is going to // be unused, having an easier time generally, e.g. not having to create the error in the first // place. PyObject *value = PyObject_GetAttr(source, attr_name); if (value == NULL) { bool had_attribute_error = CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED(); if (had_attribute_error) { return 0; } else { return -1; } } Py_DECREF(value); return 1; } bool HAS_ATTR_BOOL(PyObject *source, PyObject *attr_name) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { DROP_ERROR_OCCURRED(); return false; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (result) { CHECK_OBJECT(result); Py_DECREF(result); return true; } DROP_ERROR_OCCURRED(); } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); // TODO: If this is an exact dict, we don't have to hold a reference, is it? Py_INCREF(dict); PyObject *result = DICT_GET_ITEM1(dict, attr_name); Py_DECREF(dict); if (result != NULL) { Py_XDECREF(descr); CHECK_OBJECT(result); Py_DECREF(result); return true; } } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (result != NULL) { CHECK_OBJECT(result); Py_DECREF(result); return true; } DROP_ERROR_OCCURRED(); } if (descr != NULL) { CHECK_OBJECT(descr); Py_DECREF(descr); return true; } return false; } #if PYTHON_VERSION < 0x300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyObject *result = LOOKUP_INSTANCE(source, attr_name); if (result == NULL) { DROP_ERROR_OCCURRED(); return false; } CHECK_OBJECT(result); Py_DECREF(result); return true; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, attr_name); if (result == NULL) { DROP_ERROR_OCCURRED(); return false; } CHECK_OBJECT(result); Py_DECREF(result); return true; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (result == NULL) { DROP_ERROR_OCCURRED(); return false; } CHECK_OBJECT(result); Py_DECREF(result); return true; } else { return false; } } #if PYTHON_VERSION < 0x300 extern PyObject *CALL_FUNCTION_WITH_ARGS3(PyObject *called, PyObject *const *args); static bool SET_INSTANCE(PyObject *target, PyObject *attr_name, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(attr_name); CHECK_OBJECT(value); assert(PyInstance_Check(target)); assert(PyString_Check(attr_name)); PyInstanceObject *target_instance = (PyInstanceObject *)target; // The special cases should get their own SET_ATTRIBUTE_xxxx_SLOT variants // on the code generation level as SET_ATTRIBUTE is called with constants // only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); if (target_instance->in_class->cl_setattr != NULL) { PyObject *args[] = {target, attr_name, value}; PyObject *result = CALL_FUNCTION_WITH_ARGS3(target_instance->in_class->cl_setattr, args); if (unlikely(result == NULL)) { return false; } Py_DECREF(result); return true; } else { int status = PyDict_SetItem(target_instance->in_dict, attr_name, value); if (unlikely(status != 0)) { return false; } return true; } } #endif #if PYTHON_VERSION < 0x300 || defined(_NUITKA_USE_UNEXPOSED_API) // Classes in Pyhon3 might share keys. #define CACHED_KEYS(type) (((PyHeapTypeObject *)type)->ht_cached_keys) static bool SET_ATTRIBUTE_GENERIC(PyTypeObject *type, PyObject *target, PyObject *attr_name, PyObject *value) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { descrsetfunc func = Py_TYPE(descr)->tp_descr_set; if (func != NULL && PyDescr_IsData(descr)) { int res = func(descr, target, value); Py_DECREF(descr); return res == 0; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)target)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)target + dictoffset); #if PYTHON_VERSION >= 0x300 if ((type->tp_flags & Py_TPFLAGS_HEAPTYPE) && (CACHED_KEYS(type) != NULL)) { int res = _PyObjectDict_SetItem(type, dictptr, attr_name, value); // TODO: Not possible for set, is it? if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, attr_name); return false; } return res >= 0; } else #endif { dict = *dictptr; if (dict == NULL) { dict = PyDict_New(); *dictptr = dict; } } } if (dict != NULL) { CHECK_OBJECT(dict); // TODO: If this is an exact dict, we don't have to hold a reference, is it? Py_INCREF(dict); int res = PyDict_SetItem(dict, attr_name, value); Py_DECREF(dict); Py_XDECREF(descr); return res == 0; } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #endif bool SET_ATTRIBUTE(PyObject *target, PyObject *attr_name, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(attr_name); CHECK_OBJECT(value); PyTypeObject *type = Py_TYPE(target); #if PYTHON_VERSION < 0x300 || defined(_NUITKA_USE_UNEXPOSED_API) if (type->tp_setattro == PyObject_GenericSetAttr) { return SET_ATTRIBUTE_GENERIC(type, target, attr_name, value); } #endif #if PYTHON_VERSION < 0x300 if (type->tp_setattro == PyInstance_Type.tp_setattro) { return SET_INSTANCE(target, attr_name, value); } #endif if (type->tp_setattro != NULL) { int status = (*type->tp_setattro)(target, attr_name, value); if (unlikely(status == -1)) { return false; } return true; } if (type->tp_setattr != NULL) { int status = (*type->tp_setattr)(target, (char *)Nuitka_String_AsString_Unchecked(attr_name), value); if (unlikely(status == -1)) { return false; } return true; } if (type->tp_getattr == NULL && type->tp_getattro == NULL) { PyErr_Format(PyExc_TypeError, "'%s' object has no attributes (assign to %s)", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return false; } else { PyErr_Format(PyExc_TypeError, "'%s' object has only read-only attributes (assign to %s)", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return false; } } bool SET_ATTRIBUTE_DICT_SLOT(PyObject *target, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(value); #if PYTHON_VERSION < 0x300 if (likely(PyInstance_Check(target))) { PyInstanceObject *target_instance = (PyInstanceObject *)target; /* Note seems this doesn't have to be an exact dictionary. */ if (unlikely(!PyDict_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__dict__ must be set to a dictionary"); return false; } PyObject *old = target_instance->in_dict; Py_INCREF(value); target_instance->in_dict = value; Py_DECREF(old); } else #endif { PyTypeObject *type = Py_TYPE(target); if (type->tp_setattro != NULL) { int status = (*type->tp_setattro)(target, const_str_plain___dict__, value); if (unlikely(status == -1)) { return false; } } else if (type->tp_setattr != NULL) { int status = (*type->tp_setattr)(target, (char *)"__dict__", value); if (unlikely(status == -1)) { return false; } } else if (type->tp_getattr == NULL && type->tp_getattro == NULL) { PyErr_Format(PyExc_TypeError, "'%s' object has no attributes (assign to __dict__)", type->tp_name); return false; } else { PyErr_Format(PyExc_TypeError, "'%s' object has only read-only attributes (assign to __dict__)", type->tp_name); return false; } } return true; } bool SET_ATTRIBUTE_CLASS_SLOT(PyObject *target, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(value); #if PYTHON_VERSION < 0x300 if (likely(PyInstance_Check(target))) { PyInstanceObject *target_instance = (PyInstanceObject *)target; if (unlikely(!PyClass_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__class__ must be set to a class"); return false; } PyObject *old = (PyObject *)(target_instance->in_class); Py_INCREF(value); target_instance->in_class = (PyClassObject *)value; Py_DECREF(old); } else #endif { PyTypeObject *type = Py_TYPE(target); if (type->tp_setattro != NULL) { int status = (*type->tp_setattro)(target, const_str_plain___class__, value); if (unlikely(status == -1)) { return false; } } else if (type->tp_setattr != NULL) { int status = (*type->tp_setattr)(target, (char *)"__class__", value); if (unlikely(status == -1)) { return false; } } else if (type->tp_getattr == NULL && type->tp_getattro == NULL) { PyErr_Format(PyExc_TypeError, "'%s' object has no attributes (assign to __class__)", type->tp_name); return false; } else { PyErr_Format(PyExc_TypeError, "'%s' object has only read-only attributes (assign to __class__)", type->tp_name); return false; } } return true; } PyObject *LOOKUP_SPECIAL(PyObject *source, PyObject *attr_name) { #if PYTHON_VERSION < 0x300 if (PyInstance_Check(source)) { return LOOKUP_INSTANCE(source, attr_name); } #endif // TODO: There is heavy optimization in CPython to avoid it. Potentially // that's worth it to imitate that. PyObject *result = Nuitka_TypeLookup(Py_TYPE(source), attr_name); if (likely(result)) { descrgetfunc func = Py_TYPE(result)->tp_descr_get; if (func == NULL) { Py_INCREF(result); return result; } else { PyObject *func_result = func(result, source, (PyObject *)(Py_TYPE(source))); if (unlikely(func_result == NULL)) { return NULL; } CHECK_OBJECT(func_result); return func_result; } } SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, attr_name); return NULL; } PyObject *LOOKUP_MODULE_VALUE(PyDictObject *module_dict, PyObject *var_name) { PyObject *result = GET_STRING_DICT_VALUE(module_dict, (Nuitka_StringObject *)var_name); if (unlikely(result == NULL)) { result = GET_STRING_DICT_VALUE(dict_builtin, (Nuitka_StringObject *)var_name); } return result; } PyObject *GET_MODULE_VARIABLE_VALUE_FALLBACK(PyObject *variable_name) { PyObject *result = GET_STRING_DICT_VALUE(dict_builtin, (Nuitka_StringObject *)variable_name); if (unlikely(result == NULL)) { PyObject *exception_type; PyObject *exception_value; // TODO: Do this in one go, once FORMAT_NAME_ERROR becomes unused in code generation. FORMAT_NAME_ERROR(&exception_type, &exception_value, variable_name); #if PYTHON_VERSION >= 0x300 // TODO: FORMAT_NAME_ERROR for Python3 should already produce this normalized and chained. NORMALIZE_EXCEPTION(&exception_type, &exception_value, NULL); CHAIN_EXCEPTION(exception_value); #endif RESTORE_ERROR_OCCURRED(exception_type, exception_value, NULL); } return result; } #if PYTHON_VERSION < 0x340 PyObject *GET_MODULE_VARIABLE_VALUE_FALLBACK_IN_FUNCTION(PyObject *variable_name) { PyObject *result = GET_STRING_DICT_VALUE(dict_builtin, (Nuitka_StringObject *)variable_name); if (unlikely(result == NULL)) { PyObject *exception_type; PyObject *exception_value; FORMAT_GLOBAL_NAME_ERROR(&exception_type, &exception_value, variable_name); RESTORE_ERROR_OCCURRED(exception_type, exception_value, NULL); } return result; } #endifNuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryFloordiv.c0000600000372100037210000037326514166627112033340 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "//" (FLOORDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledMethodType.c0000600000372100037210000005226114166627112030730 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Compiled methods. * * It strives to be full replacement for normal method objects, but * normally should be avoided to exist in Nuitka calls. * */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/freelists.h" #include "nuitka/prelude.h" #endif static PyObject *Nuitka_Method_get__doc__(struct Nuitka_MethodObject *method, void *closure) { PyObject *result = method->m_function->m_doc; if (result == NULL) { result = Py_None; } Py_INCREF(result); return result; } static PyGetSetDef Nuitka_Method_getsets[] = {{(char *)"__doc__", (getter)Nuitka_Method_get__doc__, NULL, NULL}, {NULL}}; #define OFF(x) offsetof(struct Nuitka_MethodObject, x) static PyMemberDef Nuitka_Method_members[] = { {(char *)"im_class", T_OBJECT, OFF(m_class), READONLY | RESTRICTED, (char *)"the class associated with a method"}, {(char *)"im_func", T_OBJECT, OFF(m_function), READONLY | RESTRICTED, (char *)"the function (or other callable) implementing a method"}, {(char *)"__func__", T_OBJECT, OFF(m_function), READONLY | RESTRICTED, (char *)"the function (or other callable) implementing a method"}, {(char *)"im_self", T_OBJECT, OFF(m_object), READONLY | RESTRICTED, (char *)"the instance to which a method is bound; None for unbound method"}, {(char *)"__self__", T_OBJECT, OFF(m_object), READONLY | RESTRICTED, (char *)"the instance to which a method is bound; None for unbound method"}, {NULL}}; static PyObject *Nuitka_Method_reduce(struct Nuitka_MethodObject *method) { #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't pickle instancemethod objects"); return NULL; #elif PYTHON_VERSION < 0x340 SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't pickle method objects"); return NULL; #else PyObject *result = PyTuple_New(2); PyTuple_SET_ITEM0(result, 0, LOOKUP_BUILTIN(const_str_plain_getattr)); PyObject *arg_tuple = PyTuple_New(2); PyTuple_SET_ITEM0(arg_tuple, 0, method->m_object); PyTuple_SET_ITEM0(arg_tuple, 1, method->m_function->m_name); PyTuple_SET_ITEM(result, 1, arg_tuple); CHECK_OBJECT_DEEP(result); return result; #endif } static PyObject *Nuitka_Method_reduce_ex(struct Nuitka_MethodObject *method, PyObject *args) { int proto; if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) { return NULL; } #if PYTHON_VERSION < 0x340 #if PYTHON_VERSION < 0x300 PyObject *copy_reg = PyImport_ImportModule("copy_reg"); #else PyObject *copy_reg = PyImport_ImportModule("copyreg"); #endif CHECK_OBJECT(copy_reg); PyObject *newobj_func = LOOKUP_ATTRIBUTE(copy_reg, const_str_plain___newobj__); Py_DECREF(copy_reg); if (unlikely(newobj_func == NULL)) { return NULL; } PyObject *result = PyTuple_New(5); PyTuple_SET_ITEM(result, 0, newobj_func); PyObject *type_tuple = PyTuple_New(1); PyTuple_SET_ITEM0(type_tuple, 0, (PyObject *)&Nuitka_Method_Type); PyTuple_SET_ITEM(result, 1, type_tuple); PyTuple_SET_ITEM0(result, 2, Py_None); PyTuple_SET_ITEM0(result, 3, Py_None); PyTuple_SET_ITEM0(result, 4, Py_None); CHECK_OBJECT_DEEP(result); return result; #else return Nuitka_Method_reduce(method); #endif } static PyObject *Nuitka_Method_deepcopy(struct Nuitka_MethodObject *method, PyObject *memo) { assert(Nuitka_Method_Check((PyObject *)method)); static PyObject *module_copy = NULL; static PyObject *deepcopy_function = NULL; if (module_copy == NULL) { module_copy = PyImport_ImportModule("copy"); CHECK_OBJECT(module_copy); deepcopy_function = PyObject_GetAttrString(module_copy, "deepcopy"); CHECK_OBJECT(deepcopy_function); } PyObject *object = PyObject_CallFunctionObjArgs(deepcopy_function, method->m_object, memo, NULL); if (unlikely(object == NULL)) { return NULL; } return Nuitka_Method_New(method->m_function, object, method->m_class); } static PyMethodDef Nuitka_Method_methods[] = { {"__reduce__", (PyCFunction)Nuitka_Method_reduce, METH_NOARGS, NULL}, {"__reduce_ex__", (PyCFunction)Nuitka_Method_reduce_ex, METH_VARARGS, NULL}, {"__deepcopy__", (PyCFunction)Nuitka_Method_deepcopy, METH_O, NULL}, {NULL}}; #if PYTHON_VERSION >= 0x380 static PyObject *Nuitka_Method_tp_vectorcall(struct Nuitka_MethodObject *method, PyObject *const *stack, size_t nargsf, PyObject *kwnames) { assert(Nuitka_Method_Check((PyObject *)method)); assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); assert((nargs == 0 && nkwargs == 0) || stack != NULL); Py_ssize_t totalargs = nargs + nkwargs; // Shortcut possible, no args. if (totalargs == 0) { return Nuitka_CallMethodFunctionNoArgs(method->m_function, method->m_object); } PyObject *result; if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { /* We are allowed to mutate the stack. TODO: Is this the normal case, so we can consider the else branch irrelevant? Also does it not make sense to check pos arg and kw counts and shortcut somewhat. */ PyObject **new_args = (PyObject **)stack - 1; PyObject *tmp = new_args[0]; new_args[0] = method->m_object; CHECK_OBJECTS(new_args, totalargs + 1); result = Nuitka_CallFunctionVectorcall(method->m_function, new_args, nargs + 1, kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs); CHECK_OBJECTS(new_args, totalargs + 1); new_args[0] = tmp; } else { /* Definitely having args at this point. */ assert(stack != NULL); NUITKA_DYNAMIC_ARRAY_DECL(new_args, PyObject *, totalargs + 1); new_args[0] = method->m_object; memcpy(&new_args[1], stack, totalargs * sizeof(PyObject *)); CHECK_OBJECTS(new_args, totalargs + 1); result = Nuitka_CallFunctionVectorcall(method->m_function, new_args, nargs + 1, kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs); CHECK_OBJECTS(new_args, totalargs + 1); } return result; } #endif static PyObject *Nuitka_Method_tp_call(struct Nuitka_MethodObject *method, PyObject *args, PyObject *kw) { Py_ssize_t arg_count = PyTuple_GET_SIZE(args); if (method->m_object == NULL) { if (unlikely(arg_count < 1)) { PyErr_Format( PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class)); return NULL; } else { PyObject *self = PyTuple_GET_ITEM(args, 0); CHECK_OBJECT(self); int result = PyObject_IsInstance(self, method->m_class); if (unlikely(result < 0)) { return NULL; } else if (unlikely(result == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } } return Py_TYPE(method->m_function)->tp_call((PyObject *)method->m_function, args, kw); } else { if (kw == NULL) { if (arg_count == 0) { return Nuitka_CallMethodFunctionNoArgs(method->m_function, method->m_object); } else { return Nuitka_CallMethodFunctionPosArgs(method->m_function, method->m_object, &PyTuple_GET_ITEM(args, 0), arg_count); } } else { return Nuitka_CallMethodFunctionPosArgsKwArgs(method->m_function, method->m_object, &PyTuple_GET_ITEM(args, 0), arg_count, kw); } } } static PyObject *Nuitka_Method_tp_descr_get(struct Nuitka_MethodObject *method, PyObject *object, PyObject *klass) { // Don't rebind already bound methods. if (method->m_object != NULL) { Py_INCREF(method); return (PyObject *)method; } if (method->m_class != NULL && klass != NULL) { // Quick subclass test, bound methods remain the same if the class is a sub class int result = PyObject_IsSubclass(klass, method->m_class); if (unlikely(result < 0)) { return NULL; } else if (result == 0) { Py_INCREF(method); return (PyObject *)method; } } return Nuitka_Method_New(method->m_function, object, klass); } static PyObject *Nuitka_Method_tp_getattro(struct Nuitka_MethodObject *method, PyObject *name) { PyObject *descr = Nuitka_TypeLookup(&Nuitka_Method_Type, name); if (descr != NULL) { if (NuitkaType_HasFeatureClass(Py_TYPE(descr)) && (Py_TYPE(descr)->tp_descr_get != NULL)) { return Py_TYPE(descr)->tp_descr_get(descr, (PyObject *)method, (PyObject *)Py_TYPE(method)); } else { Py_INCREF(descr); return descr; } } return PyObject_GetAttr((PyObject *)method->m_function, name); } static long Nuitka_Method_tp_traverse(struct Nuitka_MethodObject *method, visitproc visit, void *arg) { Py_VISIT(method->m_function); Py_VISIT(method->m_object); Py_VISIT(method->m_class); return 0; } // tp_repr slot, decide how a function shall be output static PyObject *Nuitka_Method_tp_repr(struct Nuitka_MethodObject *method) { if (method->m_object == NULL) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat("", GET_CLASS_NAME(method->m_class), Nuitka_String_AsString(method->m_function->m_name)); #else return PyUnicode_FromFormat("", Nuitka_String_AsString(method->m_function->m_name), method->m_function); #endif } else { // Note: CPython uses repr of the object, although a comment despises // it, we do it for compatibility. PyObject *object_repr = PyObject_Repr(method->m_object); if (object_repr == NULL) { return NULL; } #if PYTHON_VERSION < 0x300 else if (!PyString_Check(object_repr)) { Py_DECREF(object_repr); return NULL; } #else else if (!PyUnicode_Check(object_repr)) { Py_DECREF(object_repr); return NULL; } #endif #if PYTHON_VERSION < 0x300 PyObject *result = PyString_FromFormat("", GET_CLASS_NAME(method->m_class), Nuitka_String_AsString(method->m_function->m_name), Nuitka_String_AsString_Unchecked(object_repr)); #elif PYTHON_VERSION < 0x350 PyObject *result = PyUnicode_FromFormat("", GET_CLASS_NAME(method->m_class), Nuitka_String_AsString(method->m_function->m_name), Nuitka_String_AsString_Unchecked(object_repr)); #else PyObject *result = PyUnicode_FromFormat("", Nuitka_String_AsString(method->m_function->m_qualname), Nuitka_String_AsString_Unchecked(object_repr)); #endif Py_DECREF(object_repr); return result; } } #if PYTHON_VERSION < 0x300 static int Nuitka_Method_tp_compare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b) { if (a->m_function->m_counter < b->m_function->m_counter) { return -1; } else if (a->m_function->m_counter > b->m_function->m_counter) { return 1; } else if (a->m_object == b->m_object) { return 0; } else if (a->m_object == NULL) { return -1; } else if (b->m_object == NULL) { return 1; } else { return PyObject_Compare(a->m_object, b->m_object); } } #endif static PyObject *Nuitka_Method_tp_richcompare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b, int op) { if (op != Py_EQ && op != Py_NE) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } if (Nuitka_Method_Check((PyObject *)a) == false || Nuitka_Method_Check((PyObject *)b) == false) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } bool b_res = a->m_function->m_counter == b->m_function->m_counter; // If the underlying function objects are the same, check the objects, which // may be NULL in case of unbound methods, which would be the same again. if (b_res) { #if PYTHON_VERSION < 0x380 if (a->m_object == NULL) { b_res = b->m_object == NULL; } else if (b->m_object == NULL) { b_res = false; } else { int res = PyObject_RichCompareBool(a->m_object, b->m_object, Py_EQ); if (unlikely(res < 0)) { return NULL; } b_res = res != 0; } #else b_res = a->m_object == b->m_object; #endif } PyObject *result; if (op == Py_EQ) { result = BOOL_FROM(b_res); } else { result = BOOL_FROM(!b_res); } Py_INCREF(result); return result; } static long Nuitka_Method_tp_hash(struct Nuitka_MethodObject *method) { // Just give the hash of the method function, that ought to be good enough. return method->m_function->m_counter; } #define MAX_METHOD_FREE_LIST_COUNT 100 static struct Nuitka_MethodObject *free_list_methods = NULL; static int free_list_methods_count = 0; static void Nuitka_Method_tp_dealloc(struct Nuitka_MethodObject *method) { #ifndef __NUITKA_NO_ASSERT__ // Save the current exception, if any, we must to not corrupt it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); #endif Nuitka_GC_UnTrack(method); if (method->m_weakrefs != NULL) { PyObject_ClearWeakRefs((PyObject *)method); } Py_XDECREF(method->m_object); Py_XDECREF(method->m_class); Py_DECREF((PyObject *)method->m_function); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_methods, method, MAX_METHOD_FREE_LIST_COUNT); #ifndef __NUITKA_NO_ASSERT__ PyThreadState *tstate = PyThreadState_GET(); assert(tstate->curexc_type == save_exception_type); assert(tstate->curexc_value == save_exception_value); assert((PyTracebackObject *)tstate->curexc_traceback == save_exception_tb); #endif } static PyObject *Nuitka_Method_tp_new(PyTypeObject *type, PyObject *args, PyObject *kw) { PyObject *func; PyObject *self; PyObject *klass = NULL; if (!_PyArg_NoKeywords("compiled_method", kw)) { return NULL; } else if (!PyArg_UnpackTuple(args, "compiled_method", 2, 3, &func, &self, &klass)) { return NULL; } else if (!PyCallable_Check(func)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "first argument must be callable"); return NULL; } else { if (self == Py_None) { self = NULL; } if (self == NULL && klass == NULL) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "unbound methods must have non-NULL im_class"); return NULL; } } assert(Nuitka_Function_Check(func)); return Nuitka_Method_New((struct Nuitka_FunctionObject *)func, self, klass); } PyTypeObject Nuitka_Method_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_method", sizeof(struct Nuitka_MethodObject), 0, (destructor)Nuitka_Method_tp_dealloc, /* tp_dealloc */ #if PYTHON_VERSION < 0x380 0, /* tp_print */ #else offsetof(struct Nuitka_MethodObject, m_vectorcall), /* tp_vectorcall_offset */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ #if PYTHON_VERSION < 0x300 (cmpfunc)Nuitka_Method_tp_compare, /* tp_compare */ #else 0, #endif (reprfunc)Nuitka_Method_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Nuitka_Method_tp_hash, /* tp_hash */ (ternaryfunc)Nuitka_Method_tp_call, /* tp_call */ 0, /* tp_str */ (getattrofunc)Nuitka_Method_tp_getattro, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | /* tp_flags */ #if PYTHON_VERSION < 0x300 Py_TPFLAGS_HAVE_WEAKREFS | #endif #if PYTHON_VERSION >= 0x380 _Py_TPFLAGS_HAVE_VECTORCALL | #endif Py_TPFLAGS_HAVE_GC, 0, /* tp_doc */ (traverseproc)Nuitka_Method_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)Nuitka_Method_tp_richcompare, /* tp_richcompare */ offsetof(struct Nuitka_MethodObject, m_weakrefs), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Method_methods, /* tp_methods */ Nuitka_Method_members, /* tp_members */ Nuitka_Method_getsets, /* tp_getset */ #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyMethod_Type, /* tp_base */ #else 0, /* tp_base */ #endif 0, /* tp_dict */ (descrgetfunc)Nuitka_Method_tp_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Nuitka_Method_tp_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0 /* tp_version_tag */ #if PYTHON_VERSION >= 0x340 , 0 /* tp_finalizer */ #endif }; void _initCompiledMethodType(void) { PyType_Ready(&Nuitka_Method_Type); #ifdef _NUITKA_PLUGIN_DILL_ENABLED // TODO: Move this to a __nuitka__ module maybe PyObject_SetAttrString((PyObject *)builtin_module, "compiled_method", (PyObject *)&Nuitka_Method_Type); #endif } PyObject *Nuitka_Method_New(struct Nuitka_FunctionObject *function, PyObject *object, PyObject *klass) { struct Nuitka_MethodObject *result; allocateFromFreeListFixed(free_list_methods, struct Nuitka_MethodObject, Nuitka_Method_Type); if (unlikely(result == NULL)) { PyErr_Format(PyExc_RuntimeError, "cannot create method %s", Nuitka_String_AsString(function->m_name)); return NULL; } Py_INCREF(function); result->m_function = function; result->m_object = object; Py_XINCREF(object); result->m_class = klass; Py_XINCREF(klass); result->m_weakrefs = NULL; #if PYTHON_VERSION >= 0x380 result->m_vectorcall = (vectorcallfunc)Nuitka_Method_tp_vectorcall; #endif Nuitka_GC_Track(result); return (PyObject *)result; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryDivmod.c0000600000372100037210000014261414166627112032766 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersOperationBinaryDivmodUtils.c" /* C helpers for type specialized "divmod" (DIVMOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b); obj_result = r; goto exit_result_object; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divmod; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b); obj_result = r; goto exit_result_object; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divmod; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b); obj_result = r; goto exit_result_object; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divmod; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divmod; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { mod += b; div -= 1.0; } } else { mod = copysign(0.0, b); } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } PyObject *r = Py_BuildValue("(dd)", floordiv, mod); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divmod; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { mod += b; div -= 1.0; } } else { mod = copysign(0.0, b); } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } PyObject *r = Py_BuildValue("(dd)", floordiv, mod); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divmod; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { mod += b; div -= 1.0; } } else { mod = copysign(0.0, b); } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } PyObject *r = Py_BuildValue("(dd)", floordiv, mod); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b); obj_result = r; goto exit_result_object; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divmod; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryMod.c0000600000372100037210000060702114166627112032261 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "%" (MOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_FLOAT_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'unicode'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_UNICODE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'tuple'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_TUPLE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'list'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_LIST(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "DICT" to Python 'dict'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_DICT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'dict'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_DICT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_DICT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_STR_STR(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_INT(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_LONG(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyString_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'str'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_STR(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "BYTES" to Python3 'bytes'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyBytes_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'bytes'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_BYTES(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'tuple'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'tuple'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_TUPLE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'list'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'list'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_LIST(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "DICT" to Python 'dict'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_DICT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'dict'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'dict'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_DICT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_DICT(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_LONG(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'str'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_UNICODE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'tuple'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_TUPLE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'list'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_LIST(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "DICT" to Python 'dict'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_DICT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'dict'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_DICT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_DICT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyString_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'str'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_STR_STR(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyBytes_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'bytes'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'unicode'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'str'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(operand1, operand2); } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'tuple'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'list'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "DICT" to Python 'dict'. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_DICT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'dict'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_DICT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_DICT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_MOD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceMod.c0000600000372100037210000053710614166627112032416 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "%" (MOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MOD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float modulo"); goto exit_result_exception; } { double mod = fmod(a, b); if (mod) { if ((a < 0) != (mod < 0)) { mod += b; } } else { mod = copysign(0.0, b); } cfloat_result = mod; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MOD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MOD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MOD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MOD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_FLOAT_LONG_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MOD_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MOD_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_STR_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_MOD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static inline bool _BINARY_OPERATION_MOD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'unicode'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_UNICODE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MOD_STR_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'tuple'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_TUPLE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MOD_STR_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'list'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_LIST_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "DICT" to Python 'dict'. */ static inline bool _BINARY_OPERATION_MOD_STR_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'dict'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_STR_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_DICT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_STR_STR_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_LONG_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyString_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'str'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "BYTES" to Python3 'bytes'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyBytes_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'bytes'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_BYTES_INPLACE(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'tuple'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'tuple'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'list'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'list'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_LIST_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "DICT" to Python 'dict'. */ static inline bool _BINARY_OPERATION_MOD_UNICODE_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and 'dict'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and 'dict'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_UNICODE_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_DICT_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'unicode' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'str' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'str'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_UNICODE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'tuple'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_TUPLE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'list'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_LIST_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "DICT" to Python 'dict'. */ static inline bool _BINARY_OPERATION_MOD_BYTES_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and 'dict'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_BYTES_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_DICT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_remainder available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_remainder == NULL); { binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: 'bytes' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyString_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'str'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyString_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_STR_STR_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyBytes_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'bytes'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyBytes_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyUnicode_Type.tp_as_number->nb_remainder; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'unicode'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'str'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyUnicode_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyUnicode_Format(*operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MOD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'tuple'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MOD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'list'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_LIST_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "DICT" to Python 'dict'. */ static inline bool _BINARY_OPERATION_MOD_OBJECT_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyDict_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyDict_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_remainder == NULL || type1->tp_as_number->nb_remainder == type2->tp_as_number->nb_remainder); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and 'dict'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_OBJECT_DICT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_DICT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MOD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long r = a % b; // Sign handling. if (r != 0 && ((b ^ r) < 0)) { r += b; } clong_result = r; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_remainder : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_remainder; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MOD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MOD_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonNe.c0000600000372100037210000157465214166627112031127 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "!=" (NE) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_NE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a != b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_NE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a != b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_NE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a != b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_NE_OBJECT_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = false; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_NE_CBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = false; bool result = r; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_NE_NBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = false; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_NE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_NE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_NE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. bool result = r; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. bool result = r; return result; } else { bool r = true; // Convert to target type. bool result = r; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_NE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_NE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_NE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_NE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_NE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_NE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } PyObject *result = BOOL_FROM(r == false); Py_INCREF(result); return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } PyObject *result = BOOL_FROM(r == false); Py_INCREF(result); return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_NE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_NE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } bool result = r == false; return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } bool result = r == false; return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_NE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_NE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } nuitka_bool result = r == false ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } nuitka_bool result = r == false ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_NE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_NE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_NE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_NE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. bool result = r; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. bool result = r; return result; } else { bool r = true; // Convert to target type. bool result = r; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_NE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_NE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_NE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_NE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_NE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_NE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_NE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_NE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_NE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_NE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_NE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_NE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = true; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = true; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_NE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_NE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = true; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = true; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_NE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_NE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = false; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = true; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = false; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = true; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_NE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_NE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_NE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() != %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_NE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a != b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_NE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_NE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a != b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_NE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_NE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a != b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_NE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_NE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_NE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_NE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_NE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_NE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. bool result = r; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. bool result = r; return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_NE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_NE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_NE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_NE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_NE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_NE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_NE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_NE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. bool result = r; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. bool result = r; return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_NE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_NE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_FALSE; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_NE_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_NE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_NE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_NE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_NE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() != list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_NE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_NE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_NE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_NE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_NE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_NE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_NE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_NE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_NE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() != %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'!=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceBitor.c0000600000372100037210000015433114166627112032751 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "|" (BITOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_or : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_or available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_or == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_BITOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_or : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_or available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_or == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_or available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_or == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_or available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_or == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_LONG_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static inline bool _BINARY_OPERATION_BITOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_SET_SET_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_or : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'set'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = PySet_Type.tp_as_number->nb_inplace_or; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = PySet_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'set' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITOR_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_or(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_BITOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_or : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryDivmodUtils.c0000600000372100037210000000232414166627112034000 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* These are defines used in floordiv code. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include /* Check if unary negation would not fit into long */ #define UNARY_NEG_WOULD_OVERFLOW(x) ((x) < 0 && (unsigned long)(x) == 0 - (unsigned long)(x)) /* This is from pyport.h */ #define WIDTH_OF_ULONG (CHAR_BIT * SIZEOF_LONG) Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceTruediv.c0000600000372100037210000023166414166627112033321 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "/" (TRUEDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_0_0); *operand1 = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_minus_0_0); *operand1 = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_true_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_0_0); *operand1 = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_minus_0_0); *operand1 = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_0_0); *operand1 = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_minus_0_0); *operand1 = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_true_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_true_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_TRUEDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_TRUEDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_TRUEDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_true_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_true_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_FLOAT_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_0_0); *operand1 = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_float_minus_0_0); *operand1 = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_true_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersClasses.c0000600000372100037210000000564514166627112030115 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For creating classes. * * Currently only the Python3 meta class selection is here, but more will be * added later, should be choose to have our own "__slots__" special metaclass. * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #if PYTHON_VERSION >= 0x300 PyObject *SELECT_METACLASS(PyObject *metaclass, PyObject *bases) { CHECK_OBJECT(metaclass); CHECK_OBJECT(bases); if (likely(PyType_Check(metaclass))) { // Determine the proper metaclass type Py_ssize_t nbases = PyTuple_GET_SIZE(bases); PyTypeObject *winner = (PyTypeObject *)metaclass; #if _DEBUG_CLASSES PRINT_STRING("Bases:"); PRINT_ITEM((PyObject *)bases); PRINT_NEW_LINE(); #endif for (int i = 0; i < nbases; i++) { PyObject *base = PyTuple_GET_ITEM(bases, i); PyTypeObject *base_type = Py_TYPE(base); if (PyType_IsSubtype(winner, base_type)) { // Ignore if current winner is already a subtype. continue; } else if (PyType_IsSubtype(base_type, winner)) { // Use if, if it's a subtype of the current winner. winner = base_type; continue; } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "metaclass conflict: the metaclass of a derived class must be a " "(non-strict) subclass of the metaclasses of all its bases"); return NULL; } } if (unlikely(winner == NULL)) { return NULL; } #if _DEBUG_CLASSES PRINT_STRING("Metaclass winner:"); PRINT_ITEM((PyObject *)winner); PRINT_NEW_LINE(); #endif Py_INCREF(winner); return (PyObject *)winner; } else { #if _DEBUG_CLASSES PRINT_STRING("Metaclass not a type is used:"); PRINT_ITEM((PyObject *)metaclass); PRINT_NEW_LINE(); #endif Py_INCREF(metaclass); return metaclass; } } #endif Nuitka-0.6.19.1/nuitka/build/static_src/CompiledFunctionType.c0000600000372100037210000027074614166627112031307 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "nuitka/prelude.h" #include "nuitka/compiled_method.h" #include "nuitka/freelists.h" // Needed for offsetof #include "structmember.h" #include // tp_descr_get slot, bind a function to an object. static PyObject *Nuitka_Function_descr_get(PyObject *function, PyObject *object, PyObject *klass) { assert(Nuitka_Function_Check(function)); #if PYTHON_VERSION >= 0x300 if (object == NULL || object == Py_None) { Py_INCREF(function); return function; } #endif return Nuitka_Method_New((struct Nuitka_FunctionObject *)function, object == Py_None ? NULL : object, klass); } // tp_repr slot, decide how compiled function shall be output to "repr" built-in static PyObject *Nuitka_Function_tp_repr(struct Nuitka_FunctionObject *function) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif "", #if PYTHON_VERSION < 0x300 Nuitka_String_AsString(function->m_name), #else Nuitka_String_AsString(function->m_qualname), #endif function); } static long Nuitka_Function_tp_traverse(struct Nuitka_FunctionObject *function, visitproc visit, void *arg) { // TODO: Identify the impact of not visiting other owned objects. It appears // to be mostly harmless, as these are strings. Py_VISIT(function->m_dict); for (Py_ssize_t i = 0; i < function->m_closure_given; i++) { Py_VISIT(function->m_closure[i]); } return 0; } static long Nuitka_Function_tp_hash(struct Nuitka_FunctionObject *function) { return function->m_counter; } static PyObject *Nuitka_Function_get_name(struct Nuitka_FunctionObject *object) { PyObject *result = object->m_name; Py_INCREF(result); return result; } static int Nuitka_Function_set_name(struct Nuitka_FunctionObject *object, PyObject *value) { #if PYTHON_VERSION < 0x300 if (unlikely(value == NULL || PyString_Check(value) == 0)) #else if (unlikely(value == NULL || PyUnicode_Check(value) == 0)) #endif { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } PyObject *old = object->m_name; Py_INCREF(value); object->m_name = value; Py_DECREF(old); return 0; } #if PYTHON_VERSION >= 0x300 static PyObject *Nuitka_Function_get_qualname(struct Nuitka_FunctionObject *object) { PyObject *result = object->m_qualname; Py_INCREF(result); return result; } static int Nuitka_Function_set_qualname(struct Nuitka_FunctionObject *object, PyObject *value) { if (unlikely(value == NULL || PyUnicode_Check(value) == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } PyObject *old = object->m_qualname; Py_INCREF(value); object->m_qualname = value; Py_DECREF(old); return 0; } #endif static PyObject *Nuitka_Function_get_doc(struct Nuitka_FunctionObject *object) { PyObject *result = object->m_doc; if (result == NULL) { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Function_set_doc(struct Nuitka_FunctionObject *object, PyObject *value) { PyObject *old = object->m_doc; object->m_doc = value; Py_XINCREF(value); Py_XDECREF(old); return 0; } static PyObject *Nuitka_Function_get_dict(struct Nuitka_FunctionObject *object) { if (object->m_dict == NULL) { object->m_dict = PyDict_New(); } Py_INCREF(object->m_dict); return object->m_dict; } static int Nuitka_Function_set_dict(struct Nuitka_FunctionObject *object, PyObject *value) { if (unlikely(value == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "function's dictionary may not be deleted"); return -1; } if (likely(PyDict_Check(value))) { PyObject *old = object->m_dict; Py_INCREF(value); object->m_dict = value; Py_XDECREF(old); return 0; } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "setting function's dictionary to a non-dict"); return -1; } } static PyObject *Nuitka_Function_get_code(struct Nuitka_FunctionObject *object) { PyObject *result = (PyObject *)object->m_code_object; Py_INCREF(result); return result; } static int Nuitka_Function_set_code(struct Nuitka_FunctionObject *object, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "__code__ is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Function_get_closure(struct Nuitka_FunctionObject *object) { if (object->m_closure_given > 0) { PyObject *result = PyTuple_New(object->m_closure_given); for (Py_ssize_t i = 0; i < object->m_closure_given; i++) { PyTuple_SET_ITEM0(result, i, (PyObject *)object->m_closure[i]); } return result; } else { Py_INCREF(Py_None); return Py_None; } } static int Nuitka_Function_set_closure(struct Nuitka_FunctionObject *object, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR( #if PYTHON_VERSION < 0x300 PyExc_TypeError, #else PyExc_AttributeError, #endif "readonly attribute"); return -1; } static PyObject *Nuitka_Function_get_defaults(struct Nuitka_FunctionObject *object) { PyObject *result = (PyObject *)object->m_defaults; Py_INCREF(result); return result; } static void onUpdatedDefaultsValue(struct Nuitka_FunctionObject *function) { if (function->m_defaults == Py_None) { function->m_defaults_given = 0; } else { function->m_defaults_given = PyTuple_GET_SIZE(function->m_defaults); } } static int Nuitka_Function_set_defaults(struct Nuitka_FunctionObject *object, PyObject *value) { if (value == NULL) { value = Py_None; } if (unlikely(value != Py_None && PyTuple_Check(value) == false)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__defaults__ must be set to a tuple object"); return -1; } // TODO: Do we actually need this ever, probably not, as we don't generate argument // parsing per function anymore. #ifndef _NUITKA_PLUGIN_DILL_ENABLED if (object->m_defaults == Py_None && value != Py_None) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "Nuitka doesn't support __defaults__ size changes"); return -1; } if (object->m_defaults != Py_None && (value == Py_None || PyTuple_GET_SIZE(object->m_defaults) != PyTuple_GET_SIZE(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "Nuitka doesn't support __defaults__ size changes"); return -1; } #endif PyObject *old = object->m_defaults; Py_INCREF(value); object->m_defaults = value; Py_DECREF(old); onUpdatedDefaultsValue(object); return 0; } #if PYTHON_VERSION >= 0x300 static PyObject *Nuitka_Function_get_kwdefaults(struct Nuitka_FunctionObject *object) { PyObject *result = object->m_kwdefaults; if (result == NULL) { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Function_set_kwdefaults(struct Nuitka_FunctionObject *object, PyObject *value) { if (value == NULL) { value = Py_None; } if (unlikely(value != Py_None && PyDict_Check(value) == false)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__kwdefaults__ must be set to a dict object"); return -1; } if (value == Py_None) { value = NULL; } PyObject *old = object->m_kwdefaults; Py_XINCREF(value); object->m_kwdefaults = value; Py_XDECREF(old); return 0; } static PyObject *Nuitka_Function_get_annotations(struct Nuitka_FunctionObject *object) { if (object->m_annotations == NULL) { object->m_annotations = PyDict_New(); } Py_INCREF(object->m_annotations); return object->m_annotations; } static int Nuitka_Function_set_annotations(struct Nuitka_FunctionObject *object, PyObject *value) { if (unlikely(value != NULL && PyDict_Check(value) == false)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__annotations__ must be set to a dict object"); return -1; } PyObject *old = object->m_annotations; Py_XINCREF(value); object->m_annotations = value; Py_XDECREF(old); return 0; } #endif static int Nuitka_Function_set_globals(struct Nuitka_FunctionObject *function, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "readonly attribute"); return -1; } static PyObject *Nuitka_Function_get_globals(struct Nuitka_FunctionObject *function) { PyObject *result = PyModule_GetDict(function->m_module); Py_INCREF(result); return result; } #if PYTHON_VERSION >= 0x3a0 static int Nuitka_Function_set_builtins(struct Nuitka_FunctionObject *function, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "readonly attribute"); return -1; } static PyObject *Nuitka_Function_get_builtins(struct Nuitka_FunctionObject *function) { return LOOKUP_SUBSCRIPT(PyModule_GetDict(function->m_module), const_str_plain___builtins__); } #endif static int Nuitka_Function_set_module(struct Nuitka_FunctionObject *object, PyObject *value) { if (object->m_dict == NULL) { object->m_dict = PyDict_New(); } if (value == NULL) { value = Py_None; } return PyDict_SetItem(object->m_dict, const_str_plain___module__, value); } static PyObject *Nuitka_Function_get_module(struct Nuitka_FunctionObject *object) { PyObject *result; // The __dict__ might overrule this. if (object->m_dict) { result = DICT_GET_ITEM1(object->m_dict, const_str_plain___module__); if (result != NULL) { return result; } } result = MODULE_NAME1(object->m_module); return result; } static PyGetSetDef Nuitka_Function_getset[] = { #if PYTHON_VERSION >= 0x300 {(char *)"__qualname__", (getter)Nuitka_Function_get_qualname, (setter)Nuitka_Function_set_qualname, NULL}, #endif #if PYTHON_VERSION < 0x300 {(char *)"func_name", (getter)Nuitka_Function_get_name, (setter)Nuitka_Function_set_name, NULL}, #endif {(char *)"__name__", (getter)Nuitka_Function_get_name, (setter)Nuitka_Function_set_name, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_doc", (getter)Nuitka_Function_get_doc, (setter)Nuitka_Function_set_doc, NULL}, #endif {(char *)"__doc__", (getter)Nuitka_Function_get_doc, (setter)Nuitka_Function_set_doc, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_dict", (getter)Nuitka_Function_get_dict, (setter)Nuitka_Function_set_dict, NULL}, #endif {(char *)"__dict__", (getter)Nuitka_Function_get_dict, (setter)Nuitka_Function_set_dict, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_code", (getter)Nuitka_Function_get_code, (setter)Nuitka_Function_set_code, NULL}, #endif {(char *)"__code__", (getter)Nuitka_Function_get_code, (setter)Nuitka_Function_set_code, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_defaults", (getter)Nuitka_Function_get_defaults, (setter)Nuitka_Function_set_defaults, NULL}, #endif {(char *)"__defaults__", (getter)Nuitka_Function_get_defaults, (setter)Nuitka_Function_set_defaults, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_globals", (getter)Nuitka_Function_get_globals, (setter)Nuitka_Function_set_globals, NULL}, #endif {(char *)"__closure__", (getter)Nuitka_Function_get_closure, (setter)Nuitka_Function_set_closure, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"func_closure", (getter)Nuitka_Function_get_closure, (setter)Nuitka_Function_set_closure, NULL}, #endif {(char *)"__globals__", (getter)Nuitka_Function_get_globals, (setter)Nuitka_Function_set_globals, NULL}, {(char *)"__module__", (getter)Nuitka_Function_get_module, (setter)Nuitka_Function_set_module, NULL}, #if PYTHON_VERSION >= 0x300 {(char *)"__kwdefaults__", (getter)Nuitka_Function_get_kwdefaults, (setter)Nuitka_Function_set_kwdefaults, NULL}, {(char *)"__annotations__", (getter)Nuitka_Function_get_annotations, (setter)Nuitka_Function_set_annotations, NULL}, #endif #if PYTHON_VERSION >= 0x3a0 {(char *)"__builtins__", (getter)Nuitka_Function_get_builtins, (setter)Nuitka_Function_set_builtins, NULL}, #endif {NULL}}; static PyObject *Nuitka_Function_reduce(struct Nuitka_FunctionObject *function) { PyObject *result; #if PYTHON_VERSION < 0x300 result = function->m_name; #else result = function->m_qualname; #endif Py_INCREF(result); return result; } #define MAX_FUNCTION_FREE_LIST_COUNT 100 static struct Nuitka_FunctionObject *free_list_functions = NULL; static int free_list_functions_count = 0; static void Nuitka_Function_tp_dealloc(struct Nuitka_FunctionObject *function) { #ifndef __NUITKA_NO_ASSERT__ // Save the current exception, if any, we must to not corrupt it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); #endif Nuitka_GC_UnTrack(function); if (function->m_weakrefs != NULL) { PyObject_ClearWeakRefs((PyObject *)function); } Py_DECREF(function->m_name); #if PYTHON_VERSION >= 0x300 Py_DECREF(function->m_qualname); #endif // These may actually re-surrect the object, not? Py_XDECREF(function->m_dict); Py_DECREF(function->m_defaults); Py_XDECREF(function->m_doc); #if PYTHON_VERSION >= 0x300 Py_XDECREF(function->m_kwdefaults); Py_XDECREF(function->m_annotations); #endif for (Py_ssize_t i = 0; i < function->m_closure_given; i++) { assert(function->m_closure[i]); Py_DECREF(function->m_closure[i]); // Note: No need to set to NULL, each function creation makes // a full copy, doing the init. } /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_functions, function, MAX_FUNCTION_FREE_LIST_COUNT); #ifndef __NUITKA_NO_ASSERT__ PyThreadState *tstate = PyThreadState_GET(); assert(tstate->curexc_type == save_exception_type); assert(tstate->curexc_value == save_exception_value); assert((PyTracebackObject *)tstate->curexc_traceback == save_exception_tb); #endif } static PyMethodDef Nuitka_Function_methods[] = {{"__reduce__", (PyCFunction)Nuitka_Function_reduce, METH_NOARGS, NULL}, {NULL}}; static PyObject *Nuitka_Function_tp_call(struct Nuitka_FunctionObject *function, PyObject *tuple_args, PyObject *kw); PyTypeObject Nuitka_Function_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_function", /* tp_name */ sizeof(struct Nuitka_FunctionObject), /* tp_basicsize */ sizeof(struct Nuitka_CellObject *), /* tp_itemsize */ (destructor)Nuitka_Function_tp_dealloc, /* tp_dealloc */ #if PYTHON_VERSION < 0x380 0, /* tp_print */ #else offsetof(struct Nuitka_FunctionObject, m_vectorcall), /* tp_vectorcall_offset */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)Nuitka_Function_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Nuitka_Function_tp_hash, /* tp_hash */ (ternaryfunc)Nuitka_Function_tp_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | #if PYTHON_VERSION < 0x300 Py_TPFLAGS_HAVE_WEAKREFS | #endif #if PYTHON_VERSION >= 0x380 _Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_METHOD_DESCRIPTOR | #endif Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Function_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(struct Nuitka_FunctionObject, m_weakrefs), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Function_methods, /* tp_methods */ 0, /* tp_members */ Nuitka_Function_getset, /* tp_getset */ #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyFunction_Type, /* tp_base */ #else 0, /* tp_base */ #endif 0, /* tp_dict */ Nuitka_Function_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(struct Nuitka_FunctionObject, m_dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0 /* tp_version_tag */ #if PYTHON_VERSION >= 0x340 , 0 /* tp_finalizer */ #endif }; void _initCompiledFunctionType(void) { PyType_Ready(&Nuitka_Function_Type); // Be a paranoid subtype of uncompiled function, we want nothing shared. assert(Nuitka_Function_Type.tp_doc != PyFunction_Type.tp_doc); assert(Nuitka_Function_Type.tp_traverse != PyFunction_Type.tp_traverse); assert(Nuitka_Function_Type.tp_clear != PyFunction_Type.tp_clear || PyFunction_Type.tp_clear == NULL); assert(Nuitka_Function_Type.tp_richcompare != PyFunction_Type.tp_richcompare || PyFunction_Type.tp_richcompare == NULL); assert(Nuitka_Function_Type.tp_weaklistoffset != PyFunction_Type.tp_weaklistoffset); assert(Nuitka_Function_Type.tp_iter != PyFunction_Type.tp_iter || PyFunction_Type.tp_iter == NULL); assert(Nuitka_Function_Type.tp_iternext != PyFunction_Type.tp_iternext || PyFunction_Type.tp_iternext == NULL); assert(Nuitka_Function_Type.tp_methods != PyFunction_Type.tp_methods); assert(Nuitka_Function_Type.tp_members != PyFunction_Type.tp_members); assert(Nuitka_Function_Type.tp_getset != PyFunction_Type.tp_getset); #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) assert(Nuitka_Function_Type.tp_base != PyFunction_Type.tp_base); #endif assert(Nuitka_Function_Type.tp_dict != PyFunction_Type.tp_dict); assert(Nuitka_Function_Type.tp_descr_get != PyFunction_Type.tp_descr_get); assert(Nuitka_Function_Type.tp_descr_set != PyFunction_Type.tp_descr_set || PyFunction_Type.tp_descr_set == NULL); assert(Nuitka_Function_Type.tp_dictoffset != PyFunction_Type.tp_dictoffset); // TODO: These get changed and into the same thing, not sure what to compare against, project something // assert(Nuitka_Function_Type.tp_init != PyFunction_Type.tp_init || PyFunction_Type.tp_init == NULL); // assert(Nuitka_Function_Type.tp_alloc != PyFunction_Type.tp_alloc || PyFunction_Type.tp_alloc == NULL); // assert(Nuitka_Function_Type.tp_new != PyFunction_Type.tp_new || PyFunction_Type.tp_new == NULL); // assert(Nuitka_Function_Type.tp_free != PyFunction_Type.tp_free || PyFunction_Type.tp_free == NULL); assert(Nuitka_Function_Type.tp_bases != PyFunction_Type.tp_bases); assert(Nuitka_Function_Type.tp_mro != PyFunction_Type.tp_mro); assert(Nuitka_Function_Type.tp_cache != PyFunction_Type.tp_cache || PyFunction_Type.tp_cache == NULL); assert(Nuitka_Function_Type.tp_subclasses != PyFunction_Type.tp_subclasses || PyFunction_Type.tp_cache == NULL); assert(Nuitka_Function_Type.tp_weaklist != PyFunction_Type.tp_weaklist); assert(Nuitka_Function_Type.tp_del != PyFunction_Type.tp_del || PyFunction_Type.tp_del == NULL); #if PYTHON_VERSION >= 0x340 assert(Nuitka_Function_Type.tp_finalize != PyFunction_Type.tp_finalize || PyFunction_Type.tp_finalize == NULL); #endif // Make sure we don't miss out on attributes we are not having or should not have. #ifndef __NUITKA_NO_ASSERT__ for (struct PyGetSetDef *own = &Nuitka_Function_getset[0]; own->name != NULL; own++) { bool found = false; for (struct PyGetSetDef *related = PyFunction_Type.tp_getset; related->name != NULL; related++) { if (strcmp(related->name, own->name) == 0) { found = true; } } if (found == false) { if (strcmp(own->name, "__doc__") == 0) { // We do that one differently right now. continue; } #if PYTHON_VERSION < 0x300 if (strcmp(own->name, "func_doc") == 0) { // We do that one differently right now. continue; } #endif if (strcmp(own->name, "__globals__") == 0) { // We do that one differently right now. continue; } #if PYTHON_VERSION < 0x300 if (strcmp(own->name, "func_globals") == 0) { // We do that one differently right now. continue; } #endif #if PYTHON_VERSION >= 0x3a0 if (strcmp(own->name, "__builtins__") == 0) { // We do that one differently right now. continue; } #endif if (strcmp(own->name, "__module__") == 0) { // We do that one differently right now. continue; } if (strcmp(own->name, "__closure__") == 0) { // We have to do that differently, because we do not keep this around until // needed, and we make it read-only continue; } #if PYTHON_VERSION < 0x300 if (strcmp(own->name, "func_closure") == 0) { // We have to do that differently, because we do not keep this around until // needed, and we make it read-only continue; } #endif PRINT_FORMAT("Not found in uncompiled type: %s\n", own->name); NUITKA_CANNOT_GET_HERE("Type problem"); } } for (struct PyGetSetDef *related = PyFunction_Type.tp_getset; related->name != NULL; related++) { bool found = false; for (struct PyGetSetDef *own = &Nuitka_Function_getset[0]; own->name != NULL; own++) { if (strcmp(related->name, own->name) == 0) { found = true; } } if (found == false) { PRINT_FORMAT("Not found in compiled type: %s\n", related->name); NUITKA_CANNOT_GET_HERE("Type problem"); } } for (struct PyMemberDef *related = PyFunction_Type.tp_members; related->name != NULL; related++) { bool found = false; for (struct PyGetSetDef *own = &Nuitka_Function_getset[0]; own->name != NULL; own++) { if (strcmp(related->name, own->name) == 0) { found = true; } } if (found == false) { PRINT_FORMAT("Not found in compiled type: %s\n", related->name); NUITKA_CANNOT_GET_HERE("Type problem"); } } #endif #ifdef _NUITKA_PLUGIN_DILL_ENABLED // TODO: Move this to a __nuitka__ module maybe PyObject_SetAttrString((PyObject *)builtin_module, "compiled_function", (PyObject *)&Nuitka_Function_Type); #endif } // Shared implementations for empty functions. When a function body is empty, but // still needs to exist, e.g. overloaded functions, this is saving the effort to // produce one. static PyObject *_Nuitka_FunctionEmptyCodeNoneImpl(struct Nuitka_FunctionObject const *function, PyObject **python_pars) { Py_ssize_t arg_count = function->m_args_overall_count; for (Py_ssize_t i = 0; i < arg_count; i++) { Py_DECREF(python_pars[i]); } PyObject *result = Py_None; Py_INCREF(result); return result; } static PyObject *_Nuitka_FunctionEmptyCodeTrueImpl(struct Nuitka_FunctionObject const *function, PyObject **python_pars) { Py_ssize_t arg_count = function->m_args_overall_count; for (Py_ssize_t i = 0; i < arg_count; i++) { Py_DECREF(python_pars[i]); } PyObject *result = Py_True; Py_INCREF(result); return result; } static PyObject *_Nuitka_FunctionEmptyCodeFalseImpl(struct Nuitka_FunctionObject const *function, PyObject **python_pars) { Py_ssize_t arg_count = function->m_args_overall_count; for (Py_ssize_t i = 0; i < arg_count; i++) { Py_DECREF(python_pars[i]); } PyObject *result = Py_False; Py_INCREF(result); return result; } static PyObject *_Nuitka_FunctionEmptyCodeGenericImpl(struct Nuitka_FunctionObject const *function, PyObject **python_pars) { Py_ssize_t arg_count = function->m_args_overall_count; for (Py_ssize_t i = 0; i < arg_count; i++) { Py_DECREF(python_pars[i]); } PyObject *result = function->m_constant_return_value; Py_INCREF(result); return result; } void Nuitka_Function_EnableConstReturnTrue(struct Nuitka_FunctionObject *function) { function->m_constant_return_value = Py_True; function->m_c_code = _Nuitka_FunctionEmptyCodeTrueImpl; } void Nuitka_Function_EnableConstReturnFalse(struct Nuitka_FunctionObject *function) { function->m_constant_return_value = Py_False; function->m_c_code = _Nuitka_FunctionEmptyCodeFalseImpl; } void Nuitka_Function_EnableConstReturnGeneric(struct Nuitka_FunctionObject *function, PyObject *value) { function->m_constant_return_value = value; function->m_c_code = _Nuitka_FunctionEmptyCodeGenericImpl; } #if PYTHON_VERSION >= 0x380 static PyObject *Nuitka_Function_tp_vectorcall(struct Nuitka_FunctionObject *function, PyObject *const *stack, size_t nargsf, PyObject *kwnames); #endif // Make a function with closure. #if PYTHON_VERSION < 0x300 struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name, PyCodeObject *code_object, PyObject *defaults, PyObject *module, PyObject *doc, struct Nuitka_CellObject **closure, Py_ssize_t closure_given) #else struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name, PyObject *qualname, PyCodeObject *code_object, PyObject *defaults, PyObject *kwdefaults, PyObject *annotations, PyObject *module, PyObject *doc, struct Nuitka_CellObject **closure, Py_ssize_t closure_given) #endif { struct Nuitka_FunctionObject *result; // Macro to assign result memory from GC or free list. allocateFromFreeList(free_list_functions, struct Nuitka_FunctionObject, Nuitka_Function_Type, closure_given); memcpy(&result->m_closure[0], closure, closure_given * sizeof(struct Nuitka_CellObject *)); result->m_closure_given = closure_given; if (c_code != NULL) { result->m_c_code = c_code; #ifndef __NUITKA_NO_ASSERT__ result->m_constant_return_value = NULL; #endif } else { result->m_c_code = _Nuitka_FunctionEmptyCodeNoneImpl; result->m_constant_return_value = Py_None; } Py_INCREF(name); result->m_name = name; #if PYTHON_VERSION >= 0x300 // The "qualname" defaults to NULL for most compact C code. if (qualname == NULL) { qualname = name; } CHECK_OBJECT(qualname); Py_INCREF(qualname); result->m_qualname = qualname; #endif if (defaults == NULL) { Py_INCREF(Py_None); defaults = Py_None; } CHECK_OBJECT(defaults); assert(defaults == Py_None || (PyTuple_Check(defaults) && PyTuple_GET_SIZE(defaults) > 0)); result->m_defaults = defaults; onUpdatedDefaultsValue(result); #if PYTHON_VERSION >= 0x300 assert(kwdefaults == NULL || (PyDict_Check(kwdefaults) && DICT_SIZE(kwdefaults) > 0)); result->m_kwdefaults = kwdefaults; assert(annotations == NULL || (PyDict_Check(annotations) && DICT_SIZE(annotations) > 0)); result->m_annotations = annotations; #endif result->m_code_object = code_object; result->m_args_positional_count = code_object->co_argcount; result->m_args_keywords_count = result->m_args_positional_count; #if PYTHON_VERSION >= 0x300 result->m_args_keywords_count += code_object->co_kwonlyargcount; #endif #if PYTHON_VERSION >= 0x380 result->m_args_pos_only_count = code_object->co_posonlyargcount; #endif result->m_args_overall_count = result->m_args_keywords_count + ((code_object->co_flags & CO_VARARGS) ? 1 : 0) + ((code_object->co_flags & CO_VARKEYWORDS) ? 1 : 0); result->m_args_simple = (code_object->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) == 0; #if PYTHON_VERSION >= 0x300 if (code_object->co_kwonlyargcount > 0) { result->m_args_simple = false; } #endif if ((code_object->co_flags & CO_VARARGS) != 0) { result->m_args_star_list_index = result->m_args_keywords_count; } else { result->m_args_star_list_index = -1; } if ((code_object->co_flags & CO_VARKEYWORDS) != 0) { result->m_args_star_dict_index = result->m_args_keywords_count; if (code_object->co_flags & CO_VARARGS) { result->m_args_star_dict_index += 1; } } else { result->m_args_star_dict_index = -1; } result->m_varnames = &PyTuple_GET_ITEM(code_object->co_varnames, 0); result->m_module = module; Py_XINCREF(doc); result->m_doc = doc; result->m_dict = NULL; result->m_weakrefs = NULL; static long Nuitka_Function_counter = 0; result->m_counter = Nuitka_Function_counter++; #if PYTHON_VERSION >= 0x380 result->m_vectorcall = (vectorcallfunc)Nuitka_Function_tp_vectorcall; #endif Nuitka_GC_Track(result); assert(Py_REFCNT(result) == 1); return result; } #if PYTHON_VERSION >= 0x300 static void formatErrorNoArgumentAllowedKwSplit(struct Nuitka_FunctionObject const *function, PyObject *kw_name, Py_ssize_t given) { #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_AsString(kw_name)); } #endif static void formatErrorNoArgumentAllowed(struct Nuitka_FunctionObject const *function, #if PYTHON_VERSION >= 0x300 PyObject *kw, #endif Py_ssize_t given) { #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "%s() takes no arguments (%zd given)", function_name, given); #else if (kw == NULL) { PyErr_Format(PyExc_TypeError, "%s() takes 0 positional arguments but %zd was given", function_name, given); } else { PyObject *tmp_iter = PyObject_GetIter(kw); PyObject *tmp_arg_name = PyIter_Next(tmp_iter); Py_DECREF(tmp_iter); PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_AsString(tmp_arg_name)); Py_DECREF(tmp_arg_name); } #endif } static void formatErrorMultipleValuesGiven(struct Nuitka_FunctionObject const *function, Py_ssize_t index) { #if PYTHON_VERSION < 0x390 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x300 "%s() got multiple values for keyword argument '%s'", #else "%s() got multiple values for argument '%s'", #endif function_name, Nuitka_String_AsString(function->m_varnames[index])); } #if PYTHON_VERSION < 0x300 static void formatErrorTooFewArguments(struct Nuitka_FunctionObject const *function, #if PYTHON_VERSION < 0x270 Py_ssize_t kw_size, #endif Py_ssize_t given) { Py_ssize_t required_parameter_count = function->m_args_positional_count - function->m_defaults_given; #if PYTHON_VERSION < 0x390 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif char const *violation = (function->m_defaults != Py_None || function->m_args_star_list_index != -1) ? "at least" : "exactly"; char const *plural = required_parameter_count == 1 ? "" : "s"; #if PYTHON_VERSION < 0x270 if (kw_size > 0) { PyErr_Format(PyExc_TypeError, "%s() takes %s %zd non-keyword argument%s (%zd given)", function_name, violation, required_parameter_count, plural, given - function->m_defaults_given); } else { PyErr_Format(PyExc_TypeError, "%s() takes %s %zd argument%s (%zd given)", function_name, violation, required_parameter_count, plural, given); } #else PyErr_Format(PyExc_TypeError, "%s() takes %s %zd argument%s (%zd given)", function_name, violation, required_parameter_count, plural, given); #endif } #else static void formatErrorTooFewArguments(struct Nuitka_FunctionObject const *function, PyObject **values) { #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif Py_ssize_t max_missing = 0; for (Py_ssize_t i = function->m_args_positional_count - 1 - function->m_defaults_given; i >= 0; --i) { if (values[i] == NULL) { max_missing += 1; } } PyObject *list_str = PyUnicode_FromString(""); PyObject *comma_str = PyUnicode_FromString(", "); PyObject *and_str = PyUnicode_FromString(max_missing == 2 ? " and " : ", and "); Py_ssize_t missing = 0; for (Py_ssize_t i = function->m_args_positional_count - 1 - function->m_defaults_given; i >= 0; --i) { if (values[i] == NULL) { PyObject *current_str = function->m_varnames[i]; PyObject *current = PyObject_Repr(current_str); if (missing == 0) { PyObject *old = list_str; list_str = UNICODE_CONCAT(list_str, current); Py_DECREF(old); } else if (missing == 1) { PyObject *old = list_str; list_str = UNICODE_CONCAT(and_str, list_str); Py_DECREF(old); old = list_str; list_str = UNICODE_CONCAT(current, list_str); Py_DECREF(old); } else { PyObject *old = list_str; list_str = UNICODE_CONCAT(comma_str, list_str); Py_DECREF(old); old = list_str; list_str = UNICODE_CONCAT(current, list_str); Py_DECREF(old); } Py_DECREF(current); missing += 1; } } Py_DECREF(comma_str); Py_DECREF(and_str); PyErr_Format(PyExc_TypeError, "%s() missing %zd required positional argument%s: %s", function_name, max_missing, max_missing > 1 ? "s" : "", Nuitka_String_AsString(list_str)); Py_DECREF(list_str); } #endif static void formatErrorTooManyArguments(struct Nuitka_FunctionObject const *function, Py_ssize_t given #if PYTHON_VERSION < 0x270 , Py_ssize_t kw_size #endif #if PYTHON_VERSION >= 0x300 , Py_ssize_t kw_only #endif ) { Py_ssize_t top_level_parameter_count = function->m_args_positional_count; #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif #if PYTHON_VERSION < 0x300 char const *violation = function->m_defaults != Py_None ? "at most" : "exactly"; #endif char const *plural = top_level_parameter_count == 1 ? "" : "s"; #if PYTHON_VERSION < 0x270 PyErr_Format(PyExc_TypeError, "%s() takes %s %zd %sargument%s (%zd given)", function_name, violation, top_level_parameter_count, kw_size > 0 ? "non-keyword " : "", plural, given); #elif PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "%s() takes %s %zd argument%s (%zd given)", function_name, violation, top_level_parameter_count, plural, given); #else char keyword_only_part[100]; if (kw_only > 0) { snprintf(keyword_only_part, sizeof(keyword_only_part) - 1, " positional argument%s (and %" PY_FORMAT_SIZE_T "d keyword-only argument%s)", given != 1 ? "s" : "", kw_only, kw_only != 1 ? "s" : ""); } else { keyword_only_part[0] = 0; } if (function->m_defaults_given == 0) { PyErr_Format(PyExc_TypeError, "%s() takes %zd positional argument%s but %zd%s were given", function_name, top_level_parameter_count, plural, given, keyword_only_part); } else { PyErr_Format(PyExc_TypeError, "%s() takes from %zd to %zd positional argument%s but %zd%s were given", function_name, top_level_parameter_count - function->m_defaults_given, top_level_parameter_count, plural, given, keyword_only_part); } #endif } #if PYTHON_VERSION >= 0x300 static void formatErrorTooFewKwOnlyArguments(struct Nuitka_FunctionObject const *function, PyObject **kw_vars) { #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif Py_ssize_t kwonlyargcount = function->m_code_object->co_kwonlyargcount; Py_ssize_t max_missing = 0; for (Py_ssize_t i = kwonlyargcount - 1; i >= 0; --i) { if (kw_vars[i] == NULL) { max_missing += 1; } } PyObject *list_str = PyUnicode_FromString(""); PyObject *comma_str = PyUnicode_FromString(", "); PyObject *and_str = PyUnicode_FromString(max_missing == 2 ? " and " : ", and "); Py_ssize_t missing = 0; for (Py_ssize_t i = kwonlyargcount - 1; i >= 0; --i) { if (kw_vars[i] == NULL) { PyObject *current_str = function->m_varnames[function->m_args_positional_count + i]; PyObject *current = PyObject_Repr(current_str); if (missing == 0) { PyObject *old = list_str; list_str = UNICODE_CONCAT(list_str, current); Py_DECREF(old); } else if (missing == 1) { PyObject *old = list_str; list_str = UNICODE_CONCAT(and_str, list_str); Py_DECREF(old); old = list_str; list_str = UNICODE_CONCAT(current, list_str); Py_DECREF(old); } else { PyObject *old = list_str; list_str = UNICODE_CONCAT(comma_str, list_str); Py_DECREF(old); old = list_str; list_str = UNICODE_CONCAT(current, list_str); Py_DECREF(old); } Py_DECREF(current); missing += 1; } } Py_DECREF(comma_str); Py_DECREF(and_str); PyErr_Format(PyExc_TypeError, "%s() missing %zd required keyword-only argument%s: %s", function_name, max_missing, max_missing > 1 ? "s" : "", Nuitka_String_AsString(list_str)); Py_DECREF(list_str); } #endif static void formatErrorKeywordsMustBeString(struct Nuitka_FunctionObject const *function) { #if PYTHON_VERSION < 0x390 char const *function_name = Nuitka_String_AsString(function->m_name); SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() keywords must be strings", function_name); #else SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "keywords must be strings"); #endif } static inline bool checkKeywordType(PyObject *arg_name) { #if PYTHON_VERSION < 0x300 return (PyString_Check(arg_name) || PyUnicode_Check(arg_name)); #else return PyUnicode_Check(arg_name); #endif } #if PYTHON_VERSION < 0x300 static Py_ssize_t handleKeywordArgs(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *kw) #else static Py_ssize_t handleKeywordArgs(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *kw) #endif { Py_ssize_t keywords_count = function->m_args_keywords_count; #if PYTHON_VERSION >= 0x300 Py_ssize_t keyword_after_index = function->m_args_positional_count; #endif assert(function->m_args_star_dict_index == -1); Py_ssize_t kw_found = 0; Py_ssize_t ppos = 0; PyObject *key, *value; while (PyDict_Next(kw, &ppos, &key, &value)) { if (unlikely(!checkKeywordType(key))) { formatErrorKeywordsMustBeString(function); return -1; } NUITKA_MAY_BE_UNUSED bool found = false; Py_INCREF(key); Py_INCREF(value); #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { if (function->m_varnames[i] == key) { assert(python_pars[i] == NULL); python_pars[i] = value; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif found = true; break; } } if (found == false) { PyObject **varnames = function->m_varnames; for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { assert(python_pars[i] == NULL); python_pars[i] = value; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif found = true; break; } } } if (unlikely(found == false)) { bool pos_only_error = false; for (Py_ssize_t i = 0; i < kw_arg_start; i++) { PyObject **varnames = function->m_varnames; if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { pos_only_error = true; break; } } #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif if (pos_only_error == true) { PyErr_Format(PyExc_TypeError, "%s() got some positional-only arguments passed as keyword arguments: '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } else { PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } Py_DECREF(key); Py_DECREF(value); return -1; } Py_DECREF(key); kw_found += 1; } return kw_found; } #if PYTHON_VERSION < 0x300 static Py_ssize_t handleKeywordArgsSplit(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *kw_values, PyObject *kw_names) #else static Py_ssize_t handleKeywordArgsSplit(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *const *kw_values, PyObject *kw_names) #endif { Py_ssize_t keywords_count = function->m_args_keywords_count; #if PYTHON_VERSION >= 0x300 Py_ssize_t keyword_after_index = function->m_args_positional_count; #endif assert(function->m_args_star_dict_index == -1); Py_ssize_t kw_found = 0; Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); for (Py_ssize_t kw_index = 0; kw_index < nkwargs; kw_index++) { PyObject *key = PyTuple_GET_ITEM(kw_names, kw_index); PyObject *value = kw_values[kw_index]; assert(checkKeywordType(key)); NUITKA_MAY_BE_UNUSED bool found = false; #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif Py_INCREF(value); for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { if (function->m_varnames[i] == key) { assert(python_pars[i] == NULL); python_pars[i] = value; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif found = true; break; } } if (found == false) { PyObject **varnames = function->m_varnames; for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { // TODO: Could do better here, STR/UNICODE key knowledge being there. if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { assert(python_pars[i] == NULL); python_pars[i] = value; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif found = true; break; } } } if (unlikely(found == false)) { bool pos_only_error = false; for (Py_ssize_t i = 0; i < kw_arg_start; i++) { PyObject **varnames = function->m_varnames; if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { pos_only_error = true; break; } } #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif if (pos_only_error == true) { PyErr_Format(PyExc_TypeError, "%s() got some positional-only arguments passed as keyword arguments: '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } else { PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } Py_DECREF(value); return -1; } kw_found += 1; } return kw_found; } static bool MAKE_STAR_DICT_DICTIONARY_COPY(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *kw) { Py_ssize_t star_dict_index = function->m_args_star_dict_index; assert(star_dict_index != -1); if (kw == NULL) { python_pars[star_dict_index] = PyDict_New(); } else if (((PyDictObject *)kw)->ma_used > 0) { #if PYTHON_VERSION < 0x300 python_pars[star_dict_index] = _PyDict_NewPresized(((PyDictObject *)kw)->ma_used); for (int i = 0; i <= ((PyDictObject *)kw)->ma_mask; i++) { PyDictEntry *entry = &((PyDictObject *)kw)->ma_table[i]; if (entry->me_value != NULL) { if (unlikely(!checkKeywordType(entry->me_key))) { formatErrorKeywordsMustBeString(function); return false; } int res = PyDict_SetItem(python_pars[star_dict_index], entry->me_key, entry->me_value); if (unlikely(res != 0)) { return false; } } } #else if (_PyDict_HasSplitTable((PyDictObject *)kw)) { PyDictObject *mp = (PyDictObject *)kw; PyObject **newvalues = PyMem_NEW(PyObject *, mp->ma_keys->dk_size); assert(newvalues != NULL); PyDictObject *split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type); assert(split_copy != NULL); split_copy->ma_values = newvalues; split_copy->ma_keys = mp->ma_keys; split_copy->ma_used = mp->ma_used; mp->ma_keys->dk_refcnt += 1; Nuitka_GC_Track(split_copy); #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = DK_USABLE_FRACTION(DK_SIZE(mp->ma_keys)); #endif for (Py_ssize_t i = 0; i < size; i++) { #if PYTHON_VERSION < 0x360 PyDictKeyEntry *entry = &split_copy->ma_keys->dk_entries[i]; #else PyDictKeyEntry *entry = &DK_ENTRIES(split_copy->ma_keys)[i]; #endif if ((entry->me_key != NULL) && unlikely(!checkKeywordType(entry->me_key))) { formatErrorKeywordsMustBeString(function); return false; } split_copy->ma_values[i] = mp->ma_values[i]; Py_XINCREF(split_copy->ma_values[i]); } python_pars[star_dict_index] = (PyObject *)split_copy; } else { python_pars[star_dict_index] = PyDict_New(); PyDictObject *mp = (PyDictObject *)kw; #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = mp->ma_keys->dk_nentries; #endif for (Py_ssize_t i = 0; i < size; i++) { #if PYTHON_VERSION < 0x360 PyDictKeyEntry *entry = &mp->ma_keys->dk_entries[i]; #else PyDictKeyEntry *entry = &DK_ENTRIES(mp->ma_keys)[i]; #endif PyObject *value = entry->me_value; if (value != NULL) { if (unlikely(!checkKeywordType(entry->me_key))) { formatErrorKeywordsMustBeString(function); return false; } int res = PyDict_SetItem(python_pars[star_dict_index], entry->me_key, value); if (unlikely(res != 0)) { return false; } } } } #endif } else { python_pars[star_dict_index] = PyDict_New(); } return true; } #if PYTHON_VERSION < 0x300 static Py_ssize_t handleKeywordArgsWithStarDict(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *kw) #else static Py_ssize_t handleKeywordArgsWithStarDict(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *kw) #endif { assert(function->m_args_star_dict_index != -1); if (unlikely(MAKE_STAR_DICT_DICTIONARY_COPY(function, python_pars, kw) == false)) { return -1; } Py_ssize_t kw_found = 0; Py_ssize_t keywords_count = function->m_args_keywords_count; #if PYTHON_VERSION >= 0x300 Py_ssize_t keyword_after_index = function->m_args_positional_count; #endif Py_ssize_t star_dict_index = function->m_args_star_dict_index; PyObject **varnames = function->m_varnames; #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { PyObject *arg_name = varnames[i]; PyObject *kw_arg_value = DICT_GET_ITEM1(python_pars[star_dict_index], arg_name); if (kw_arg_value != NULL) { assert(python_pars[i] == NULL); python_pars[i] = kw_arg_value; PyDict_DelItem(python_pars[star_dict_index], arg_name); kw_found += 1; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif } } return kw_found; } #if PYTHON_VERSION < 0x300 static Py_ssize_t handleKeywordArgsSplitWithStarDict(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *kw_values, PyObject *kw_names) #else static Py_ssize_t handleKeywordArgsSplitWithStarDict(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *const *kw_values, PyObject *kw_names) #endif { Py_ssize_t star_dict_index = function->m_args_star_dict_index; assert(star_dict_index != -1); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); python_pars[star_dict_index] = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; PyDict_SetItem(python_pars[star_dict_index], key, value); } Py_ssize_t kw_found = 0; Py_ssize_t keywords_count = function->m_args_keywords_count; #if PYTHON_VERSION >= 0x300 Py_ssize_t keyword_after_index = function->m_args_positional_count; #endif PyObject **varnames = function->m_varnames; #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { PyObject *arg_name = varnames[i]; PyObject *kw_arg_value = DICT_GET_ITEM1(python_pars[star_dict_index], arg_name); if (kw_arg_value != NULL) { assert(python_pars[i] == NULL); python_pars[i] = kw_arg_value; PyDict_DelItem(python_pars[star_dict_index], arg_name); kw_found += 1; #if PYTHON_VERSION >= 0x300 if (i >= keyword_after_index) { *kw_only_found += 1; } #endif } } return kw_found; } static void makeStarListTupleCopy(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size) { assert(function->m_args_star_list_index != -1); Py_ssize_t list_star_index = function->m_args_star_list_index; // Copy left-over argument values to the star list parameter given. if (args_size > function->m_args_positional_count) { python_pars[list_star_index] = PyTuple_New(args_size - function->m_args_positional_count); for (Py_ssize_t i = 0; i < args_size - function->m_args_positional_count; i++) { PyObject *value = args[function->m_args_positional_count + i]; PyTuple_SET_ITEM(python_pars[list_star_index], i, value); Py_INCREF(value); } } else { python_pars[list_star_index] = const_tuple_empty; Py_INCREF(const_tuple_empty); } } static void makeStarListTupleCopyMethod(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size) { assert(function->m_args_star_list_index != -1); Py_ssize_t list_star_index = function->m_args_star_list_index; // Copy left-over argument values to the star list parameter given. if (args_size + 1 > function->m_args_positional_count) { python_pars[list_star_index] = PyTuple_New(args_size + 1 - function->m_args_positional_count); for (Py_ssize_t i = 0; i < args_size + 1 - function->m_args_positional_count; i++) { PyObject *value = args[function->m_args_positional_count + i - 1]; PyTuple_SET_ITEM(python_pars[list_star_index], i, value); Py_INCREF(value); } } else { python_pars[list_star_index] = const_tuple_empty; Py_INCREF(const_tuple_empty); } } static bool _handleArgumentsPlainOnly(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size) { Py_ssize_t arg_count = function->m_args_positional_count; // Check if too many arguments were given in case of non list star arg. // For Python3.3 it's done only later, when more knowledge has // been gained. TODO: Could be done this way for improved mode // on all versions. #if PYTHON_VERSION < 0x300 if (function->m_args_star_list_index == -1) { if (unlikely(args_size > arg_count)) { #if PYTHON_VERSION < 0x270 formatErrorTooManyArguments(function, args_size, 0); #else formatErrorTooManyArguments(function, args_size); #endif return false; } } #endif #if PYTHON_VERSION >= 0x300 bool parameter_error = false; #endif Py_ssize_t defaults_given = function->m_defaults_given; if (args_size + defaults_given < arg_count) { #if PYTHON_VERSION < 0x270 formatErrorTooFewArguments(function, 0, args_size); return false; #elif PYTHON_VERSION < 0x300 formatErrorTooFewArguments(function, args_size); return false; #else parameter_error = true; #endif } for (Py_ssize_t i = 0; i < args_size; i++) { if (i >= arg_count) break; assert(python_pars[i] == NULL); python_pars[i] = args[i]; Py_INCREF(python_pars[i]); } #if PYTHON_VERSION >= 0x300 if (parameter_error == false) { #endif PyObject *source = function->m_defaults; for (Py_ssize_t i = args_size; i < arg_count; i++) { assert(python_pars[i] == NULL); assert(i + defaults_given >= arg_count); python_pars[i] = PyTuple_GET_ITEM(source, defaults_given + i - arg_count); Py_INCREF(python_pars[i]); } #if PYTHON_VERSION >= 0x300 } #endif #if PYTHON_VERSION >= 0x300 if (unlikely(parameter_error)) { formatErrorTooFewArguments(function, python_pars); return false; } if (function->m_args_star_list_index == -1) { // Check if too many arguments were given in case of non list star arg if (unlikely(args_size > arg_count)) { formatErrorTooManyArguments(function, args_size, 0); return false; } } #endif if (function->m_args_star_list_index != -1) { makeStarListTupleCopy(function, python_pars, args, args_size); } return true; } static bool handleMethodArgumentsPlainOnly(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *object, PyObject *const *args, Py_ssize_t args_size) { Py_ssize_t arg_count = function->m_args_positional_count; // There may be no self, otherwise we can directly assign it. if (arg_count >= 1) { python_pars[0] = object; Py_INCREF(object); } else { // Without self, there can only be star list to get the object as its // first element. Or we complain about illegal arguments. if (function->m_args_star_list_index == 0) { python_pars[0] = PyTuple_New(args_size + 1); PyTuple_SET_ITEM(python_pars[0], 0, object); Py_INCREF(object); for (Py_ssize_t i = 0; i < args_size; i++) { PyTuple_SET_ITEM(python_pars[0], i + 1, args[i]); Py_INCREF(args[i]); } return true; } } // Check if too many arguments were given in case of non list star arg. // For Python3.3 it's done only later, when more knowledge has // been gained. TODO: Could be done this way for improved mode // on all versions. #if PYTHON_VERSION < 0x300 if (function->m_args_star_list_index == -1) { if (unlikely(args_size + 1 > arg_count)) { #if PYTHON_VERSION < 0x270 formatErrorTooManyArguments(function, args_size + 1, 0); #else formatErrorTooManyArguments(function, args_size + 1); #endif return false; } } #endif #if PYTHON_VERSION >= 0x300 bool parameter_error = false; #endif Py_ssize_t defaults_given = function->m_defaults_given; if (args_size + 1 + defaults_given < arg_count) { #if PYTHON_VERSION < 0x270 formatErrorTooFewArguments(function, 0, args_size + 1); return false; #elif PYTHON_VERSION < 0x300 formatErrorTooFewArguments(function, args_size + 1); return false; #else parameter_error = true; #endif } for (Py_ssize_t i = 0; i < args_size; i++) { if (i + 1 >= arg_count) break; assert(python_pars[i + 1] == NULL); python_pars[i + 1] = args[i]; Py_INCREF(python_pars[i + 1]); } #if PYTHON_VERSION >= 0x300 if (parameter_error == false) { #endif for (Py_ssize_t i = args_size + 1; i < arg_count; i++) { assert(python_pars[i] == NULL); assert(i + defaults_given >= arg_count); python_pars[i] = PyTuple_GET_ITEM(function->m_defaults, defaults_given + i - arg_count); Py_INCREF(python_pars[i]); } #if PYTHON_VERSION >= 0x300 } #endif #if PYTHON_VERSION >= 0x300 if (unlikely(parameter_error)) { formatErrorTooFewArguments(function, python_pars); return false; } if (function->m_args_star_list_index == -1) { // Check if too many arguments were given in case of non list star arg if (unlikely(args_size + 1 > arg_count)) { formatErrorTooManyArguments(function, args_size + 1, 0); return false; } } #endif if (function->m_args_star_list_index != -1) { makeStarListTupleCopyMethod(function, python_pars, args, args_size); } return true; } #if PYTHON_VERSION < 0x270 static bool _handleArgumentsPlain(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, Py_ssize_t kw_found, Py_ssize_t kw_size) #elif PYTHON_VERSION < 0x300 static bool _handleArgumentsPlain(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, Py_ssize_t kw_found) #else static bool _handleArgumentsPlain(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, Py_ssize_t kw_found, Py_ssize_t kw_only_found) #endif { Py_ssize_t arg_count = function->m_args_positional_count; // Check if too many arguments were given in case of non list star arg. // For Python3.3 it's done only later, when more knowledge has // been gained. TODO: Could be done this way for improved mode // on all versions. #if PYTHON_VERSION < 0x300 if (function->m_args_star_list_index == -1) { if (unlikely(args_size > arg_count)) { #if PYTHON_VERSION < 0x270 formatErrorTooManyArguments(function, args_size, kw_size); #else formatErrorTooManyArguments(function, args_size + kw_found); #endif return false; } } #endif #if PYTHON_VERSION >= 0x300 bool parameter_error = false; #endif if (kw_found > 0) { Py_ssize_t i; for (i = 0; i < (args_size < arg_count ? args_size : arg_count); i++) { if (unlikely(python_pars[i] != NULL)) { formatErrorMultipleValuesGiven(function, i); return false; } python_pars[i] = args[i]; Py_INCREF(python_pars[i]); } Py_ssize_t defaults_given = function->m_defaults_given; for (; i < arg_count; i++) { if (python_pars[i] == NULL) { if (i + defaults_given >= arg_count) { python_pars[i] = PyTuple_GET_ITEM(function->m_defaults, defaults_given + i - arg_count); Py_INCREF(python_pars[i]); } else { #if PYTHON_VERSION < 0x270 formatErrorTooFewArguments(function, kw_size, args_size + kw_found); return false; #elif PYTHON_VERSION < 0x300 formatErrorTooFewArguments(function, args_size + kw_found); return false; #else parameter_error = true; #endif } } } } else { Py_ssize_t usable = (args_size < arg_count ? args_size : arg_count); Py_ssize_t defaults_given = function->m_defaults_given; if (defaults_given < arg_count - usable) { #if PYTHON_VERSION < 0x270 formatErrorTooFewArguments(function, kw_size, args_size + kw_found); return false; #elif PYTHON_VERSION < 0x300 formatErrorTooFewArguments(function, args_size + kw_found); return false; #else parameter_error = true; #endif } for (Py_ssize_t i = 0; i < usable; i++) { assert(python_pars[i] == NULL); python_pars[i] = args[i]; Py_INCREF(python_pars[i]); } #if PYTHON_VERSION >= 0x300 if (parameter_error == false) { #endif for (Py_ssize_t i = usable; i < arg_count; i++) { assert(python_pars[i] == NULL); assert(i + defaults_given >= arg_count); python_pars[i] = PyTuple_GET_ITEM(function->m_defaults, defaults_given + i - arg_count); Py_INCREF(python_pars[i]); } #if PYTHON_VERSION >= 0x300 } #endif } #if PYTHON_VERSION >= 0x300 if (unlikely(parameter_error)) { formatErrorTooFewArguments(function, python_pars); return false; } if (function->m_args_star_list_index == -1) { // Check if too many arguments were given in case of non list star arg if (unlikely(args_size > arg_count)) { formatErrorTooManyArguments(function, args_size, kw_only_found); return false; } } #endif if (function->m_args_star_list_index != -1) { makeStarListTupleCopy(function, python_pars, args, args_size); } return true; } // Release them all in case of an error. static void releaseParameters(struct Nuitka_FunctionObject const *function, PyObject *const *python_pars) { Py_ssize_t arg_count = function->m_args_overall_count; for (Py_ssize_t i = 0; i < arg_count; i++) { Py_XDECREF(python_pars[i]); } } static bool parseArgumentsPos(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size) { bool result; Py_ssize_t arg_count = function->m_args_positional_count; if (unlikely(arg_count == 0 && function->m_args_simple && args_size != 0)) { #if PYTHON_VERSION < 0x300 formatErrorNoArgumentAllowed(function, args_size); #else formatErrorNoArgumentAllowed(function, NULL, args_size); #endif releaseParameters(function, python_pars); return false; } result = _handleArgumentsPlainOnly(function, python_pars, args, args_size); if (result == false) { releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 // For Python3.3 the keyword only errors are all reported at once. bool kw_only_error = false; for (Py_ssize_t i = function->m_args_positional_count; i < function->m_args_keywords_count; i++) { if (python_pars[i] == NULL) { PyObject *arg_name = function->m_varnames[i]; if (function->m_kwdefaults != NULL) { python_pars[i] = DICT_GET_ITEM1(function->m_kwdefaults, arg_name); } if (unlikely(python_pars[i] == NULL)) { kw_only_error = true; } } } if (unlikely(kw_only_error)) { formatErrorTooFewKwOnlyArguments(function, &python_pars[function->m_args_positional_count]); releaseParameters(function, python_pars); return false; } #endif if (function->m_args_star_dict_index != -1) { python_pars[function->m_args_star_dict_index] = PyDict_New(); } return true; } // We leave it to partial inlining to specialize this. static bool parseArgumentsEmpty(struct Nuitka_FunctionObject const *function, PyObject **python_pars) { return parseArgumentsPos(function, python_pars, NULL, 0); } static bool parseArgumentsMethodPos(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *object, PyObject *const *args, Py_ssize_t args_size) { bool result; result = handleMethodArgumentsPlainOnly(function, python_pars, object, args, args_size); if (result == false) { releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 // For Python3 the keyword only errors are all reported at once. bool kw_only_error = false; for (Py_ssize_t i = function->m_args_positional_count; i < function->m_args_keywords_count; i++) { if (python_pars[i] == NULL) { PyObject *arg_name = function->m_varnames[i]; if (function->m_kwdefaults != NULL) { python_pars[i] = DICT_GET_ITEM1(function->m_kwdefaults, arg_name); } if (unlikely(python_pars[i] == NULL)) { kw_only_error = true; } } } if (unlikely(kw_only_error)) { formatErrorTooFewKwOnlyArguments(function, &python_pars[function->m_args_positional_count]); releaseParameters(function, python_pars); return false; } #endif if (function->m_args_star_dict_index != -1) { python_pars[function->m_args_star_dict_index] = PyDict_New(); } return true; } static bool parseArgumentsFullKwSplit(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_values, PyObject *kw_names) { Py_ssize_t kw_size = PyTuple_GET_SIZE(kw_names); Py_ssize_t kw_found; bool result; Py_ssize_t arg_count = function->m_args_keywords_count; if (unlikely(arg_count == 0 && function->m_args_simple && args_size + kw_size > 0)) { #if PYTHON_VERSION < 0x300 formatErrorNoArgumentAllowed(function, args_size + kw_size); #else formatErrorNoArgumentAllowedKwSplit(function, PyTuple_GET_ITEM(kw_names, 0), args_size); #endif releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 Py_ssize_t kw_only_found = 0; #endif if (function->m_args_star_dict_index != -1) { #if PYTHON_VERSION < 0x300 kw_found = handleKeywordArgsSplitWithStarDict(function, python_pars, kw_values, kw_names); #else kw_found = handleKeywordArgsSplitWithStarDict(function, python_pars, &kw_only_found, kw_values, kw_names); #endif if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } else { #if PYTHON_VERSION < 0x300 kw_found = handleKeywordArgsSplit(function, python_pars, kw_values, kw_names); #else kw_found = handleKeywordArgsSplit(function, python_pars, &kw_only_found, kw_values, kw_names); #endif if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } #if PYTHON_VERSION < 0x270 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_size); #elif PYTHON_VERSION < 0x300 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found); #else result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_only_found); #endif if (result == false) { releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 // For Python3.3 the keyword only errors are all reported at once. bool kw_only_error = false; for (Py_ssize_t i = function->m_args_positional_count; i < function->m_args_keywords_count; i++) { if (python_pars[i] == NULL) { PyObject *arg_name = function->m_varnames[i]; if (function->m_kwdefaults != NULL) { python_pars[i] = DICT_GET_ITEM1(function->m_kwdefaults, arg_name); } if (unlikely(python_pars[i] == NULL)) { kw_only_error = true; } } } if (unlikely(kw_only_error)) { formatErrorTooFewKwOnlyArguments(function, &python_pars[function->m_args_positional_count]); releaseParameters(function, python_pars); return false; } #endif return true; } static bool parseArgumentsFull(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, PyObject *kw) { Py_ssize_t kw_size = kw ? DICT_SIZE(kw) : 0; Py_ssize_t kw_found; bool result; Py_ssize_t arg_count = function->m_args_keywords_count; assert(kw == NULL || PyDict_CheckExact(kw)); if (unlikely(arg_count == 0 && function->m_args_simple && args_size + kw_size > 0)) { #if PYTHON_VERSION < 0x300 formatErrorNoArgumentAllowed(function, args_size + kw_size); #else formatErrorNoArgumentAllowed(function, kw_size > 0 ? kw : NULL, args_size); #endif releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 Py_ssize_t kw_only_found = 0; #endif if (function->m_args_star_dict_index != -1) { #if PYTHON_VERSION < 0x300 kw_found = handleKeywordArgsWithStarDict(function, python_pars, kw); #else kw_found = handleKeywordArgsWithStarDict(function, python_pars, &kw_only_found, kw); #endif if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } else if (kw == NULL || DICT_SIZE(kw) == 0) { kw_found = 0; } else { #if PYTHON_VERSION < 0x300 kw_found = handleKeywordArgs(function, python_pars, kw); #else kw_found = handleKeywordArgs(function, python_pars, &kw_only_found, kw); #endif if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } #if PYTHON_VERSION < 0x270 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_size); #elif PYTHON_VERSION < 0x300 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found); #else result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_only_found); #endif if (result == false) { releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 // For Python3.3 the keyword only errors are all reported at once. bool kw_only_error = false; for (Py_ssize_t i = function->m_args_positional_count; i < function->m_args_keywords_count; i++) { if (python_pars[i] == NULL) { PyObject *arg_name = function->m_varnames[i]; if (function->m_kwdefaults != NULL) { python_pars[i] = DICT_GET_ITEM1(function->m_kwdefaults, arg_name); } if (unlikely(python_pars[i] == NULL)) { kw_only_error = true; } } } if (unlikely(kw_only_error)) { formatErrorTooFewKwOnlyArguments(function, &python_pars[function->m_args_positional_count]); releaseParameters(function, python_pars); return false; } #endif return true; } PyObject *Nuitka_CallFunctionNoArgs(struct Nuitka_FunctionObject const *function) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsEmpty(function, python_pars))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallFunctionPosArgs(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsPos(function, python_pars, args, args_size))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallFunctionPosArgsKwArgs(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *kw) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsFull(function, python_pars, args, args_size, kw))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallFunctionPosArgsKwSplit(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_values, PyObject *kw_names) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsFullKwSplit(function, python_pars, args, args_size, kw_values, kw_names))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallMethodFunctionNoArgs(struct Nuitka_FunctionObject const *function, PyObject *object) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsMethodPos(function, python_pars, object, NULL, 0))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallMethodFunctionPosArgs(struct Nuitka_FunctionObject const *function, PyObject *object, PyObject *const *args, Py_ssize_t args_size) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsMethodPos(function, python_pars, object, args, args_size))) { return NULL; } return function->m_c_code(function, python_pars); } PyObject *Nuitka_CallMethodFunctionPosArgsKwArgs(struct Nuitka_FunctionObject const *function, PyObject *object, PyObject *const *args, Py_ssize_t args_size, PyObject *kw) { NUITKA_DYNAMIC_ARRAY_DECL(new_args, PyObject *, args_size + 1); new_args[0] = object; memcpy(new_args + 1, args, args_size * sizeof(PyObject *)); // TODO: Specialize implementation for massive gains. return Nuitka_CallFunctionPosArgsKwArgs(function, new_args, args_size + 1, kw); } static Py_ssize_t handleVectorcallKeywordArgs(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *const *kw_names, PyObject *const *kw_values, Py_ssize_t kw_size) { Py_ssize_t keywords_count = function->m_args_keywords_count; Py_ssize_t keyword_after_index = function->m_args_positional_count; assert(function->m_args_star_dict_index == -1); Py_ssize_t kw_found = 0; for (Py_ssize_t ppos = 0; ppos < kw_size; ppos++) { PyObject *key = kw_names[ppos]; if (unlikely(!checkKeywordType(key))) { formatErrorKeywordsMustBeString(function); return -1; } NUITKA_MAY_BE_UNUSED bool found = false; #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { if (function->m_varnames[i] == key) { assert(python_pars[i] == NULL); python_pars[i] = kw_values[ppos]; Py_INCREF(python_pars[i]); if (i >= keyword_after_index) { *kw_only_found += 1; } found = true; break; } } if (found == false) { PyObject **varnames = function->m_varnames; for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { assert(python_pars[i] == NULL); python_pars[i] = kw_values[ppos]; Py_INCREF(python_pars[i]); if (i >= keyword_after_index) { *kw_only_found += 1; } found = true; break; } } } if (unlikely(found == false)) { bool pos_only_error = false; for (Py_ssize_t i = 0; i < kw_arg_start; i++) { PyObject **varnames = function->m_varnames; if (RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(varnames[i], key)) { pos_only_error = true; break; } } #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif if (pos_only_error == true) { PyErr_Format(PyExc_TypeError, "%s() got some positional-only arguments passed as keyword arguments: '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } else { PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_Check(key) ? Nuitka_String_AsString(key) : ""); } return -1; } kw_found += 1; } return kw_found; } static bool MAKE_STAR_DICT_DICTIONARY_COPY38(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *kw_names, PyObject *const *kw_values, Py_ssize_t kw_size) { Py_ssize_t star_dict_index = function->m_args_star_dict_index; assert(star_dict_index != -1); python_pars[star_dict_index] = _PyDict_NewPresized(kw_size); for (int i = 0; i < kw_size; i++) { PyObject *key = kw_names[i]; if (unlikely(!checkKeywordType(key))) { formatErrorKeywordsMustBeString(function); return false; } int res = PyDict_SetItem(python_pars[star_dict_index], key, kw_values[i]); if (unlikely(res != 0)) { return false; } } return true; } static Py_ssize_t handleVectorcallKeywordArgsWithStarDict(struct Nuitka_FunctionObject const *function, PyObject **python_pars, Py_ssize_t *kw_only_found, PyObject *const *kw_names, PyObject *const *kw_values, Py_ssize_t kw_size) { assert(function->m_args_star_dict_index != -1); if (unlikely(MAKE_STAR_DICT_DICTIONARY_COPY38(function, python_pars, kw_names, kw_values, kw_size) == false)) { return -1; } Py_ssize_t kw_found = 0; Py_ssize_t keywords_count = function->m_args_keywords_count; Py_ssize_t keyword_after_index = function->m_args_positional_count; Py_ssize_t star_dict_index = function->m_args_star_dict_index; PyObject **varnames = function->m_varnames; #if PYTHON_VERSION < 0x380 Py_ssize_t kw_arg_start = 0; #else Py_ssize_t kw_arg_start = function->m_args_pos_only_count; #endif for (Py_ssize_t i = kw_arg_start; i < keywords_count; i++) { PyObject *arg_name = varnames[i]; PyObject *kw_arg_value = DICT_GET_ITEM1(python_pars[star_dict_index], arg_name); if (kw_arg_value != NULL) { assert(python_pars[i] == NULL); python_pars[i] = kw_arg_value; PyDict_DelItem(python_pars[star_dict_index], arg_name); kw_found += 1; if (i >= keyword_after_index) { *kw_only_found += 1; } } } return kw_found; } static bool parseArgumentsVectorcall(struct Nuitka_FunctionObject const *function, PyObject **python_pars, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_names, Py_ssize_t kw_size) { Py_ssize_t kw_found; bool result; Py_ssize_t kw_only_found; Py_ssize_t arg_count = function->m_args_keywords_count; // TODO: Create different the vector call slot entries for different function types for extra // performance. if (unlikely(arg_count == 0 && function->m_args_simple && args_size + kw_size > 0)) { #if PYTHON_VERSION < 0x3a0 char const *function_name = Nuitka_String_AsString(function->m_name); #else char const *function_name = Nuitka_String_AsString(function->m_qualname); #endif if (kw_size == 0) { PyErr_Format(PyExc_TypeError, "%s() takes 0 positional arguments but %zd was given", function_name, args_size); } else { PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%s'", function_name, Nuitka_String_AsString(kw_names[0])); } releaseParameters(function, python_pars); return false; } kw_only_found = 0; if (function->m_args_star_dict_index != -1) { kw_found = handleVectorcallKeywordArgsWithStarDict(function, python_pars, &kw_only_found, kw_names, &args[args_size], kw_size); if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } else if (kw_size == 0) { kw_found = 0; } else { kw_found = handleVectorcallKeywordArgs(function, python_pars, &kw_only_found, kw_names, &args[args_size], kw_size); if (kw_found == -1) { releaseParameters(function, python_pars); return false; } } #if PYTHON_VERSION < 0x270 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_size); #elif PYTHON_VERSION < 0x300 result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found); #else result = _handleArgumentsPlain(function, python_pars, args, args_size, kw_found, kw_only_found); #endif if (result == false) { releaseParameters(function, python_pars); return false; } #if PYTHON_VERSION >= 0x300 // For Python3 the keyword only errors are all reported at once. bool kw_only_error = false; for (Py_ssize_t i = function->m_args_positional_count; i < function->m_args_keywords_count; i++) { if (python_pars[i] == NULL) { PyObject *arg_name = function->m_varnames[i]; if (function->m_kwdefaults != NULL) { python_pars[i] = DICT_GET_ITEM1(function->m_kwdefaults, arg_name); } if (unlikely(python_pars[i] == NULL)) { kw_only_error = true; } } } if (unlikely(kw_only_error)) { formatErrorTooFewKwOnlyArguments(function, &python_pars[function->m_args_positional_count]); releaseParameters(function, python_pars); return false; } #endif return true; } PyObject *Nuitka_CallFunctionVectorcall(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_names, Py_ssize_t kw_size) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (unlikely(!parseArgumentsVectorcall(function, python_pars, args, args_size, kw_names, kw_size))) { return NULL; } return function->m_c_code(function, python_pars); } static PyObject *Nuitka_Function_tp_call(struct Nuitka_FunctionObject *function, PyObject *tuple_args, PyObject *kw) { CHECK_OBJECT(tuple_args); assert(PyTuple_CheckExact(tuple_args)); if (kw == NULL) { PyObject **args = &PyTuple_GET_ITEM(tuple_args, 0); Py_ssize_t args_size = PyTuple_GET_SIZE(tuple_args); if (function->m_args_simple && args_size == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < args_size; i++) { Py_INCREF(args[i]); } return function->m_c_code(function, args); } else if (function->m_args_simple && args_size + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memcpy(python_pars, args, args_size * sizeof(PyObject *)); memcpy(python_pars + args_size, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } return function->m_c_code(function, python_pars); } else { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_overall_count); memset(python_pars, 0, function->m_args_overall_count * sizeof(PyObject *)); if (parseArgumentsPos(function, python_pars, args, args_size)) { return function->m_c_code(function, python_pars); } else { return NULL; } } } else { return Nuitka_CallFunctionPosArgsKwArgs(function, &PyTuple_GET_ITEM(tuple_args, 0), PyTuple_GET_SIZE(tuple_args), kw); } } #if PYTHON_VERSION >= 0x380 static PyObject *Nuitka_Function_tp_vectorcall(struct Nuitka_FunctionObject *function, PyObject *const *stack, size_t nargsf, PyObject *kwnames) { assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); assert((nargs == 0 && nkwargs == 0) || stack != NULL); return Nuitka_CallFunctionVectorcall(function, stack, nargs, kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs); } #endif #include "CompiledMethodType.c" #include "CompiledCodeHelpers.c"Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryMultUtils.c0000600000372100037210000000653414166627112033506 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* These slots are still manually coded and are used by the generated code. * * The plan should be to generate these as well, so e.g. we can have a slot * SLOT_nb_multiply_LONG_INT that is optimal too. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "longintrepr.h" static Py_ssize_t CONVERT_LONG_TO_REPEAT_FACTOR(PyObject *value) { /* Inline PyLong_AsSsize_t here for our special purpose. */ Py_ssize_t i = Py_SIZE(value); if (i == 0) { return 0; } PyLongObject *long_value = (PyLongObject *)value; if (i == 1) { return long_value->ob_digit[0]; } Py_ssize_t result = 0; bool is_negative = i < 0; if (is_negative) { i = -i; } while (--i >= 0) { Py_ssize_t prev = result; result = (result << PyLong_SHIFT) | long_value->ob_digit[i]; if ((result >> PyLong_SHIFT) != prev) { return (Py_ssize_t)-1; } } if (is_negative) { return 0; } else { return result; } } static Py_ssize_t CONVERT_TO_REPEAT_FACTOR(PyObject *value) { #if PYTHON_VERSION < 0x300 assert(PyInt_Check(value) || PyLong_Check(value)); if (PyInt_Check(value)) { Py_ssize_t result = PyInt_AS_LONG(value); /* A -1 value could indicate error, so we avoid it. */ if (result < 0) { return 0; } else { return result; } } else { return CONVERT_LONG_TO_REPEAT_FACTOR(value); } #else /* For Python3 we know for a fact that it's a long, or else it's an * exception. */ assert(PyLong_Check(value)); return CONVERT_LONG_TO_REPEAT_FACTOR(value); #endif } static PyObject *SEQUENCE_REPEAT(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n) { if (unlikely(!PyIndex_Check(n))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", Py_TYPE(n)->tp_name); return NULL; } PyObject *index_value = PyNumber_Index(n); if (unlikely(index_value == NULL)) { return NULL; } Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", Py_TYPE(n)->tp_name); return NULL; } PyObject *result = (*repeatfunc)(seq, count); if (unlikely(result == NULL)) { return NULL; } return result; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryTruediv.c0000600000372100037210000035640114166627112033167 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "/" (TRUEDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: Py_INCREF(const_float_minus_0_0); result = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: Py_INCREF(const_float_minus_0_0); result = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: Py_INCREF(const_float_minus_0_0); result = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } cbool_result = a == 0; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } cbool_result = a == 0; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } cbool_result = a == 0; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_true_divide(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_true_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_true_divide; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } if (a == 0) { if (b < 0) { goto exit_result_ok_const_float_minus_0_0; } else { goto exit_result_ok_const_float_0_0; } } /* May need to resort to LONG code, which we currently do not * specialize yet. TODO: Once we do that, call it here instead. */ #if DBL_MANT_DIG < WIDTH_OF_ULONG if ((a >= 0 ? 0UL + a : 0UL - a) >> DBL_MANT_DIG || (b >= 0 ? 0UL + b : 0UL - b) >> DBL_MANT_DIG) { } else #endif { double r = (double)a / (double)b; cfloat_result = r; goto exit_result_ok_cfloat; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_true_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_minus_0_0: Py_INCREF(const_float_minus_0_0); result = const_float_minus_0_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "division by zero"); goto exit_result_exception; } cbool_result = a == 0; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_true_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_true_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_true_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonEqUtils.c0000600000372100037210000001106414166627112032131 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For making rich comparisons work. * * Helpers that implement the details of comparisons for both Python2 and * Python3 individually, mostly because of the many changes. * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif python_initproc default_tp_init_wrapper; #if PYTHON_VERSION < 0x300 static cmpfunc default_tp_compare; #endif void _initSlotCompare() { // Create a class with "__cmp__" attribute, to get a hand at the default // implementation of tp_compare. It's not part of the API and with shared // libraries it's not accessible. The name does not matter, nor does the // actual value used for "__cmp__". // Use "int" as the base class. PyObject *pos_args = PyTuple_New(1); PyTuple_SET_ITEM(pos_args, 0, (PyObject *)&PyLong_Type); Py_INCREF(&PyLong_Type); // Use "__cmp__" with true value, won't matter. PyObject *kw_args = PyDict_New(); #if PYTHON_VERSION < 0x0300 PyDict_SetItem(kw_args, const_str_plain___cmp__, Py_True); #endif PyDict_SetItem(kw_args, const_str_plain___init__, (PyObject *)Py_TYPE(Py_None)); // Create the type. PyTypeObject *c = (PyTypeObject *)PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, const_str_plain___cmp__, pos_args, kw_args, NULL); Py_DECREF(pos_args); Py_DECREF(kw_args); CHECK_OBJECT(c); #if PYTHON_VERSION < 0x0300 assert(c->tp_compare); default_tp_compare = c->tp_compare; #endif assert(c->tp_init); default_tp_init_wrapper = c->tp_init; Py_DECREF(c); } #if PYTHON_VERSION < 0x300 static inline int adjust_tp_compare(int c) { if (ERROR_OCCURRED()) { return -2; } else if (c < -1 || c > 1) { return c < -1 ? -1 : 1; } else { return c; } } static inline int coerce_objects(PyObject **pa, PyObject **pb) { PyObject *a = *pa; PyObject *b = *pb; // Shortcut only for old-style types if (a->ob_type == b->ob_type && !PyType_HasFeature(a->ob_type, Py_TPFLAGS_CHECKTYPES)) { Py_INCREF(a); Py_INCREF(b); return 0; } if (a->ob_type->tp_as_number && a->ob_type->tp_as_number->nb_coerce) { int res = (*a->ob_type->tp_as_number->nb_coerce)(pa, pb); if (res <= 0) { return res; } } if (b->ob_type->tp_as_number && b->ob_type->tp_as_number->nb_coerce) { int res = (*b->ob_type->tp_as_number->nb_coerce)(pb, pa); if (res <= 0) { return res; } } return 1; } static int try_3way_compare(PyObject *a, PyObject *b) { cmpfunc f1 = a->ob_type->tp_compare; cmpfunc f2 = b->ob_type->tp_compare; int c; // Same compares, just use it. if (f1 != NULL && f1 == f2) { c = (*f1)(a, b); return adjust_tp_compare(c); } // If one slot is _PyObject_SlotCompare (which we got our hands on under a // different name in case it's a shared library), prefer it. if (f1 == default_tp_compare || f2 == default_tp_compare) { return default_tp_compare(a, b); } // Try coercion. c = coerce_objects(&a, &b); if (c < 0) { return -2; } if (c > 0) { return 2; } f1 = a->ob_type->tp_compare; if (f1 != NULL && f1 == b->ob_type->tp_compare) { c = (*f1)(a, b); Py_DECREF(a); Py_DECREF(b); return adjust_tp_compare(c); } // No comparison defined. Py_DECREF(a); Py_DECREF(b); return 2; } #endif static inline bool IS_SANE_TYPE(PyTypeObject *type) { return #if PYTHON_VERSION < 0x300 type == &PyString_Type || type == &PyInt_Type || #endif type == &PyLong_Type || type == &PyList_Type || type == &PyTuple_Type; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryInplaceAdd.c0000600000372100037210000001420214166627112033517 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* C helpers for type specialized "+=" (IAdd) operations */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif bool BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (likely(PyUnicode_CheckExact(*operand1))) { #if PYTHON_VERSION >= 0x300 if (Py_REFCNT(*operand1) == 1 && !PyUnicode_CHECK_INTERNED(*operand1)) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; } bool BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(*operand1)); if (likely(PyUnicode_CheckExact(operand2))) { #if PYTHON_VERSION >= 0x300 if (Py_REFCNT(*operand1) == 1 && !PyUnicode_CHECK_INTERNED(*operand1)) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; } bool BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(*operand1)); assert(PyUnicode_CheckExact(operand2)); #if PYTHON_VERSION >= 0x300 if (Py_REFCNT(*operand1) == 1 && !PyUnicode_CHECK_INTERNED(*operand1)) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } #if PYTHON_VERSION >= 0x300 bool BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1 && PyBytes_CheckExact(*operand1)) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; } bool BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(*operand1)); if (Py_REFCNT(*operand1) == 1 && PyBytes_CheckExact(operand2)) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; } bool BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(*operand1)); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { return BYTES_ADD_INCREMENTAL(operand1, operand2); } // Could concat bytes here more directly. PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; } #endifNuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceSub.c0000600000372100037210000023370614166627112032427 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "-" (SUB) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_SUB_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_SUB_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_subtract : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_SUB_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_SUB_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_SUB_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_subtract : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_SUB_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(*operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { if (Py_REFCNT(*operand1) == 1) { Nuitka_LongUpdateFromCLong(&*operand1, MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); goto exit_result_ok; } PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(*operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } if (Py_REFCNT(*operand1) == 1) { digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); #if 0 PyObject *r = BINARY_OPERATION_SUB_OBJECT_LONG_LONG( *operand1, operand2 ); #endif if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, -1); } else { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); Py_SIZE(*operand1) = -Py_ABS(Py_SIZE(*operand1)); } } else { if (Py_SIZE(operand2) < 0) { *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b, size_b); } else { *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b, size_b, 1); } } #if 0 assert(PyObject_RichCompareBool(r, *operand1, Py_EQ) == 1); Py_DECREF(r); #endif goto exit_result_ok; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(*operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(*operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(*operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_subtract : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_SUB_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_SUB_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_SUB_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_SUB_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_SUB_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_SUB_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_subtract available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_subtract == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_FLOAT_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_SUB_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_SUB_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_subtract : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_SUB_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryMatmult.c0000600000372100037210000003524514166627112033170 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "@" (MATMULT) operations */ #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'long' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'int' and 'int'"); #endif goto exit_binary_exception; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_LONG_LONG(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_OBJECT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_LONG_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'float' and 'float'"); goto exit_binary_exception; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_FLOAT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_OBJECT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_FLOAT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MATMULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); #error Operator @ not implemented { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_matrix_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_OBJECT_OBJECT(operand1, operand2); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersLists.c0000600000372100037210000002226314166627112027611 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This helpers is used to work with lists. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif // TODO: Move these into prelude maybe #ifndef _PyTuple_ITEMS #define _PyTuple_ITEMS(op) (((PyTupleObject *)(op))->ob_item) #endif #ifndef _PyList_ITEMS #define _PyList_ITEMS(op) (((PyListObject *)(op))->ob_item) #endif #ifndef Py_SET_SIZE #define Py_SET_SIZE(op, size) ((PyVarObject *)(op))->ob_size = size #endif PyObject *LIST_COPY(PyObject *list) { CHECK_OBJECT(list); assert(PyList_CheckExact(list)); Py_ssize_t size = PyList_GET_SIZE(list); PyObject *result = PyList_New(size); if (unlikely(result == NULL)) { return NULL; } for (Py_ssize_t i = 0; i < size; i++) { PyObject *item = PyList_GET_ITEM(list, i); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } return result; } static bool LIST_RESIZE(PyListObject *list, Py_ssize_t newsize) { Py_ssize_t allocated = list->allocated; if (allocated >= newsize && newsize >= (allocated >> 1)) { Py_SIZE(list) = newsize; return true; } size_t new_allocated; if (newsize == 0) { new_allocated = 0; } else { new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3; } size_t num_allocated_bytes = new_allocated * sizeof(PyObject *); PyObject **items = (PyObject **)PyMem_Realloc(list->ob_item, num_allocated_bytes); if (unlikely(items == NULL)) { PyErr_NoMemory(); return false; } list->ob_item = items; Py_SIZE(list) = newsize; list->allocated = new_allocated; return true; } bool LIST_EXTEND_FROM_LIST(PyObject *list, PyObject *other) { assert(PyList_CheckExact(list)); assert(PyList_CheckExact(other)); size_t n = PyList_GET_SIZE(other); if (n == 0) { return true; } size_t m = Py_SIZE(list); if (LIST_RESIZE((PyListObject *)list, m + n) == false) { return false; } PyObject **src = &PyList_GET_ITEM(other, 0); PyObject **dest = &PyList_GET_ITEM(list, m); for (size_t i = 0; i < n; i++) { PyObject *o = src[i]; Py_INCREF(o); dest[i] = o; } return true; } bool LIST_EXTEND(PyObject *target, PyObject *other) { CHECK_OBJECT(target); assert(PyList_Check(target)); CHECK_OBJECT(other); PyListObject *list = (PyListObject *)target; // First attempt those things that occur most often. Keep in mind that // other might be the same object as list. PyObject **src; Py_ssize_t src_size; if (PyList_CheckExact(other)) { // this covers list == other too. src = _PyList_ITEMS(other); src_size = PyList_GET_SIZE(other); } else if (PyTuple_CheckExact(other)) { src = _PyTuple_ITEMS(other); src_size = PyTuple_GET_SIZE(other); } else { src = NULL; #ifndef __NUITKA_NO_ASSERT__ src_size = 0; #endif } if (src != NULL) { if (src_size == 0) { return true; } Py_ssize_t list_size = PyList_GET_SIZE(list); // Overflow is not really realistic, so we only assert against it. assert(list_size <= PY_SSIZE_T_MAX - src_size); if (LIST_RESIZE(list, list_size + src_size) == false) { return false; } PyObject **target_items = _PyList_ITEMS(list) + list_size; for (Py_ssize_t i = 0; i < src_size; i++) { PyObject *value = src[i]; Py_INCREF(value); *target_items++ = value; } return true; } // Slow path needs to use iterator. TODO: PyObject *iter = MAKE_ITERATOR(other); if (iter == NULL) { return false; } PyObject *(*iternext)(PyObject *) = *Py_TYPE(iter)->tp_iternext; Py_ssize_t cur_size = PyList_GET_SIZE(list); #if PYTHON_VERSION >= 0x340 // Guess a iteratat if possible src_size = PyObject_LengthHint(other, 8); if (src_size < 0) { Py_DECREF(iter); return false; } Py_ssize_t list_size = PyList_GET_SIZE(list); if (list_size > PY_SSIZE_T_MAX - src_size) { // Overflow is not really realistic, hope is, it will not come true. } else { // Allocate the space in one go. if (LIST_RESIZE(list, list_size + src_size) == false) { Py_DECREF(iter); return false; } // Restore validity of the object for the time being. Py_SET_SIZE(list, list_size); } #endif for (;;) { PyObject *item = iternext(iter); if (item == NULL) { bool stop_iteration_error = CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(); Py_DECREF(iter); if (unlikely(stop_iteration_error == false)) { if (cur_size < list->allocated) { if (LIST_RESIZE(list, cur_size) == false) { return false; } } return false; } break; } CHECK_OBJECT(item); if (cur_size < list->allocated) { // Already allocated, so we can just set it. PyList_SET_ITEM(list, cur_size, item); Py_SET_SIZE(list, cur_size + 1); } else { assert(cur_size != PY_SSIZE_T_MAX); if (LIST_RESIZE(list, cur_size + 1) == false) { return false; } PyList_SET_ITEM(list, cur_size, item); } cur_size += 1; } /* Cut back result list if initial guess was too large. */ assert(cur_size == PyList_GET_SIZE(list)); if (cur_size < list->allocated) { if (LIST_RESIZE(list, cur_size) == false) { return false; } } return true; } #if PYTHON_VERSION >= 0x390 bool LIST_EXTEND_FOR_UNPACK(PyObject *list, PyObject *other) { // TODO: For improved performance, inline this, but we probably wait // until code generation for this kind of helpers is there. bool result = LIST_EXTEND(list, other); if (likely(result)) { return true; } PyObject *error = GET_ERROR_OCCURRED(); if (EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_TypeError) && (Py_TYPE(other)->tp_iter == NULL && !PySequence_Check(other))) { CLEAR_ERROR_OCCURRED(); PyErr_Format(PyExc_TypeError, "Value after * must be an iterable, not %s", Py_TYPE(other)->tp_name); } return false; } #endif bool LIST_APPEND1(PyObject *target, PyObject *item) { CHECK_OBJECT(target); assert(PyList_Check(target)); CHECK_OBJECT(item); PyListObject *list = (PyListObject *)target; Py_ssize_t cur_size = PyList_GET_SIZE(list); // Overflow is not really realistic, so we only assert against it. assert(cur_size <= PY_SSIZE_T_MAX); if (LIST_RESIZE(list, cur_size + 1) == false) { return false; } PyList_SET_ITEM(list, cur_size, item); return true; } bool LIST_APPEND0(PyObject *target, PyObject *item) { CHECK_OBJECT(target); assert(PyList_Check(target)); CHECK_OBJECT(item); PyListObject *list = (PyListObject *)target; Py_ssize_t cur_size = PyList_GET_SIZE(list); // Overflow is not really realistic, so we only assert against it. assert(cur_size <= PY_SSIZE_T_MAX); if (LIST_RESIZE(list, cur_size + 1) == false) { return false; } PyList_SET_ITEM0(list, cur_size, item); return true; } #if PYTHON_VERSION >= 0x340 static bool allocateListItems(PyListObject *list, Py_ssize_t size) { PyObject **items = PyMem_New(PyObject *, size); if (unlikely(items == NULL)) { PyErr_NoMemory(); return false; } list->ob_item = items; list->allocated = size; return true; } #endif PyObject *MAKE_LIST(PyObject *iterable) { PyObject *list = PyList_New(0); #if PYTHON_VERSION >= 0x340 if (_PyObject_HasLen(iterable)) { Py_ssize_t iter_len = PyObject_Size(iterable); if (unlikely(iter_len == -1)) { if (!PyErr_ExceptionMatches(PyExc_TypeError)) { return NULL; } CLEAR_ERROR_OCCURRED(); } if (iter_len > 0) { if (allocateListItems((PyListObject *)list, iter_len) == false) { return NULL; } } } #endif bool res = LIST_EXTEND(list, iterable); if (unlikely(res == false)) { Py_DECREF(list); return NULL; } return list; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceMatmult.c0000600000372100037210000005030214166627112033306 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "@" (MATMULT) operations */ #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MATMULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_matrix_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_matrix_multiply == NULL); { assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'long' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'int' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_LONG_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MATMULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_matrix_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MATMULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_matrix_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_matrix_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_LONG_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MATMULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_matrix_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_matrix_multiply == NULL); { assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'float' and 'float'"); goto exit_inplace_exception; } exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_FLOAT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MATMULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_matrix_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_matrix_multiply == NULL || type1->tp_as_number->nb_matrix_multiply == type2->tp_as_number->nb_matrix_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MATMULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_matrix_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_matrix_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_FLOAT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MATMULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); #error Operator @ not implemented { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_matrix_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_matrix_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with Python3 only operator '@' PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MATMULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MATMULT_OBJECT_OBJECT_INPLACE(operand1, operand2); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersImport.c0000600000372100037210000003330514166627112027764 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For making imports work. * * These make the actual built-in importing mechanic work with Nuitka. We * provide code to import modules and names from modules, also the mechanic * for star imports to look at "__all__". * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif NUITKA_DEFINE_BUILTIN(__import__); PyObject *IMPORT_MODULE_KW(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items, PyObject *level) { CHECK_OBJECT_X(module_name); CHECK_OBJECT_X(globals); CHECK_OBJECT_X(locals); CHECK_OBJECT_X(import_items); CHECK_OBJECT_X(level); PyObject *kw_args = PyDict_New(); if (module_name) { PyDict_SetItem(kw_args, const_str_plain_name, module_name); } if (globals) { PyDict_SetItem(kw_args, const_str_plain_globals, globals); } if (locals) { PyDict_SetItem(kw_args, const_str_plain_locals, locals); } if (import_items) { PyDict_SetItem(kw_args, const_str_plain_fromlist, import_items); } if (level) { PyDict_SetItem(kw_args, const_str_plain_level, level); } NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_KEYARGS(NUITKA_ACCESS_BUILTIN(__import__), kw_args); Py_DECREF(kw_args); return import_result; } PyObject *IMPORT_MODULE1(PyObject *module_name) { CHECK_OBJECT(module_name); NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(__import__), module_name); return import_result; } PyObject *IMPORT_MODULE2(PyObject *module_name, PyObject *globals) { CHECK_OBJECT(module_name); CHECK_OBJECT(globals); PyObject *pos_args[] = {module_name, globals}; NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_ARGS2(NUITKA_ACCESS_BUILTIN(__import__), pos_args); return import_result; } PyObject *IMPORT_MODULE3(PyObject *module_name, PyObject *globals, PyObject *locals) { CHECK_OBJECT(module_name); CHECK_OBJECT(globals); CHECK_OBJECT(locals); PyObject *pos_args[] = {module_name, globals, locals}; NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_ARGS3(NUITKA_ACCESS_BUILTIN(__import__), pos_args); return import_result; } PyObject *IMPORT_MODULE4(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items) { CHECK_OBJECT(module_name); CHECK_OBJECT(globals); CHECK_OBJECT(locals); CHECK_OBJECT(import_items); PyObject *pos_args[] = {module_name, globals, locals, import_items}; NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_ARGS4(NUITKA_ACCESS_BUILTIN(__import__), pos_args); return import_result; } PyObject *IMPORT_MODULE5(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items, PyObject *level) { CHECK_OBJECT(module_name); CHECK_OBJECT(globals); CHECK_OBJECT(locals); CHECK_OBJECT(import_items); CHECK_OBJECT(level); PyObject *pos_args[] = {module_name, globals, locals, import_items, level}; NUITKA_ASSIGN_BUILTIN(__import__); PyObject *import_result = CALL_FUNCTION_WITH_ARGS5(NUITKA_ACCESS_BUILTIN(__import__), pos_args); return import_result; } bool IMPORT_MODULE_STAR(PyObject *target, bool is_module, PyObject *module) { // Check parameters. CHECK_OBJECT(module); CHECK_OBJECT(target); PyObject *iter; bool all_case; PyObject *all = PyObject_GetAttr(module, const_str_plain___all__); if (all != NULL) { iter = MAKE_ITERATOR(all); Py_DECREF(all); if (unlikely(iter == NULL)) { return false; } all_case = true; } else if (EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_AttributeError)) { CLEAR_ERROR_OCCURRED(); iter = MAKE_ITERATOR(PyModule_GetDict(module)); CHECK_OBJECT(iter); all_case = false; } else { return false; } for (;;) { PyObject *item = ITERATOR_NEXT(iter); if (item == NULL) { break; } #if PYTHON_VERSION < 0x300 if (unlikely(PyString_Check(item) == false && PyUnicode_Check(item) == false)) #else if (unlikely(PyUnicode_Check(item) == false)) #endif { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%s'", Py_TYPE(item)->tp_name); break; } // When we are not using the "__all__", we should skip private variables. if (all_case == false) { if (Nuitka_String_AsString_Unchecked(item)[0] == '_') { continue; } } PyObject *value = LOOKUP_ATTRIBUTE(module, item); // Might not exist, because of e.g. wrong "__all__" value. if (unlikely(value == NULL)) { Py_DECREF(item); break; } // TODO: Check if the reference is handled correctly if (is_module) { SET_ATTRIBUTE(target, item, value); } else { SET_SUBSCRIPT(target, item, value); } Py_DECREF(value); Py_DECREF(item); } Py_DECREF(iter); return !ERROR_OCCURRED(); } PyObject *IMPORT_NAME(PyObject *module, PyObject *import_name) { CHECK_OBJECT(module); CHECK_OBJECT(import_name); PyObject *result = PyObject_GetAttr(module, import_name); if (unlikely(result == NULL)) { if (CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED()) { #if PYTHON_VERSION >= 0x370 PyObject *filename = Nuitka_GetFilenameObject(module); PyObject *name = LOOKUP_ATTRIBUTE(module, const_str_plain___name__); if (name == NULL) { name = PyUnicode_FromString(""); } PyErr_Format(PyExc_ImportError, "cannot import name %R from %R (%S)", import_name, name, filename); Py_DECREF(filename); Py_DECREF(name); #elif PYTHON_VERSION >= 0x340 || !defined(_NUITKA_FULL_COMPAT) PyErr_Format(PyExc_ImportError, "cannot import name '%s'", Nuitka_String_AsString(import_name)); #else PyErr_Format(PyExc_ImportError, "cannot import name %s", Nuitka_String_AsString(import_name)); #endif } return NULL; } return result; } #if PYTHON_VERSION >= 0x350 static PyObject *resolveParentModuleName(PyObject *module, PyObject *name, int level) { PyObject *globals = PyModule_GetDict(module); CHECK_OBJECT(globals); if (unlikely(!PyDict_Check(globals))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "globals must be a dict"); return NULL; } PyObject *package = DICT_GET_ITEM0(globals, const_str_plain___package__); if (unlikely(package == NULL && ERROR_OCCURRED())) { return NULL; } if (package == Py_None) { package = NULL; } PyObject *spec = DICT_GET_ITEM0(globals, const_str_plain___spec__); if (unlikely(spec == NULL && ERROR_OCCURRED())) { return NULL; } if (package != NULL) { if (!PyUnicode_Check(package)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "package must be a string"); return NULL; } // Compare with spec. if (spec != NULL && spec != Py_None) { PyObject *parent = PyObject_GetAttr(spec, const_str_plain_parent); if (unlikely(parent == NULL)) { return NULL; } int equal = PyObject_RichCompareBool(package, parent, Py_EQ); Py_DECREF(parent); if (unlikely(equal < 0)) { return NULL; } if (unlikely(equal == 0)) { if (PyErr_WarnEx(PyExc_ImportWarning, "__package__ != __spec__.parent", 1) < 0) { return NULL; } } } Py_INCREF(package); } else if (spec != NULL && spec != Py_None) { package = PyObject_GetAttr(spec, const_str_plain_parent); if (unlikely(package == NULL)) { return NULL; } if (unlikely(!PyUnicode_Check(package))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__spec__.parent must be a string"); return NULL; } } else { if (PyErr_WarnEx(PyExc_ImportWarning, "can't resolve package from __spec__ or __package__, " "falling back on __name__ and __path__", 1) < 0) { return NULL; } package = DICT_GET_ITEM0(globals, const_str_plain___name__); if (unlikely(package == NULL && !ERROR_OCCURRED())) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_KeyError, "'__name__' not in globals"); return NULL; } if (!PyUnicode_Check(package)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be a string"); return NULL; } // Detect package from __path__ presence. if (DICT_HAS_ITEM(globals, const_str_plain___path__) == 1) { Py_ssize_t dot = PyUnicode_FindChar(package, '.', 0, PyUnicode_GET_LENGTH(package), -1); if (unlikely(dot == -2)) { return NULL; } if (unlikely(dot == -1)) { // NULL without error means it just didn't work. return NULL; } PyObject *substr = PyUnicode_Substring(package, 0, dot); if (unlikely(substr == NULL)) { return NULL; } package = substr; } else { Py_INCREF(package); } } Py_ssize_t last_dot = PyUnicode_GET_LENGTH(package); if (unlikely(last_dot == 0)) { Py_DECREF(package); // NULL without error means it just didn't work. return NULL; } for (int level_up = 1; level_up < level; level_up += 1) { last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); if (last_dot == -2) { Py_DECREF(package); return NULL; } else if (last_dot == -1) { Py_DECREF(package); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "attempted relative import beyond top-level package"); return NULL; } } PyObject *base = PyUnicode_Substring(package, 0, last_dot); Py_DECREF(package); if (unlikely(base == NULL || PyUnicode_GET_LENGTH(name) == 0)) { return base; } PyObject *abs_name = PyUnicode_FromFormat("%U.%U", base, name); Py_DECREF(base); return abs_name; } PyObject *IMPORT_NAME_OR_MODULE(PyObject *module, PyObject *globals, PyObject *import_name, PyObject *level) { CHECK_OBJECT(module); CHECK_OBJECT(import_name); PyObject *result = PyObject_GetAttr(module, import_name); if (unlikely(result == NULL)) { if (EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_AttributeError)) { CLEAR_ERROR_OCCURRED(); long level_int = PyLong_AsLong(level); if (unlikely(level_int == -1 && ERROR_OCCURRED())) { return NULL; } if (unlikely(level_int < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "level must be >= 0"); return NULL; } if (level_int > 0) { PyObject *fromlist = PyTuple_New(1); PyTuple_SET_ITEM0(fromlist, 0, import_name); result = IMPORT_MODULE5(const_str_empty, globals, globals, fromlist, level); Py_DECREF(fromlist); // Look up in "sys.modules", because we will have returned the // package of it from IMPORT_MODULE5. PyObject *name = PyUnicode_FromFormat("%s.%S", PyModule_GetName(result), import_name); if (result != NULL) { Py_DECREF(result); result = Nuitka_GetModule(name); } Py_DECREF(name); } else { PyObject *name = resolveParentModuleName(module, import_name, level_int); if (name == NULL) { if (unlikely(ERROR_OCCURRED())) { return NULL; } } else { result = IMPORT_MODULE5(name, globals, globals, const_tuple_empty, level); if (result != NULL) { Py_DECREF(result); // Look up in "sys.modules", because we will have returned the result = Nuitka_GetModule(name); Py_DECREF(name); } } } if (result == NULL) { CLEAR_ERROR_OCCURRED(); result = IMPORT_NAME(module, import_name); } } } CHECK_OBJECT(import_name); return result; } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryPowUtils.c0000600000372100037210000000177714166627112033336 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include #define DOUBLE_IS_ODD_INTEGER(x) (fmod(fabs(x), 2.0) == 1.0) Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryBitand.c0000600000372100037210000023540414166627112032745 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "&" (BITAND) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITAND_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITAND_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_and; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_LONG_INT(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITAND_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_SET_SET(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_and; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and 'set'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PySet_Type.tp_as_number->nb_and; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: 'set' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITAND_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_and(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_BITAND_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_BITAND_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a & b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_and : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_and : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_and; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITAND_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersSafeStrings.c0000600000372100037210000001620014166627112030735 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This helpers are used to interact safely with buffers to not overflow. Currently this is used for char and wchar_t string buffers and shared between onefile bootstrap for Windows, plugins and Nuitka core, but should not use any Python level functionality. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #if defined(_WIN32) #include #endif #include #endif #if defined(_WIN32) #include #endif void copyStringSafe(char *buffer, char const *source, size_t buffer_size) { if (strlen(source) >= buffer_size) { abort(); } strcpy(buffer, source); } void copyStringSafeN(char *buffer, char const *source, size_t n, size_t buffer_size) { if (n >= buffer_size - 1) { abort(); } strncpy(buffer, source, n); buffer[n] = 0; } void appendStringSafe(char *buffer, char const *source, size_t buffer_size) { if (strlen(source) + strlen(buffer) >= buffer_size) { abort(); } strcat(buffer, source); } void appendCharSafe(char *buffer, char c, size_t buffer_size) { char source[2] = {c, 0}; appendStringSafe(buffer, source, buffer_size); } void appendWStringSafeW(wchar_t *target, wchar_t const *source, size_t buffer_size) { while (*target != 0) { target++; buffer_size -= 1; } while (*source != 0) { if (buffer_size < 1) { abort(); } *target++ = *source++; buffer_size -= 1; } *target = 0; } void appendCharSafeW(wchar_t *target, char c, size_t buffer_size) { while (*target != 0) { target++; buffer_size -= 1; } if (buffer_size < 1) { abort(); } target += wcslen(target); char buffer_c[2] = {c, 0}; size_t res = mbstowcs(target, buffer_c, 2); assert(res == 1); } void appendStringSafeW(wchar_t *target, char const *source, size_t buffer_size) { while (*target != 0) { target++; buffer_size -= 1; } while (*source != 0) { appendCharSafeW(target, *source, buffer_size); source++; buffer_size -= 1; } } #if defined(_WIN32) bool expandTemplatePathW(wchar_t *target, wchar_t const *source, size_t buffer_size) { target[0] = 0; wchar_t var_name[1024]; wchar_t *w = NULL; while (*source != 0) { if (*source == '%') { if (w == NULL) { w = var_name; *w = 0; source++; continue; } else { *w = 0; if (wcsicmp(var_name, L"TEMP") == 0) { GetTempPathW((DWORD)buffer_size, target); } else if (wcsicmp(var_name, L"PROGRAM") == 0) { #if _NUITKA_ONEFILE_TEMP == 1 appendWStringSafeW(target, __wargv[0], buffer_size); #else if (!GetModuleFileNameW(NULL, target, (DWORD)buffer_size)) { return false; } #endif } else if (wcsicmp(var_name, L"PID") == 0) { char pid_buffer[128]; snprintf(pid_buffer, sizeof(pid_buffer), "%d", GetCurrentProcessId()); appendStringSafeW(target, pid_buffer, buffer_size); } else if (wcsicmp(var_name, L"TIME") == 0) { char time_buffer[1024]; __int64 time = 0; assert(sizeof(time) == sizeof(FILETIME)); GetSystemTimeAsFileTime((LPFILETIME)&time); snprintf(time_buffer, sizeof(time_buffer), "%lld", time); appendStringSafeW(target, time_buffer, buffer_size); } else { return false; } // Skip over appended stuff. while (*target) { target++; buffer_size -= 1; } w = NULL; source++; continue; } } if (w != NULL) { *w++ = *source++; continue; } if (buffer_size < 1) { return false; } *target++ = *source++; buffer_size -= 1; } *target = 0; return true; } #else #include #include bool expandTemplatePath(char *target, char const *source, size_t buffer_size) { target[0] = 0; char var_name[1024]; char *w = NULL; while (*source != 0) { if (*source == '%') { if (w == NULL) { w = var_name; *w = 0; source++; continue; } else { *w = 0; if (strcasecmp(var_name, "TEMP") == 0) { char const *tmp_dir = getenv("TMPDIR"); if (tmp_dir == NULL) { tmp_dir = "/tmp"; } appendStringSafe(target, tmp_dir, buffer_size); } else if (strcasecmp(var_name, "PROGRAM") == 0) { // Not implemented outside of Windows yet. return false; } else if (strcasecmp(var_name, "PID") == 0) { char pid_buffer[128]; snprintf(pid_buffer, sizeof(pid_buffer), "%d", getpid()); appendStringSafe(target, pid_buffer, buffer_size); } else if (strcasecmp(var_name, "TIME") == 0) { char time_buffer[1024]; struct timeval current_time; gettimeofday(¤t_time, NULL); snprintf(time_buffer, sizeof(time_buffer), "%ld_%ld", current_time.tv_sec, current_time.tv_usec); appendStringSafe(target, time_buffer, buffer_size); } else { return false; } // Skip over appended stuff. while (*target) { target++; buffer_size -= 1; } w = NULL; source++; continue; } } if (w != NULL) { *w++ = *source++; continue; } if (buffer_size < 1) { return false; } *target++ = *source++; buffer_size -= 1; } *target = 0; return true; } #endifNuitka-0.6.19.1/nuitka/build/static_src/CompiledAsyncgenType.c0000600000372100037210000023660314166627112031263 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Compiled Asyncgen. * * Unlike in CPython, we have one type for just asyncgen, this doesn't do generators * nor coroutines. * * It strives to be full replacement for normal asyncgen. * */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/freelists.h" #include "nuitka/prelude.h" #include #endif // For reporting about reference counts per type. #if _DEBUG_REFCOUNTS int count_active_Nuitka_Asyncgen_Type = 0; int count_allocated_Nuitka_Asyncgen_Type = 0; int count_released_Nuitka_Asyncgen_Type = 0; int count_active_Nuitka_AsyncgenValueWrapper_Type = 0; int count_allocated_Nuitka_AsyncgenValueWrapper_Type = 0; int count_released_Nuitka_AsyncgenValueWrapper_Type = 0; int count_active_Nuitka_AsyncgenAsend_Type = 0; int count_allocated_Nuitka_AsyncgenAsend_Type = 0; int count_released_Nuitka_AsyncgenAsend_Type = 0; int count_active_Nuitka_AsyncgenAthrow_Type = 0; int count_allocated_Nuitka_AsyncgenAthrow_Type = 0; int count_released_Nuitka_AsyncgenAthrow_Type = 0; #endif static long Nuitka_Asyncgen_tp_hash(struct Nuitka_AsyncgenObject *asyncgen) { return asyncgen->m_counter; } static PyObject *Nuitka_Asyncgen_get_name(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); Py_INCREF(asyncgen->m_name); return asyncgen->m_name; } static int Nuitka_Asyncgen_set_name(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(value); // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } PyObject *tmp = asyncgen->m_name; Py_INCREF(value); asyncgen->m_name = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Asyncgen_get_qualname(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); Py_INCREF(asyncgen->m_qualname); return asyncgen->m_qualname; } static int Nuitka_Asyncgen_set_qualname(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(value); // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } PyObject *tmp = asyncgen->m_qualname; Py_INCREF(value); asyncgen->m_qualname = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Asyncgen_get_ag_await(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); if (asyncgen->m_yieldfrom) { Py_INCREF(asyncgen->m_yieldfrom); return asyncgen->m_yieldfrom; } else { Py_INCREF(Py_None); return Py_None; } } static PyObject *Nuitka_Asyncgen_get_code(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); CHECK_OBJECT(asyncgen->m_code_object); Py_INCREF(asyncgen->m_code_object); return (PyObject *)asyncgen->m_code_object; } static int Nuitka_Asyncgen_set_code(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value) { CHECK_OBJECT(asyncgen); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "ag_code is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Asyncgen_get_frame(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(asyncgen->m_frame); if (asyncgen->m_frame) { Py_INCREF(asyncgen->m_frame); return (PyObject *)asyncgen->m_frame; } else { Py_INCREF(Py_None); return Py_None; } } static int Nuitka_Asyncgen_set_frame(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(value); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "ag_frame is not writable in Nuitka"); return -1; } static void Nuitka_Asyncgen_release_closure(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); for (Py_ssize_t i = 0; i < asyncgen->m_closure_given; i++) { CHECK_OBJECT(asyncgen->m_closure[i]); Py_DECREF(asyncgen->m_closure[i]); } asyncgen->m_closure_given = 0; } static PyObject *Nuitka_YieldFromAsyncgenCore(struct Nuitka_AsyncgenObject *asyncgen, PyObject *send_value, bool mode) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(send_value); PyObject *yieldfrom = asyncgen->m_yieldfrom; CHECK_OBJECT(yieldfrom); // Need to make it unaccessible while using it. asyncgen->m_yieldfrom = NULL; PyObject *returned_value; PyObject *yielded = _Nuitka_YieldFromCore(yieldfrom, send_value, &returned_value, mode); if (yielded == NULL) { assert(asyncgen->m_yieldfrom == NULL); Py_DECREF(yieldfrom); yielded = ((asyncgen_code)asyncgen->m_code)(asyncgen, returned_value); } else { assert(asyncgen->m_yieldfrom == NULL); asyncgen->m_yieldfrom = yieldfrom; } return yielded; } #if _DEBUG_ASYNCGEN NUITKA_MAY_BE_UNUSED static void _PRINT_ASYNCGEN_STATUS(char const *descriptor, char const *context, struct Nuitka_AsyncgenObject *asyncgen) { char const *status; switch (asyncgen->m_status) { case status_Finished: status = "(finished)"; break; case status_Running: status = "(running)"; break; case status_Unused: status = "(unused)"; break; default: status = "(ILLEGAL)"; break; } PRINT_STRING(descriptor); PRINT_STRING(" : "); PRINT_STRING(context); PRINT_STRING(" "); PRINT_ITEM((PyObject *)asyncgen); PRINT_STRING(" "); PRINT_STRING(status); PRINT_NEW_LINE(); } #define PRINT_ASYNCGEN_STATUS(context, asyncgen) _PRINT_ASYNCGEN_STATUS(__FUNCTION__, context, asyncgen) #endif static PyObject *Nuitka_YieldFromAsyncgenNext(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_NEW_LINE(); #endif PyObject *result = Nuitka_YieldFromAsyncgenCore(asyncgen, Py_None, true); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_YieldFromAsyncgenInitial(struct Nuitka_AsyncgenObject *asyncgen, PyObject *send_value) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(send_value); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_NEW_LINE(); #endif PyObject *result = Nuitka_YieldFromAsyncgenCore(asyncgen, send_value, false); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_AsyncgenValueWrapper_New(PyObject *value); static PySendResult _Nuitka_Asyncgen_sendR(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb, PyObject **result) { CHECK_OBJECT(asyncgen); assert(Nuitka_Asyncgen_Check((PyObject *)asyncgen)); CHECK_OBJECT_X(value); CHECK_OBJECT_X(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_COROUTINE_VALUE("value", value); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif if (value != NULL) { assert(exception_type == NULL); assert(exception_value == NULL); assert(exception_tb == NULL); } if (asyncgen->m_status == status_Unused && value != NULL && value != Py_None) { // No exception if value is given. SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't send non-None value to a just-started async generator"); return PYGEN_ERROR; } if (asyncgen->m_status != status_Finished) { if (asyncgen->m_running) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "async generator already executing"); return PYGEN_ERROR; } PyThreadState *thread_state = PyThreadState_GET(); // Put the asyncgen back on the frame stack. // First take of running frame from the stack, owning a reference. PyFrameObject *return_frame = thread_state->frame; #ifndef __NUITKA_NO_ASSERT__ if (return_frame) { assertFrameObject((struct Nuitka_FrameObject *)return_frame); } #endif if (asyncgen->m_resume_frame) { // It would be nice if our frame were still alive. Nobody had the // right to release it. assertFrameObject(asyncgen->m_resume_frame); // It's not supposed to be on the top right now. assert(return_frame != &asyncgen->m_resume_frame->m_frame); thread_state->frame = &asyncgen->m_frame->m_frame; asyncgen->m_resume_frame = NULL; } // Consider it as running. if (asyncgen->m_status == status_Unused) { asyncgen->m_status = status_Running; } // Continue the yielder function while preventing recursion. asyncgen->m_running = true; // Check for thrown exception, and publish it. if (unlikely(exception_type != NULL)) { assert(value == NULL); // Transfer exception ownership to published. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); } if (asyncgen->m_frame) { Nuitka_Frame_MarkAsExecuting(asyncgen->m_frame); } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Switching to asyncgen", asyncgen); PRINT_COROUTINE_VALUE("value", value); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); // dumpFrameStack(); #endif PyObject *yielded; if (asyncgen->m_yieldfrom == NULL) { yielded = ((asyncgen_code)asyncgen->m_code)(asyncgen, value); } else { yielded = Nuitka_YieldFromAsyncgenInitial(asyncgen, value); } // If the asyncgen returns with m_yieldfrom set, it wants us to yield // from that value from now on. while (yielded == NULL && asyncgen->m_yieldfrom != NULL) { yielded = Nuitka_YieldFromAsyncgenNext(asyncgen); } if (asyncgen->m_frame) { Nuitka_Frame_MarkAsNotExecuting(asyncgen->m_frame); } asyncgen->m_running = false; thread_state = PyThreadState_GET(); // Remove the back frame from asyncgen if it's there. if (asyncgen->m_frame) { // assert(thread_state->frame == &asyncgen->m_frame->m_frame); assertFrameObject(asyncgen->m_frame); Py_CLEAR(asyncgen->m_frame->m_frame.f_back); // Remember where to resume from. asyncgen->m_resume_frame = (struct Nuitka_FrameObject *)thread_state->frame; } thread_state->frame = return_frame; #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Returned from coroutine", asyncgen); // dumpFrameStack(); #endif #ifndef __NUITKA_NO_ASSERT__ if (return_frame) { assertFrameObject((struct Nuitka_FrameObject *)return_frame); } #endif if (yielded == NULL) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("finishing from yield", asyncgen); PRINT_CURRENT_EXCEPTION(); PRINT_STRING("-> finishing asyncgen with exception sets status_Finished\n"); PRINT_NEW_LINE(); #endif asyncgen->m_status = status_Finished; if (asyncgen->m_frame != NULL) { asyncgen->m_frame->m_frame.f_gen = NULL; Py_DECREF(asyncgen->m_frame); asyncgen->m_frame = NULL; } Nuitka_Asyncgen_release_closure(asyncgen); PyObject *error_occurred = GET_ERROR_OCCURRED(); if (error_occurred == PyExc_StopIteration || error_occurred == PyExc_StopAsyncIteration) { PyObject *saved_exception_type, *saved_exception_value; PyTracebackObject *saved_exception_tb; FETCH_ERROR_OCCURRED(&saved_exception_type, &saved_exception_value, &saved_exception_tb); NORMALIZE_EXCEPTION(&saved_exception_type, &saved_exception_value, &saved_exception_tb); if (error_occurred == PyExc_StopIteration) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator raised StopIteration"); } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator raised StopAsyncIteration"); } FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); RAISE_EXCEPTION_WITH_CAUSE(&exception_type, &exception_value, &exception_tb, saved_exception_value); CHECK_OBJECT(exception_value); CHECK_OBJECT(saved_exception_value); Py_INCREF(saved_exception_value); PyException_SetContext(exception_value, saved_exception_value); Py_DECREF(saved_exception_type); Py_XDECREF(saved_exception_tb); RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return PYGEN_ERROR; } return PYGEN_ERROR; } else { // For normal yield, wrap the result value before returning. if (asyncgen->m_yieldfrom == NULL) { // TODO: Why not transfer ownership to constructor. PyObject *wrapped = Nuitka_AsyncgenValueWrapper_New(yielded); yielded = wrapped; assert(yielded != NULL); } *result = yielded; return PYGEN_NEXT; } } else { // Release exception if any, we are finished with it and will raise another. Py_XDECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return PYGEN_RETURN; } } static PyObject *_Nuitka_Asyncgen_send(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { PyObject *result; PySendResult res = _Nuitka_Asyncgen_sendR(asyncgen, value, closing, exception_type, exception_value, exception_tb, &result); switch (res) { case PYGEN_RETURN: SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); return NULL; case PYGEN_NEXT: return result; case PYGEN_ERROR: return NULL; default: NUITKA_CANNOT_GET_HERE("invalid PYGEN_ result"); } } // Note: Used by compiled frames. static bool _Nuitka_Asyncgen_close(struct Nuitka_AsyncgenObject *asyncgen) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); #endif CHECK_OBJECT(asyncgen); if (asyncgen->m_status == status_Running) { Py_INCREF(PyExc_GeneratorExit); PyObject *result = _Nuitka_Asyncgen_send(asyncgen, NULL, true, PyExc_GeneratorExit, NULL, NULL); if (unlikely(result)) { Py_DECREF(result); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator ignored GeneratorExit"); return false; } else { PyObject *error = GET_ERROR_OCCURRED(); assert(error != NULL); if (EXCEPTION_MATCH_GENERATOR(error)) { CLEAR_ERROR_OCCURRED(); return true; } return false; } } return true; } static bool _Nuitka_Generator_check_throw2(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); // This function is called when yielding to a asyncgen through "_Nuitka_YieldFromPassExceptionTo" // and potentially wrapper objects used by generators, or by the throw method itself. // Note: // Exception arguments are passed for ownership and must be released before returning. The // value of exception_type will not be NULL, but the actual exception will not necessarily // be normalized. static PyObject *_Nuitka_Asyncgen_throw2(struct Nuitka_AsyncgenObject *asyncgen, bool close_on_genexit, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { CHECK_OBJECT(asyncgen); assert(Nuitka_Asyncgen_Check((PyObject *)asyncgen)); CHECK_OBJECT(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_COROUTINE_VALUE("yieldfrom", asyncgen->m_yieldfrom); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif if (asyncgen->m_yieldfrom != NULL) { // TODO: This check is not done for coroutines, correct? if (close_on_genexit) { if (EXCEPTION_MATCH_BOOL_SINGLE(exception_type, PyExc_GeneratorExit)) { // Asynchronous generators need to close the yield_from. asyncgen->m_running = 1; bool res = Nuitka_gen_close_iter(asyncgen->m_yieldfrom); asyncgen->m_running = 0; if (res == false) { // Release exception, we are done with it now and pick up the new one. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); } return _Nuitka_Asyncgen_send(asyncgen, NULL, false, exception_type, exception_value, exception_tb); } } PyObject *ret; #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Passing to yielded from", asyncgen); PRINT_COROUTINE_VALUE("m_yieldfrom", asyncgen->m_yieldfrom); PRINT_NEW_LINE(); #endif if (PyGen_CheckExact(asyncgen->m_yieldfrom) || PyCoro_CheckExact(asyncgen->m_yieldfrom)) { PyGenObject *gen = (PyGenObject *)asyncgen->m_yieldfrom; // Transferred exception ownership to "Nuitka_UncompiledGenerator_throw". asyncgen->m_running = 1; ret = Nuitka_UncompiledGenerator_throw(gen, 1, exception_type, exception_value, exception_tb); asyncgen->m_running = 0; } else if (Nuitka_Generator_Check(asyncgen->m_yieldfrom)) { struct Nuitka_GeneratorObject *gen = ((struct Nuitka_GeneratorObject *)asyncgen->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Generator_throw2". asyncgen->m_running = 1; ret = _Nuitka_Generator_throw2(gen, exception_type, exception_value, exception_tb); asyncgen->m_running = 0; } else if (Nuitka_Coroutine_Check(asyncgen->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineObject *)asyncgen->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Coroutine_throw2". asyncgen->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); asyncgen->m_running = 0; } else if (Nuitka_CoroutineWrapper_Check(asyncgen->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineWrapperObject *)asyncgen->m_yieldfrom)->m_coroutine; // Transferred exception ownership to "_Nuitka_Coroutine_throw2". asyncgen->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); asyncgen->m_running = 0; } else if (Nuitka_AsyncgenAsend_Check(asyncgen->m_yieldfrom)) { struct Nuitka_AsyncgenAsendObject *asyncgen_asend = ((struct Nuitka_AsyncgenAsendObject *)asyncgen->m_yieldfrom); // Transferred exception ownership to "_Nuitka_AsyncgenAsend_throw2". asyncgen->m_running = 1; ret = _Nuitka_AsyncgenAsend_throw2(asyncgen_asend, exception_type, exception_value, exception_tb); asyncgen->m_running = 0; } else { PyObject *meth = PyObject_GetAttr(asyncgen->m_yieldfrom, const_str_plain_throw); if (unlikely(meth == NULL)) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } CLEAR_ERROR_OCCURRED(); // Passing exception ownership to that code. goto throw_here; } CHECK_OBJECT(exception_type); #if 0 // TODO: Add slow mode traces. PRINT_ITEM(coroutine->m_yieldfrom); PRINT_NEW_LINE(); #endif asyncgen->m_running = 1; ret = PyObject_CallFunctionObjArgs(meth, exception_type, exception_value, exception_tb, NULL); asyncgen->m_running = 0; Py_DECREF(meth); // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); } if (unlikely(ret == NULL)) { PyObject *val; if (_PyGen_FetchStopIterationValue(&val) == 0) { CHECK_OBJECT(val); asyncgen->m_yieldfrom = NULL; // Return value, not to continue with yielding from. if (asyncgen->m_yieldfrom != NULL) { CHECK_OBJECT(asyncgen->m_yieldfrom); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Yield from removal:", asyncgen); PRINT_COROUTINE_VALUE("yieldfrom", asyncgen->m_yieldfrom); #endif Py_DECREF(asyncgen->m_yieldfrom); asyncgen->m_yieldfrom = NULL; } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Sending return value into ourselves", asyncgen); PRINT_COROUTINE_VALUE("value", val); PRINT_NEW_LINE(); #endif ret = _Nuitka_Asyncgen_send(asyncgen, val, false, NULL, NULL, NULL); } else { #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Sending exception value into ourselves", asyncgen); PRINT_COROUTINE_VALUE("yieldfrom", asyncgen->m_yieldfrom); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif ret = _Nuitka_Asyncgen_send(asyncgen, NULL, false, NULL, NULL, NULL); } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave with value/exception from sending into ourselves:", asyncgen); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } else { #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave with return value:", asyncgen); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } return ret; } throw_here: // We continue to have exception ownership here. #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Need to throw into itself", asyncgen); #endif if (unlikely(_Nuitka_Generator_check_throw2(&exception_type, &exception_value, &exception_tb) == false)) { // Exception was released by _Nuitka_Generator_check_throw2 already. return NULL; } PyObject *result; if (asyncgen->m_status == status_Running) { result = _Nuitka_Asyncgen_send(asyncgen, NULL, false, exception_type, exception_value, exception_tb); } else if (asyncgen->m_status == status_Finished) { RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); result = NULL; } else { if (exception_tb == NULL) { // TODO: Our compiled objects really need a way to store common // stuff in a "shared" part across all instances, and outside of // run time, so we could reuse this. struct Nuitka_FrameObject *frame = MAKE_FUNCTION_FRAME(asyncgen->m_code_object, asyncgen->m_module, 0); exception_tb = MAKE_TRACEBACK(frame, asyncgen->m_code_object->co_firstlineno); Py_DECREF(frame); } RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Finishing from exception", asyncgen); PRINT_NEW_LINE(); #endif asyncgen->m_status = status_Finished; result = NULL; } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_COROUTINE_VALUE("yieldfrom", asyncgen->m_yieldfrom); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_Asyncgen_throw(struct Nuitka_AsyncgenObject *asyncgen, PyObject *args) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_DEEP(args); PyObject *exception_type; PyObject *exception_value = NULL; PyTracebackObject *exception_tb = NULL; // This takes no references, that is for us to do. int res = PyArg_UnpackTuple(args, "throw", 1, 3, &exception_type, &exception_value, &exception_tb); if (unlikely(res == 0)) { return NULL; } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif // Handing ownership of exception over, we need not release it ourselves Py_INCREF(exception_type); Py_XINCREF(exception_value); Py_XINCREF(exception_tb); PyObject *result = _Nuitka_Asyncgen_throw2(asyncgen, false, exception_type, exception_value, exception_tb); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); } } #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_COROUTINE_VALUE("return value", result); PRINT_CURRENT_EXCEPTION(); #endif CHECK_OBJECT(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); return result; } static int Nuitka_Asyncgen_init_hooks(struct Nuitka_AsyncgenObject *asyncgen) { /* Just do this once per async generator object. */ if (asyncgen->m_hooks_init_done) { return 0; } asyncgen->m_hooks_init_done = 1; PyThreadState *tstate = PyThreadState_GET(); /* Attach the finalizer if any. */ PyObject *finalizer = tstate->async_gen_finalizer; if (finalizer != NULL) { Py_INCREF(finalizer); asyncgen->m_finalizer = finalizer; } /* Call the "firstiter" hook for async generator. */ PyObject *firstiter = tstate->async_gen_firstiter; if (firstiter != NULL) { Py_INCREF(firstiter); PyObject *res = CALL_FUNCTION_WITH_SINGLE_ARG(firstiter, (PyObject *)asyncgen); Py_DECREF(firstiter); if (unlikely(res == NULL)) { return 1; } Py_DECREF(res); } return 0; } static PyObject *Nuitka_AsyncgenAsend_New(struct Nuitka_AsyncgenObject *asyncgen, PyObject *sendval); static PyObject *Nuitka_AsyncgenAthrow_New(struct Nuitka_AsyncgenObject *asyncgen, PyObject *args); static PyObject *Nuitka_Asyncgen_anext(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); PRINT_NEW_LINE(); #endif if (Nuitka_Asyncgen_init_hooks(asyncgen)) { return NULL; } PyObject *result = Nuitka_AsyncgenAsend_New(asyncgen, Py_None); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_COROUTINE_VALUE("result", result); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_Asyncgen_asend(struct Nuitka_AsyncgenObject *asyncgen, PyObject *value) { CHECK_OBJECT(asyncgen); if (Nuitka_Asyncgen_init_hooks(asyncgen)) { return NULL; } return Nuitka_AsyncgenAsend_New(asyncgen, value); } static PyObject *Nuitka_Asyncgen_aclose(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); if (Nuitka_Asyncgen_init_hooks(asyncgen)) { return NULL; } return Nuitka_AsyncgenAthrow_New(asyncgen, NULL); } static PyObject *Nuitka_Asyncgen_athrow(struct Nuitka_AsyncgenObject *asyncgen, PyObject *args) { CHECK_OBJECT(asyncgen); if (Nuitka_Asyncgen_init_hooks(asyncgen)) { return NULL; } return Nuitka_AsyncgenAthrow_New(asyncgen, args); } #if PYTHON_VERSION >= 0x3a0 static PySendResult _Nuitka_Asyncgen_amsend(struct Nuitka_AsyncgenObject *asyncgen, PyObject *arg, PyObject **result) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Enter", asyncgen); #endif *result = NULL; PySendResult res = _Nuitka_Asyncgen_sendR(asyncgen, arg, false, NULL, NULL, NULL, result); #if _DEBUG_ASYNCGEN PRINT_ASYNCGEN_STATUS("Leave", asyncgen); PRINT_COROUTINE_VALUE("result", *result); PRINT_NEW_LINE(); #endif return res; } #endif static void Nuitka_Asyncgen_tp_finalize(struct Nuitka_AsyncgenObject *asyncgen) { if (asyncgen->m_status != status_Running) { return; } PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); bool close_result = _Nuitka_Asyncgen_close(asyncgen); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)asyncgen); } /* Restore the saved exception if any. */ RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } #define MAX_ASYNCGEN_FREE_LIST_COUNT 100 static struct Nuitka_AsyncgenObject *free_list_asyncgens = NULL; static int free_list_asyncgens_count = 0; // TODO: This might have to be finalize actually. static void Nuitka_Asyncgen_tp_dealloc(struct Nuitka_AsyncgenObject *asyncgen) { #if _DEBUG_REFCOUNTS count_active_Nuitka_Asyncgen_Type -= 1; count_released_Nuitka_Asyncgen_Type += 1; #endif // Revive temporarily. assert(Py_REFCNT(asyncgen) == 0); Py_REFCNT(asyncgen) = 1; // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; PyObject *finalizer = asyncgen->m_finalizer; if (finalizer != NULL && asyncgen->m_closed == false) { /* Save the current exception, if any. */ FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); PyObject *res = CALL_FUNCTION_WITH_SINGLE_ARG(finalizer, (PyObject *)asyncgen); if (unlikely(res == NULL)) { PyErr_WriteUnraisable((PyObject *)asyncgen); } else { Py_DECREF(res); } RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); return; } FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); bool close_result = _Nuitka_Asyncgen_close(asyncgen); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)asyncgen); } Nuitka_Asyncgen_release_closure(asyncgen); // Allow for above code to resurrect the coroutine. Py_REFCNT(asyncgen) -= 1; if (Py_REFCNT(asyncgen) >= 1) { return; } if (asyncgen->m_frame) { asyncgen->m_frame->m_frame.f_gen = NULL; Py_DECREF(asyncgen->m_frame); asyncgen->m_frame = NULL; } // Now it is safe to release references and memory for it. Nuitka_GC_UnTrack(asyncgen); Py_XDECREF(asyncgen->m_finalizer); if (asyncgen->m_weakrefs != NULL) { PyObject_ClearWeakRefs((PyObject *)asyncgen); assert(!ERROR_OCCURRED()); } Py_DECREF(asyncgen->m_name); Py_DECREF(asyncgen->m_qualname); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_asyncgens, asyncgen, MAX_ASYNCGEN_FREE_LIST_COUNT); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } static PyObject *Nuitka_Asyncgen_tp_repr(struct Nuitka_AsyncgenObject *asyncgen) { CHECK_OBJECT(asyncgen); return PyUnicode_FromFormat("", Nuitka_String_AsString(asyncgen->m_qualname), asyncgen); } static int Nuitka_Asyncgen_tp_traverse(struct Nuitka_AsyncgenObject *asyncgen, visitproc visit, void *arg) { CHECK_OBJECT(asyncgen); Py_VISIT(asyncgen->m_yieldfrom); for (Py_ssize_t i = 0; i < asyncgen->m_closure_given; i++) { Py_VISIT(asyncgen->m_closure[i]); } Py_VISIT(asyncgen->m_frame); Py_VISIT(asyncgen->m_finalizer); return 0; } // TODO: Set "__doc__" automatically for method clones of compiled types from // the documentation of built-in original type. static PyMethodDef Nuitka_Asyncgen_methods[] = {{"asend", (PyCFunction)Nuitka_Asyncgen_asend, METH_O, NULL}, {"athrow", (PyCFunction)Nuitka_Asyncgen_athrow, METH_VARARGS, NULL}, {"aclose", (PyCFunction)Nuitka_Asyncgen_aclose, METH_NOARGS, NULL}, {NULL}}; static PyAsyncMethods Nuitka_Asyncgen_as_async = { 0, /* am_await */ PyObject_SelfIter, /* am_aiter */ (unaryfunc)Nuitka_Asyncgen_anext /* am_anext */ #if PYTHON_VERSION >= 0x3a0 , (sendfunc)_Nuitka_Asyncgen_amsend /* am_anext */ #endif }; // TODO: Set "__doc__" automatically for method clones of compiled types from // the documentation of built-in original type. static PyGetSetDef Nuitka_Asyncgen_getsetlist[] = { {(char *)"__name__", (getter)Nuitka_Asyncgen_get_name, (setter)Nuitka_Asyncgen_set_name, NULL}, {(char *)"__qualname__", (getter)Nuitka_Asyncgen_get_qualname, (setter)Nuitka_Asyncgen_set_qualname, NULL}, {(char *)"ag_await", (getter)Nuitka_Asyncgen_get_ag_await, (setter)NULL, NULL}, {(char *)"ag_code", (getter)Nuitka_Asyncgen_get_code, (setter)Nuitka_Asyncgen_set_code, NULL}, {(char *)"ag_frame", (getter)Nuitka_Asyncgen_get_frame, (setter)Nuitka_Asyncgen_set_frame, NULL}, {NULL}}; static PyMemberDef Nuitka_Asyncgen_members[] = { {(char *)"ag_running", T_BOOL, offsetof(struct Nuitka_AsyncgenObject, m_running), READONLY}, #if PYTHON_VERSION >= 0x380 {(char *)"ag_running", T_BOOL, offsetof(struct Nuitka_AsyncgenObject, m_running_async), READONLY}, #endif {NULL}}; PyTypeObject Nuitka_Asyncgen_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_async_generator", /* tp_name */ sizeof(struct Nuitka_AsyncgenObject), /* tp_basicsize */ sizeof(struct Nuitka_CellObject *), /* tp_itemsize */ (destructor)Nuitka_Asyncgen_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ &Nuitka_Asyncgen_as_async, /* tp_as_async */ (reprfunc)Nuitka_Asyncgen_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Nuitka_Asyncgen_tp_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Asyncgen_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(struct Nuitka_AsyncgenObject, m_weakrefs), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Asyncgen_methods, /* tp_methods */ Nuitka_Asyncgen_members, /* tp_members */ Nuitka_Asyncgen_getsetlist, /* tp_getset */ #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyAsyncGen_Type, /* tp_base */ #else 0, /* tp_base */ #endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ (destructor)Nuitka_Asyncgen_tp_finalize, /* tp_finalize */ }; PyObject *Nuitka_Asyncgen_New(asyncgen_code code, PyObject *module, PyObject *name, PyObject *qualname, PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size) { #if _DEBUG_REFCOUNTS count_active_Nuitka_Asyncgen_Type += 1; count_allocated_Nuitka_Asyncgen_Type += 1; #endif struct Nuitka_AsyncgenObject *result; // TODO: Change the var part of the type to 1 maybe Py_ssize_t full_size = closure_given + (heap_storage_size + sizeof(void *) - 1) / sizeof(void *); // Macro to assign result memory from GC or free list. allocateFromFreeList(free_list_asyncgens, struct Nuitka_AsyncgenObject, Nuitka_Asyncgen_Type, full_size); // For quicker access of generator heap. result->m_heap_storage = &result->m_closure[closure_given]; result->m_code = (void *)code; CHECK_OBJECT(module); result->m_module = module; CHECK_OBJECT(name); result->m_name = name; Py_INCREF(name); // The "qualname" defaults to NULL for most compact C code. if (qualname == NULL) { qualname = name; } CHECK_OBJECT(qualname); result->m_qualname = qualname; Py_INCREF(qualname); result->m_yieldfrom = NULL; memcpy(&result->m_closure[0], closure, closure_given * sizeof(struct Nuitka_CellObject *)); result->m_closure_given = closure_given; result->m_weakrefs = NULL; result->m_status = status_Unused; result->m_running = false; result->m_awaiting = false; #if PYTHON_VERSION >= 0x380 result->m_running_async = false; #endif result->m_yield_return_index = 0; result->m_frame = NULL; result->m_code_object = code_object; result->m_resume_frame = NULL; result->m_finalizer = NULL; result->m_hooks_init_done = false; result->m_closed = false; #if PYTHON_VERSION >= 0x370 result->m_exc_state.exc_type = NULL; result->m_exc_state.exc_value = NULL; result->m_exc_state.exc_traceback = NULL; #endif static long Nuitka_Asyncgen_counter = 0; result->m_counter = Nuitka_Asyncgen_counter++; Nuitka_GC_Track(result); return (PyObject *)result; } struct Nuitka_AsyncgenWrappedValueObject { /* Python object folklore: */ PyObject_HEAD PyObject *m_value; }; static struct Nuitka_AsyncgenWrappedValueObject *free_list_asyncgen_value_wrappers = NULL; static int free_list_asyncgen_value_wrappers_count = 0; static void Nuitka_AsyncgenValueWrapper_tp_dealloc(struct Nuitka_AsyncgenWrappedValueObject *asyncgen_value_wrapper) { #if _DEBUG_REFCOUNTS count_active_Nuitka_AsyncgenValueWrapper_Type -= 1; count_released_Nuitka_AsyncgenValueWrapper_Type += 1; #endif Nuitka_GC_UnTrack((PyObject *)asyncgen_value_wrapper); CHECK_OBJECT(asyncgen_value_wrapper->m_value); Py_DECREF(asyncgen_value_wrapper->m_value); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_asyncgen_value_wrappers, asyncgen_value_wrapper, MAX_ASYNCGEN_FREE_LIST_COUNT); } static int Nuitka_AsyncgenValueWrapper_tp_traverse(struct Nuitka_AsyncgenWrappedValueObject *asyncgen_value_wrapper, visitproc visit, void *arg) { CHECK_OBJECT(asyncgen_value_wrapper); Py_VISIT(asyncgen_value_wrapper->m_value); return 0; } static PyTypeObject Nuitka_AsyncgenValueWrapper_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_async_generator_wrapped_value", /* tp_name */ sizeof(struct Nuitka_AsyncgenWrappedValueObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_AsyncgenValueWrapper_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_AsyncgenValueWrapper_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; // Note: This expects a reference given in value, because that is the // only way we use it. static PyObject *Nuitka_AsyncgenValueWrapper_New(PyObject *value) { CHECK_OBJECT(value); #if _DEBUG_REFCOUNTS count_active_Nuitka_AsyncgenValueWrapper_Type -= 1; count_released_Nuitka_AsyncgenValueWrapper_Type += 1; #endif struct Nuitka_AsyncgenWrappedValueObject *result; allocateFromFreeListFixed(free_list_asyncgen_value_wrappers, struct Nuitka_AsyncgenWrappedValueObject, Nuitka_AsyncgenValueWrapper_Type); result->m_value = value; Nuitka_GC_Track(result); return (PyObject *)result; } #define Nuitka_AsyncgenWrappedValue_CheckExact(o) (Py_TYPE(o) == &Nuitka_AsyncgenValueWrapper_Type) typedef enum { AWAITABLE_STATE_INIT = 0, /* Has not yet been iterated. */ AWAITABLE_STATE_ITER = 1, /* Being iterated currently. */ AWAITABLE_STATE_CLOSED = 2, /* Closed, no more. */ } AwaitableState; struct Nuitka_AsyncgenAsendObject { /* Python object folklore: */ PyObject_HEAD struct Nuitka_AsyncgenObject *m_gen; PyObject *m_sendval; AwaitableState m_state; }; #if _DEBUG_ASYNCGEN NUITKA_MAY_BE_UNUSED static void _PRINT_ASYNCGENASEND_STATUS(char const *descriptor, char const *context, struct Nuitka_AsyncgenAsendObject *asyncgen_asend) { char const *status; switch (asyncgen_asend->m_state) { case AWAITABLE_STATE_INIT: status = "(init)"; break; case AWAITABLE_STATE_ITER: status = "(iter)"; break; case AWAITABLE_STATE_CLOSED: status = "(closed)"; break; default: status = "(ILLEGAL)"; break; } PRINT_STRING(descriptor); PRINT_STRING(" : "); PRINT_STRING(context); PRINT_STRING(" "); PRINT_ITEM((PyObject *)asyncgen_asend); PRINT_STRING(" "); PRINT_STRING(status); PRINT_NEW_LINE(); } #define PRINT_ASYNCGENASEND_STATUS(context, asyncgen_asend) \ _PRINT_ASYNCGENASEND_STATUS(__FUNCTION__, context, asyncgen_asend) #endif /** * These can be created by byte code loop, and we don't now its internals, * yet we have to unwrap ourselves too. These could break in future updates, * and ideally we would have checks to cover those. */ struct _PyAsyncGenWrappedValue { /* Python object folklore: */ PyObject_HEAD PyObject *agw_val; }; #define _PyAsyncGenWrappedValue_CheckExact(o) (Py_TYPE(o) == &_PyAsyncGenWrappedValue_Type) static PyObject *Nuitka_Asyncgen_unwrap_value(struct Nuitka_AsyncgenObject *asyncgen, PyObject *result) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(result); if (result == NULL) { PyObject *error = GET_ERROR_OCCURRED(); if (error == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); asyncgen->m_closed = true; } else if (EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopAsyncIteration) || EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_GeneratorExit)) { asyncgen->m_closed = true; } #if PYTHON_VERSION >= 0x380 asyncgen->m_running_async = false; #endif return NULL; } if (_PyAsyncGenWrappedValue_CheckExact(result)) { /* async yield */ _PyGen_SetStopIterationValue(((struct _PyAsyncGenWrappedValue *)result)->agw_val); Py_DECREF(result); #if PYTHON_VERSION >= 0x380 asyncgen->m_running_async = false; #endif return NULL; } else if (Nuitka_AsyncgenWrappedValue_CheckExact(result)) { /* async yield */ _PyGen_SetStopIterationValue(((struct Nuitka_AsyncgenWrappedValueObject *)result)->m_value); Py_DECREF(result); #if PYTHON_VERSION >= 0x380 asyncgen->m_running_async = false; #endif return NULL; } return result; } static struct Nuitka_AsyncgenAsendObject *free_list_asyncgen_asends = NULL; static int free_list_asyncgen_asends_count = 0; static void Nuitka_AsyncgenAsend_tp_dealloc(struct Nuitka_AsyncgenAsendObject *asyncgen_asend) { #if _DEBUG_REFCOUNTS count_active_Nuitka_AsyncgenAsend_Type -= 1; count_released_Nuitka_AsyncgenAsend_Type += 1; #endif Nuitka_GC_UnTrack(asyncgen_asend); CHECK_OBJECT(asyncgen_asend->m_gen); Py_DECREF(asyncgen_asend->m_gen); CHECK_OBJECT(asyncgen_asend->m_sendval); Py_DECREF(asyncgen_asend->m_sendval); releaseToFreeList(free_list_asyncgen_asends, asyncgen_asend, MAX_ASYNCGEN_FREE_LIST_COUNT); } static int Nuitka_AsyncgenAsend_tp_traverse(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, visitproc visit, void *arg) { CHECK_OBJECT(asyncgen_asend); CHECK_OBJECT(asyncgen_asend->m_gen); CHECK_OBJECT(asyncgen_asend->m_sendval); Py_VISIT(asyncgen_asend->m_gen); Py_VISIT(asyncgen_asend->m_sendval); return 0; } static PyObject *Nuitka_AsyncgenAsend_send(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *arg) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Enter", asyncgen_asend); PRINT_COROUTINE_VALUE("arg", arg); PRINT_NEW_LINE(); #endif if (asyncgen_asend->m_state == AWAITABLE_STATE_CLOSED) { #if PYTHON_VERSION < 0x390 SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); #else SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cannot reuse already awaited __anext__()/asend()"); #endif #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Leave", asyncgen_asend); PRINT_STRING("Closed -> StopIteration\n"); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return NULL; } else if (asyncgen_asend->m_state == AWAITABLE_STATE_INIT) { #if PYTHON_VERSION >= 0x380 if (asyncgen_asend->m_gen->m_running_async) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "anext(): asynchronous generator is already running"); return NULL; } #endif if (arg == NULL || arg == Py_None) { arg = asyncgen_asend->m_sendval; } asyncgen_asend->m_state = AWAITABLE_STATE_ITER; #if _DEBUG_ASYNCGEN PRINT_STRING("Init -> begin iteration\n"); PRINT_COROUTINE_VALUE("computed arg from sendval", arg); PRINT_NEW_LINE(); #endif } #if PYTHON_VERSION >= 0x380 asyncgen_asend->m_gen->m_running_async = true; #endif // TODO: Who releases arg. // Py_INCREF(arg); #if _DEBUG_ASYNCGEN PRINT_STRING("Deferring to _Nuitka_Asyncgen_send\n"); PRINT_NEW_LINE(); #endif PyObject *result = _Nuitka_Asyncgen_send(asyncgen_asend->m_gen, arg, false, NULL, NULL, NULL); #if _DEBUG_ASYNCGEN PRINT_STRING("Returned from _Nuitka_Asyncgen_send\n"); PRINT_COROUTINE_VALUE("result", result); PRINT_CURRENT_EXCEPTION(); #endif result = Nuitka_Asyncgen_unwrap_value(asyncgen_asend->m_gen, result); #if _DEBUG_ASYNCGEN PRINT_COROUTINE_VALUE("result", result); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif if (result == NULL) { asyncgen_asend->m_state = AWAITABLE_STATE_CLOSED; } #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Leave", asyncgen_asend); PRINT_COROUTINE_VALUE("result", result); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_AsyncgenAsend_tp_iternext(struct Nuitka_AsyncgenAsendObject *asyncgen_asend) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Enter", asyncgen_asend); PRINT_STRING("Deferring to Nuitka_AsyncgenAsend_send(Py_None)\n"); PRINT_NEW_LINE(); #endif PyObject *result = Nuitka_AsyncgenAsend_send(asyncgen_asend, Py_None); #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Leave", asyncgen_asend); PRINT_COROUTINE_VALUE("result", result); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_AsyncgenAsend_throw(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *args) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Enter", asyncgen_asend); PRINT_STRING("Nuitka_AsyncgenAsend_throw: args:"); PRINT_ITEM(args); PRINT_NEW_LINE(); PRINT_STRING("Nuitka_AsyncgenAsend_throw: On entry: "); PRINT_CURRENT_EXCEPTION(); #endif if (asyncgen_asend->m_state == AWAITABLE_STATE_CLOSED) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); return NULL; } PyObject *result = Nuitka_Asyncgen_throw(asyncgen_asend->m_gen, args); #if _DEBUG_ASYNCGEN PRINT_STRING("Nuitka_AsyncgenAsend_throw: Async throw result:"); PRINT_ITEM(result); PRINT_STRING(" exception: "); PRINT_CURRENT_EXCEPTION(); #endif result = Nuitka_Asyncgen_unwrap_value(asyncgen_asend->m_gen, result); if (result == NULL) { asyncgen_asend->m_state = AWAITABLE_STATE_CLOSED; } #if _DEBUG_ASYNCGEN PRINT_STRING("Nuitka_AsyncgenAsend_throw: Leave with result: "); PRINT_ITEM(result); PRINT_NEW_LINE(); PRINT_STRING("Nuitka_AsyncgenAsend_throw: Leave with exception: "); PRINT_CURRENT_EXCEPTION(); PRINT_STRING("Nuitka_AsyncgenAsend_throw: Leave with exception: "); PRINT_PUBLISHED_EXCEPTION(); PRINT_NEW_LINE(); #endif CHECK_OBJECT_DEEP(args); return result; } static PyObject *_Nuitka_AsyncgenAsend_throw2(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Enter", asyncgen_asend); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif if (asyncgen_asend->m_state == AWAITABLE_STATE_CLOSED) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); return NULL; } PyObject *result = _Nuitka_Asyncgen_throw2(asyncgen_asend->m_gen, false, exception_type, exception_value, exception_tb); // TODO: This might not be all that necessary as this is not directly outside facing, // but there were tests failing when this was not the specific value. if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); } } #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Got result", asyncgen_asend); PRINT_COROUTINE_VALUE("result", result); PRINT_CURRENT_EXCEPTION(); #endif result = Nuitka_Asyncgen_unwrap_value(asyncgen_asend->m_gen, result); #if _DEBUG_ASYNCGEN PRINT_COROUTINE_VALUE("unwrapped", result); PRINT_NEW_LINE(); #endif if (result == NULL) { asyncgen_asend->m_state = AWAITABLE_STATE_CLOSED; } #if _DEBUG_ASYNCGEN PRINT_ASYNCGENASEND_STATUS("Leave", asyncgen_asend); PRINT_COROUTINE_VALUE("result", result); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_AsyncgenAsend_close(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *args) { asyncgen_asend->m_state = AWAITABLE_STATE_CLOSED; Py_INCREF(Py_None); return Py_None; } static PyObject *Nuitka_AsyncgenAsend_tp_repr(struct Nuitka_AsyncgenAsendObject *asyncgen_asend) { return PyUnicode_FromFormat("", Nuitka_String_AsString(asyncgen_asend->m_gen->m_qualname), asyncgen_asend); } static PyMethodDef Nuitka_AsyncgenAsend_methods[] = { {"send", (PyCFunction)Nuitka_AsyncgenAsend_send, METH_O, NULL}, {"throw", (PyCFunction)Nuitka_AsyncgenAsend_throw, METH_VARARGS, NULL}, {"close", (PyCFunction)Nuitka_AsyncgenAsend_close, METH_NOARGS, NULL}, {NULL}}; static PyAsyncMethods Nuitka_AsyncgenAsend_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ }; static PyTypeObject Nuitka_AsyncgenAsend_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_async_generator_asend", /* tp_name */ sizeof(struct Nuitka_AsyncgenAsendObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_AsyncgenAsend_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ &Nuitka_AsyncgenAsend_as_async, /* tp_as_async */ (reprfunc)Nuitka_AsyncgenAsend_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_AsyncgenAsend_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)Nuitka_AsyncgenAsend_tp_iternext, /* tp_iternext */ Nuitka_AsyncgenAsend_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static bool Nuitka_AsyncgenAsend_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_AsyncgenAsend_Type; } static PyObject *Nuitka_AsyncgenAsend_New(struct Nuitka_AsyncgenObject *asyncgen, PyObject *send_value) { CHECK_OBJECT(asyncgen); CHECK_OBJECT(send_value); #if _DEBUG_REFCOUNTS count_active_Nuitka_AsyncgenAsend_Type += 1; count_allocated_Nuitka_AsyncgenAsend_Type += 1; #endif struct Nuitka_AsyncgenAsendObject *result; allocateFromFreeListFixed(free_list_asyncgen_asends, struct Nuitka_AsyncgenAsendObject, Nuitka_AsyncgenAsend_Type); Py_INCREF(asyncgen); result->m_gen = asyncgen; Py_INCREF(send_value); result->m_sendval = send_value; result->m_state = AWAITABLE_STATE_INIT; Nuitka_GC_Track(result); return (PyObject *)result; } struct Nuitka_AsyncgenAthrowObject { /* Python object folklore: */ PyObject_HEAD // The asyncgen we are working for. struct Nuitka_AsyncgenObject *m_gen; // Arguments, NULL in case of close, otherwise throw arguments. PyObject *m_args; AwaitableState m_state; }; #if _DEBUG_ASYNCGEN NUITKA_MAY_BE_UNUSED static void _PRINT_ASYNCGENATHROW_STATUS(char const *descriptor, char const *context, struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow) { char const *status; switch (asyncgen_athrow->m_state) { case AWAITABLE_STATE_INIT: status = "(init)"; break; case AWAITABLE_STATE_ITER: status = "(iter)"; break; case AWAITABLE_STATE_CLOSED: status = "(closed)"; break; default: status = "(ILLEGAL)"; break; } PRINT_STRING(descriptor); PRINT_STRING(" : "); PRINT_STRING(context); PRINT_STRING(" "); PRINT_ITEM((PyObject *)asyncgen_athrow); PRINT_STRING(" "); PRINT_STRING(status); PRINT_NEW_LINE(); } #define PRINT_ASYNCGENATHROW_STATUS(context, coroutine) \ _PRINT_ASYNCGENATHROW_STATUS(__FUNCTION__, context, asyncgen_athrow) #endif static struct Nuitka_AsyncgenAthrowObject *free_list_asyncgen_athrows = NULL; static int free_list_asyncgen_athrows_count = 0; static void Nuitka_AsyncgenAthrow_dealloc(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow) { #if _DEBUG_REFCOUNTS count_active_Nuitka_AIterWrapper_Type -= 1; count_released_Nuitka_AIterWrapper_Type += 1; #endif Nuitka_GC_UnTrack(asyncgen_athrow); CHECK_OBJECT(asyncgen_athrow->m_gen); Py_DECREF(asyncgen_athrow->m_gen); CHECK_OBJECT_X(asyncgen_athrow->m_args); Py_XDECREF(asyncgen_athrow->m_args); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_asyncgen_athrows, asyncgen_athrow, MAX_ASYNCGEN_FREE_LIST_COUNT); } static int Nuitka_AsyncgenAthrow_traverse(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow, visitproc visit, void *arg) { Py_VISIT(asyncgen_athrow->m_gen); Py_VISIT(asyncgen_athrow->m_args); return 0; } static PyObject *Nuitka_AsyncgenAthrow_send(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow, PyObject *arg) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENATHROW_STATUS("Enter", asyncgen_athrow); PRINT_COROUTINE_VALUE("arg", arg); PRINT_NEW_LINE(); #endif struct Nuitka_AsyncgenObject *asyncgen = asyncgen_athrow->m_gen; // Closing twice is not allowed with 3.9 or higher. if (asyncgen_athrow->m_state == AWAITABLE_STATE_CLOSED) { #if PYTHON_VERSION < 0x390 SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); #else SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cannot reuse already awaited aclose()/athrow()"); #endif return NULL; } // If finished, just report StopIteration. if (asyncgen->m_status == status_Finished) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); return NULL; } PyObject *retval; if (asyncgen_athrow->m_state == AWAITABLE_STATE_INIT) { #if PYTHON_VERSION >= 0x380 if (asyncgen_athrow->m_gen->m_running_async) { if (asyncgen_athrow->m_args == NULL) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "aclose(): asynchronous generator is already running"); } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "athrow(): asynchronous generator is already running"); } return NULL; } #endif // Can also close only once. if (asyncgen->m_closed) { #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_state = AWAITABLE_STATE_CLOSED; SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopAsyncIteration); #else SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); #endif return NULL; } // Starting accepts only "None" as input value. if (arg != Py_None) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "can't send non-None value to a just-started coroutine"); return NULL; } #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_gen->m_running_async = true; #endif asyncgen_athrow->m_state = AWAITABLE_STATE_ITER; if (asyncgen_athrow->m_args == NULL) { asyncgen->m_closed = true; Py_INCREF(PyExc_GeneratorExit); retval = _Nuitka_Asyncgen_throw2(asyncgen, 1, /* Do not close generator when PyExc_GeneratorExit is passed */ PyExc_GeneratorExit, NULL, NULL); if (retval) { if (_PyAsyncGenWrappedValue_CheckExact(retval) || Nuitka_AsyncgenWrappedValue_CheckExact(retval)) { #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_gen->m_running_async = false; #endif Py_DECREF(retval); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator ignored GeneratorExit"); return NULL; } } } else { PyObject *exception_type; PyObject *exception_value = NULL; PyTracebackObject *exception_tb = NULL; if (unlikely(!PyArg_UnpackTuple(asyncgen_athrow->m_args, "athrow", 1, 3, &exception_type, &exception_value, &exception_tb))) { return NULL; } // Handing ownership of exception over, we need not release it ourselves Py_INCREF(exception_type); Py_XINCREF(exception_value); Py_XINCREF(exception_tb); retval = _Nuitka_Asyncgen_throw2(asyncgen, 0, /* Do not close generator when PyExc_GeneratorExit is passed */ exception_type, exception_value, exception_tb); retval = Nuitka_Asyncgen_unwrap_value(asyncgen, retval); } if (retval == NULL) { goto check_error; } return retval; } assert(asyncgen_athrow->m_state == AWAITABLE_STATE_ITER); retval = _Nuitka_Asyncgen_send(asyncgen, arg, false, NULL, NULL, NULL); if (asyncgen_athrow->m_args) { return Nuitka_Asyncgen_unwrap_value(asyncgen, retval); } else { /* We are here to close if no args. */ if (retval) { if (_PyAsyncGenWrappedValue_CheckExact(retval) || Nuitka_AsyncgenWrappedValue_CheckExact(retval)) { #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_gen->m_running_async = false; #endif Py_DECREF(retval); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator ignored GeneratorExit"); return NULL; } return retval; } } check_error: #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_gen->m_running_async = false; #endif if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) { asyncgen_athrow->m_state = AWAITABLE_STATE_CLOSED; if (asyncgen_athrow->m_args == NULL) { CLEAR_ERROR_OCCURRED(); SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } else if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) { asyncgen_athrow->m_state = AWAITABLE_STATE_CLOSED; #if PYTHON_VERSION >= 0x380 if (asyncgen_athrow->m_args == NULL) { #endif CLEAR_ERROR_OCCURRED(); SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); #if PYTHON_VERSION >= 0x380 } #endif } return NULL; } static PyObject *Nuitka_AsyncgenAthrow_throw(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow, PyObject *args) { #if _DEBUG_ASYNCGEN PRINT_ASYNCGENATHROW_STATUS("Enter", asyncgen_athrow); PRINT_COROUTINE_VALUE("args", args); PRINT_NEW_LINE(); #endif PyObject *retval; #if PYTHON_VERSION < 0x375 if (asyncgen_athrow->m_state == AWAITABLE_STATE_INIT) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "can't send non-None value to a just-started coroutine"); return NULL; } #endif if (asyncgen_athrow->m_state == AWAITABLE_STATE_CLOSED) { #if PYTHON_VERSION < 0x390 SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); #else SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cannot reuse already awaited aclose()/athrow()"); #endif return NULL; } retval = Nuitka_Asyncgen_throw(asyncgen_athrow->m_gen, args); if (asyncgen_athrow->m_args) { return Nuitka_Asyncgen_unwrap_value(asyncgen_athrow->m_gen, retval); } else { if (retval != NULL) { if (_PyAsyncGenWrappedValue_CheckExact(retval) || Nuitka_AsyncgenWrappedValue_CheckExact(retval)) { #if PYTHON_VERSION >= 0x380 asyncgen_athrow->m_gen->m_running_async = false; #endif Py_DECREF(retval); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "async generator ignored GeneratorExit"); return NULL; } } #if PYTHON_VERSION >= 0x390 if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) || PyErr_ExceptionMatches(PyExc_GeneratorExit)) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } #endif return retval; } } static PyObject *Nuitka_AsyncgenAthrow_tp_iternext(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow) { return Nuitka_AsyncgenAthrow_send(asyncgen_athrow, Py_None); } static PyObject *Nuitka_AsyncgenAthrow_close(struct Nuitka_AsyncgenAthrowObject *asyncgen_athrow) { asyncgen_athrow->m_state = AWAITABLE_STATE_CLOSED; Py_INCREF(Py_None); return Py_None; } static PyMethodDef Nuitka_AsyncgenAthrow_methods[] = { {"send", (PyCFunction)Nuitka_AsyncgenAthrow_send, METH_O, NULL}, {"throw", (PyCFunction)Nuitka_AsyncgenAthrow_throw, METH_VARARGS, NULL}, {"close", (PyCFunction)Nuitka_AsyncgenAthrow_close, METH_NOARGS, NULL}, {NULL}}; static PyAsyncMethods Nuitka_AsyncgenAthrow_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ }; static PyTypeObject Nuitka_AsyncgenAthrow_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_async_generator_athrow", /* tp_name */ sizeof(struct Nuitka_AsyncgenAthrowObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_AsyncgenAthrow_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ &Nuitka_AsyncgenAthrow_as_async, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_AsyncgenAthrow_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)Nuitka_AsyncgenAthrow_tp_iternext, /* tp_iternext */ Nuitka_AsyncgenAthrow_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ }; static PyObject *Nuitka_AsyncgenAthrow_New(struct Nuitka_AsyncgenObject *asyncgen, PyObject *args) { CHECK_OBJECT(asyncgen); CHECK_OBJECT_X(args); #if _DEBUG_REFCOUNTS count_active_Nuitka_AsyncgenAthrow_Type += 1; count_allocated_Nuitka_AsyncgenAthrow_Type += 1; #endif struct Nuitka_AsyncgenAthrowObject *result; allocateFromFreeListFixed(free_list_asyncgen_athrows, struct Nuitka_AsyncgenAthrowObject, Nuitka_AsyncgenAthrow_Type); Py_INCREF(asyncgen); result->m_gen = asyncgen; Py_XINCREF(args); result->m_args = args; result->m_state = AWAITABLE_STATE_INIT; Nuitka_GC_Track(result); return (PyObject *)result; } static void _initCompiledAsyncgenTypes(void) { PyType_Ready(&Nuitka_Asyncgen_Type); // Be a paranoid subtype of uncompiled function, we want nothing shared. assert(Nuitka_Asyncgen_Type.tp_doc != PyAsyncGen_Type.tp_doc || PyAsyncGen_Type.tp_doc == NULL); assert(Nuitka_Asyncgen_Type.tp_traverse != PyAsyncGen_Type.tp_traverse); assert(Nuitka_Asyncgen_Type.tp_clear != PyAsyncGen_Type.tp_clear || PyAsyncGen_Type.tp_clear == NULL); assert(Nuitka_Asyncgen_Type.tp_richcompare != PyAsyncGen_Type.tp_richcompare || PyAsyncGen_Type.tp_richcompare == NULL); assert(Nuitka_Asyncgen_Type.tp_weaklistoffset != PyAsyncGen_Type.tp_weaklistoffset); assert(Nuitka_Asyncgen_Type.tp_iter != PyAsyncGen_Type.tp_iter || PyAsyncGen_Type.tp_iter == NULL); assert(Nuitka_Asyncgen_Type.tp_iternext != PyAsyncGen_Type.tp_iternext || PyAsyncGen_Type.tp_iternext == NULL); assert(Nuitka_Asyncgen_Type.tp_methods != PyAsyncGen_Type.tp_methods); assert(Nuitka_Asyncgen_Type.tp_members != PyAsyncGen_Type.tp_members); assert(Nuitka_Asyncgen_Type.tp_getset != PyAsyncGen_Type.tp_getset); #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) assert(Nuitka_Asyncgen_Type.tp_base != PyAsyncGen_Type.tp_base); #endif assert(Nuitka_Asyncgen_Type.tp_dict != PyAsyncGen_Type.tp_dict); assert(Nuitka_Asyncgen_Type.tp_descr_get != PyAsyncGen_Type.tp_descr_get || PyAsyncGen_Type.tp_descr_get == NULL); assert(Nuitka_Asyncgen_Type.tp_descr_set != PyAsyncGen_Type.tp_descr_set || PyAsyncGen_Type.tp_descr_set == NULL); assert(Nuitka_Asyncgen_Type.tp_dictoffset != PyAsyncGen_Type.tp_dictoffset || PyAsyncGen_Type.tp_dictoffset == 0); // TODO: These get changed and into the same thing, not sure what to compare against, project something // assert(Nuitka_Generator_Type.tp_init != PyAsyncGen_Type.tp_init || PyAsyncGen_Type.tp_init == NULL); // assert(Nuitka_Generator_Type.tp_alloc != PyAsyncGen_Type.tp_alloc || PyAsyncGen_Type.tp_alloc == NULL); // assert(Nuitka_Generator_Type.tp_new != PyAsyncGen_Type.tp_new || PyAsyncGen_Type.tp_new == NULL); // assert(Nuitka_Generator_Type.tp_free != PyAsyncGen_Type.tp_free || PyAsyncGen_Type.tp_free == NULL); assert(Nuitka_Asyncgen_Type.tp_bases != PyAsyncGen_Type.tp_bases); assert(Nuitka_Asyncgen_Type.tp_mro != PyAsyncGen_Type.tp_mro); assert(Nuitka_Asyncgen_Type.tp_cache != PyAsyncGen_Type.tp_cache || PyAsyncGen_Type.tp_cache == NULL); assert(Nuitka_Asyncgen_Type.tp_subclasses != PyAsyncGen_Type.tp_subclasses || PyAsyncGen_Type.tp_cache == NULL); assert(Nuitka_Asyncgen_Type.tp_weaklist != PyAsyncGen_Type.tp_weaklist); assert(Nuitka_Asyncgen_Type.tp_del != PyAsyncGen_Type.tp_del || PyAsyncGen_Type.tp_del == NULL); assert(Nuitka_Asyncgen_Type.tp_finalize != PyAsyncGen_Type.tp_finalize || PyAsyncGen_Type.tp_finalize == NULL); PyType_Ready(&Nuitka_AsyncgenAsend_Type); PyType_Ready(&Nuitka_AsyncgenAthrow_Type); PyType_Ready(&Nuitka_AsyncgenValueWrapper_Type); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersStrings.c0000600000372100037210000005354514166627112030153 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This helpers is used to quickly create a string object from C char. Currently this is used for string subscript code, but may also be used for the "char" C type in the future. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif PyObject *STRING_FROM_CHAR(unsigned char c) { // TODO: A switch statement might be faster, because no object needs to be // created at all, this here is how CPython does it. char s[1]; s[0] = (char)c; return Nuitka_String_FromStringAndSize(s, 1); } /* The "chr" built-in. This could also use a table for the interned single char strings, to be faster on Python2. For Python3 no such table is reasonable. */ PyObject *BUILTIN_CHR(PyObject *value) { long x = PyInt_AsLong(value); if (unlikely(x == -1 && ERROR_OCCURRED())) { #if PYTHON_VERSION < 0x300 && defined(_NUITKA_FULL_COMPAT) SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "an integer is required"); #else PyErr_Format(PyExc_TypeError, "an integer is required (got type %s)", Py_TYPE(value)->tp_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 if (unlikely(x < 0 || x >= 256)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "chr() arg not in range(256)"); return NULL; } // TODO: A switch statement might be faster, because no object needs to be // created at all, this is how CPython does it. char s[1]; s[0] = (char)x; return PyString_FromStringAndSize(s, 1); #else PyObject *result = PyUnicode_FromOrdinal(x); if (unlikely(result == NULL)) { return NULL; } assert(PyUnicode_Check(result)); return result; #endif } /* The "ord" built-in. */ PyObject *BUILTIN_ORD(PyObject *value) { long result; if (likely(PyBytes_Check(value))) { Py_ssize_t size = PyBytes_GET_SIZE(value); if (likely(size == 1)) { result = (long)(((unsigned char *)PyBytes_AS_STRING(value))[0]); } else { PyErr_Format(PyExc_TypeError, "ord() expected a character, but string of length %zd found", size); return NULL; } } else if (PyByteArray_Check(value)) { Py_ssize_t size = PyByteArray_GET_SIZE(value); if (likely(size == 1)) { result = (long)(((unsigned char *)PyByteArray_AS_STRING(value))[0]); } else { PyErr_Format(PyExc_TypeError, "ord() expected a character, but byte array of length " "%zd found", size); return NULL; } } else if (PyUnicode_Check(value)) { #if PYTHON_VERSION >= 0x300 if (unlikely(PyUnicode_READY(value) == -1)) { return NULL; } Py_ssize_t size = PyUnicode_GET_LENGTH(value); #else Py_ssize_t size = PyUnicode_GET_SIZE(value); #endif if (likely(size == 1)) { #if PYTHON_VERSION >= 0x300 result = (long)(PyUnicode_READ_CHAR(value, 0)); #else result = (long)(*PyUnicode_AS_UNICODE(value)); #endif } else { PyErr_Format(PyExc_TypeError, "ord() expected a character, but unicode string of " "length %zd found", size); return NULL; } } else { PyErr_Format(PyExc_TypeError, "ord() expected string of length 1, but %s found", Py_TYPE(value)->tp_name); return NULL; } return PyInt_FromLong(result); } #if PYTHON_VERSION >= 0x300 #define _PyUnicode_UTF8_LENGTH(op) (((PyCompactUnicodeObject *)(op))->utf8_length) #define PyUnicode_UTF8_LENGTH(op) \ (assert(_PyUnicode_CHECK(op)), assert(PyUnicode_IS_READY(op)), \ PyUnicode_IS_COMPACT_ASCII(op) ? ((PyASCIIObject *)(op))->length : _PyUnicode_UTF8_LENGTH(op)) #define _PyUnicode_WSTR(op) (((PyASCIIObject *)(op))->wstr) #define _PyUnicode_WSTR_LENGTH(op) (((PyCompactUnicodeObject *)(op))->wstr_length) #define _PyUnicode_LENGTH(op) (((PyASCIIObject *)(op))->length) #define _PyUnicode_STATE(op) (((PyASCIIObject *)(op))->state) #define _PyUnicode_HASH(op) (((PyASCIIObject *)(op))->hash) #define _PyUnicode_KIND(op) (((PyASCIIObject *)(op))->state.kind) #define _PyUnicode_DATA_ANY(op) (((PyUnicodeObject *)(op))->data.any) #undef PyUnicode_READY #define PyUnicode_READY(op) ((PyUnicode_IS_READY(op) ? 0 : _PyUnicode_Ready(op))) #define _PyUnicode_SHARE_UTF8(op) (assert(!PyUnicode_IS_COMPACT_ASCII(op)), (_PyUnicode_UTF8(op) == PyUnicode_DATA(op))) #define _PyUnicode_SHARE_WSTR(op) ((_PyUnicode_WSTR(unicode) == PyUnicode_DATA(op))) #define _PyUnicode_HAS_UTF8_MEMORY(op) \ ((!PyUnicode_IS_COMPACT_ASCII(op) && _PyUnicode_UTF8(op) && _PyUnicode_UTF8(op) != PyUnicode_DATA(op))) #define _PyUnicode_HAS_WSTR_MEMORY(op) \ ((_PyUnicode_WSTR(op) && (!PyUnicode_IS_READY(op) || _PyUnicode_WSTR(op) != PyUnicode_DATA(op)))) #define _PyUnicode_CONVERT_BYTES(from_type, to_type, begin, end, to) \ do { \ to_type *_to = (to_type *)(to); \ const from_type *_iter = (from_type *)(begin); \ const from_type *_end = (from_type *)(end); \ Py_ssize_t n = (_end) - (_iter); \ const from_type *_unrolled_end = _iter + _Py_SIZE_ROUND_DOWN(n, 4); \ while (_iter < (_unrolled_end)) { \ _to[0] = (to_type)_iter[0]; \ _to[1] = (to_type)_iter[1]; \ _to[2] = (to_type)_iter[2]; \ _to[3] = (to_type)_iter[3]; \ _iter += 4; \ _to += 4; \ } \ while (_iter < (_end)) \ *_to++ = (to_type)*_iter++; \ } while (0) extern int ucs1lib_find_max_char(const Py_UCS1 *begin, const Py_UCS1 *end); static void _NuitkaUnicode_FastCopyCharacters(PyObject *to, Py_ssize_t to_start, PyObject *from, Py_ssize_t from_start, Py_ssize_t how_many) { assert(from_start + how_many <= PyUnicode_GET_LENGTH(from)); assert(to_start + how_many <= PyUnicode_GET_LENGTH(to)); assert(how_many > 0); unsigned int from_kind = PyUnicode_KIND(from); void *from_data = PyUnicode_DATA(from); unsigned int to_kind = PyUnicode_KIND(to); void *to_data = PyUnicode_DATA(to); if (from_kind == to_kind) { memcpy((char *)to_data + to_kind * to_start, (char *)from_data + from_kind * from_start, to_kind * how_many); } else if (from_kind == PyUnicode_1BYTE_KIND && to_kind == PyUnicode_2BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS1, Py_UCS2, PyUnicode_1BYTE_DATA(from) + from_start, PyUnicode_1BYTE_DATA(from) + from_start + how_many, PyUnicode_2BYTE_DATA(to) + to_start); } else if (from_kind == PyUnicode_1BYTE_KIND && to_kind == PyUnicode_4BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS1, Py_UCS4, PyUnicode_1BYTE_DATA(from) + from_start, PyUnicode_1BYTE_DATA(from) + from_start + how_many, PyUnicode_4BYTE_DATA(to) + to_start); } else if (from_kind == PyUnicode_2BYTE_KIND && to_kind == PyUnicode_4BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS2, Py_UCS4, PyUnicode_2BYTE_DATA(from) + from_start, PyUnicode_2BYTE_DATA(from) + from_start + how_many, PyUnicode_4BYTE_DATA(to) + to_start); } else { assert(PyUnicode_MAX_CHAR_VALUE(from) > PyUnicode_MAX_CHAR_VALUE(to)); if (from_kind == PyUnicode_2BYTE_KIND && to_kind == PyUnicode_1BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS2, Py_UCS1, PyUnicode_2BYTE_DATA(from) + from_start, PyUnicode_2BYTE_DATA(from) + from_start + how_many, PyUnicode_1BYTE_DATA(to) + to_start); } else if (from_kind == PyUnicode_4BYTE_KIND && to_kind == PyUnicode_1BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS1, PyUnicode_4BYTE_DATA(from) + from_start, PyUnicode_4BYTE_DATA(from) + from_start + how_many, PyUnicode_1BYTE_DATA(to) + to_start); } else if (from_kind == PyUnicode_4BYTE_KIND && to_kind == PyUnicode_2BYTE_KIND) { _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS2, PyUnicode_4BYTE_DATA(from) + from_start, PyUnicode_4BYTE_DATA(from) + from_start + how_many, PyUnicode_2BYTE_DATA(to) + to_start); } else { assert(false); } } } static int _NuitkaUnicode_modifiable(PyObject *unicode) { if (Py_REFCNT(unicode) != 1) return 0; if (_PyUnicode_HASH(unicode) != -1) return 0; // TODO: That ought to be impossible with refcnf 1. if (PyUnicode_CHECK_INTERNED(unicode)) return 0; return 1; } static PyObject *_NuitkaUnicode_New(Py_ssize_t length) { assert(length != 0); if (length > ((PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(Py_UNICODE)) - 1)) { return PyErr_NoMemory(); } PyUnicodeObject *unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type); if (unlikely(unicode == NULL)) { return NULL; } Py_ssize_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); _PyUnicode_WSTR_LENGTH(unicode) = length; _PyUnicode_HASH(unicode) = -1; _PyUnicode_STATE(unicode).interned = 0; _PyUnicode_STATE(unicode).kind = 0; _PyUnicode_STATE(unicode).compact = 0; _PyUnicode_STATE(unicode).ready = 0; _PyUnicode_STATE(unicode).ascii = 0; _PyUnicode_DATA_ANY(unicode) = NULL; _PyUnicode_LENGTH(unicode) = 0; _PyUnicode_UTF8(unicode) = NULL; _PyUnicode_UTF8_LENGTH(unicode) = 0; _PyUnicode_WSTR(unicode) = (Py_UNICODE *)PyObject_MALLOC(new_size); if (!_PyUnicode_WSTR(unicode)) { Py_DECREF(unicode); PyErr_NoMemory(); return NULL; } _PyUnicode_WSTR(unicode)[0] = 0; _PyUnicode_WSTR(unicode)[length] = 0; return (PyObject *)unicode; } static PyObject *_NuitkaUnicode_resize_copy(PyObject *unicode, Py_ssize_t length) { if (_PyUnicode_KIND(unicode) != PyUnicode_WCHAR_KIND) { PyObject *copy = PyUnicode_New(length, PyUnicode_MAX_CHAR_VALUE(unicode)); if (unlikely(copy == NULL)) { return NULL; } Py_ssize_t copy_length = Py_MIN(length, PyUnicode_GET_LENGTH(unicode)); _NuitkaUnicode_FastCopyCharacters(copy, 0, unicode, 0, copy_length); return copy; } else { PyObject *w = _NuitkaUnicode_New(length); if (unlikely(w == NULL)) { return NULL; } Py_ssize_t copy_length = _PyUnicode_WSTR_LENGTH(unicode); copy_length = Py_MIN(copy_length, length); memcpy(_PyUnicode_WSTR(w), _PyUnicode_WSTR(unicode), copy_length * sizeof(wchar_t)); return w; } } // We use older form code, make some backward compatible defines available. #if PYTHON_VERSION >= 0x390 #ifdef Py_REF_DEBUG #define _Py_DEC_REFTOTAL _Py_RefTotal--; #else #define _Py_DEC_REFTOTAL #endif #ifdef Py_TRACE_REFS #define _Py_ForgetReference(unicode) _Py_ForgetReference(unicode) #else #define _Py_ForgetReference(unicode) #endif #endif static PyObject *_NuitkaUnicode_resize_compact(PyObject *unicode, Py_ssize_t length) { assert(PyUnicode_IS_COMPACT(unicode)); Py_ssize_t char_size = PyUnicode_KIND(unicode); Py_ssize_t struct_size; if (PyUnicode_IS_ASCII(unicode)) { struct_size = sizeof(PyASCIIObject); } else { struct_size = sizeof(PyCompactUnicodeObject); } int share_wstr = _PyUnicode_SHARE_WSTR(unicode); if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) { PyErr_NoMemory(); return NULL; } Py_ssize_t new_size = (struct_size + (length + 1) * char_size); if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) { PyObject_DEL(_PyUnicode_UTF8(unicode)); _PyUnicode_UTF8(unicode) = NULL; _PyUnicode_UTF8_LENGTH(unicode) = 0; } _Py_DEC_REFTOTAL; _Py_ForgetReference(unicode); PyObject *new_unicode = (PyObject *)PyObject_REALLOC(unicode, new_size); if (unlikely(new_unicode == NULL)) { _Py_NewReference(unicode); PyErr_NoMemory(); return NULL; } unicode = new_unicode; _Py_NewReference(unicode); _PyUnicode_LENGTH(unicode) = length; if (share_wstr) { _PyUnicode_WSTR(unicode) = (wchar_t *)PyUnicode_DATA(unicode); if (!PyUnicode_IS_ASCII(unicode)) { _PyUnicode_WSTR_LENGTH(unicode) = length; } } else if (_PyUnicode_HAS_WSTR_MEMORY(unicode)) { PyObject_DEL(_PyUnicode_WSTR(unicode)); _PyUnicode_WSTR(unicode) = NULL; if (!PyUnicode_IS_ASCII(unicode)) { _PyUnicode_WSTR_LENGTH(unicode) = 0; } } PyUnicode_WRITE(PyUnicode_KIND(unicode), PyUnicode_DATA(unicode), length, 0); return unicode; } static int _NuitkaUnicode_resize_inplace(PyObject *unicode, Py_ssize_t length) { assert(!PyUnicode_IS_COMPACT(unicode)); assert(Py_REFCNT(unicode) == 1); if (PyUnicode_IS_READY(unicode)) { void *data = _PyUnicode_DATA_ANY(unicode); Py_ssize_t char_size = PyUnicode_KIND(unicode); int share_wstr = _PyUnicode_SHARE_WSTR(unicode); int share_utf8 = _PyUnicode_SHARE_UTF8(unicode); if (length > (PY_SSIZE_T_MAX / char_size - 1)) { PyErr_NoMemory(); return -1; } Py_ssize_t new_size = (length + 1) * char_size; if (!share_utf8 && _PyUnicode_HAS_UTF8_MEMORY(unicode)) { PyObject_DEL(_PyUnicode_UTF8(unicode)); _PyUnicode_UTF8(unicode) = NULL; _PyUnicode_UTF8_LENGTH(unicode) = 0; } data = (PyObject *)PyObject_REALLOC(data, new_size); if (data == NULL) { PyErr_NoMemory(); return -1; } _PyUnicode_DATA_ANY(unicode) = data; if (share_wstr) { _PyUnicode_WSTR(unicode) = (wchar_t *)data; _PyUnicode_WSTR_LENGTH(unicode) = length; } if (share_utf8) { _PyUnicode_UTF8(unicode) = (char *)data; _PyUnicode_UTF8_LENGTH(unicode) = length; } _PyUnicode_LENGTH(unicode) = length; PyUnicode_WRITE(PyUnicode_KIND(unicode), data, length, 0); if (share_wstr || _PyUnicode_WSTR(unicode) == NULL) { return 0; } } assert(_PyUnicode_WSTR(unicode) != NULL); if (length > PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t) - 1) { PyErr_NoMemory(); return -1; } Py_ssize_t new_size = sizeof(wchar_t) * (length + 1); wchar_t *wstr = _PyUnicode_WSTR(unicode); wstr = (wchar_t *)PyObject_REALLOC(wstr, new_size); if (!wstr) { PyErr_NoMemory(); return -1; } _PyUnicode_WSTR(unicode) = wstr; _PyUnicode_WSTR(unicode)[length] = 0; _PyUnicode_WSTR_LENGTH(unicode) = length; return 0; } static int _NuitkaUnicode_resize(PyObject **p_unicode, Py_ssize_t length) { PyObject *unicode = *p_unicode; Py_ssize_t old_length; if (_PyUnicode_KIND(unicode) == PyUnicode_WCHAR_KIND) { old_length = PyUnicode_WSTR_LENGTH(unicode); } else { old_length = PyUnicode_GET_LENGTH(unicode); } if (old_length == length) { return 0; } if (length == 0) { Py_DECREF(*p_unicode); *p_unicode = const_str_empty; return 0; } if (!_NuitkaUnicode_modifiable(unicode)) { PyObject *copy = _NuitkaUnicode_resize_copy(unicode, length); if (copy == NULL) return -1; Py_DECREF(*p_unicode); *p_unicode = copy; return 0; } if (PyUnicode_IS_COMPACT(unicode)) { PyObject *new_unicode = _NuitkaUnicode_resize_compact(unicode, length); if (new_unicode == NULL) return -1; *p_unicode = new_unicode; return 0; } return _NuitkaUnicode_resize_inplace(unicode, length); } PyObject *UNICODE_CONCAT(PyObject *left, PyObject *right) { if (left == const_str_empty) { Py_INCREF(right); return right; } if (right == const_str_empty) { Py_INCREF(left); return left; } if (PyUnicode_READY(left) == -1 || PyUnicode_READY(right) == -1) { return NULL; } Py_ssize_t left_len = PyUnicode_GET_LENGTH(left); Py_ssize_t right_len = PyUnicode_GET_LENGTH(right); if (left_len > PY_SSIZE_T_MAX - right_len) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_OverflowError, "strings are too large to concat"); return NULL; } Py_ssize_t new_len = left_len + right_len; Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(left); Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(right); maxchar = Py_MAX(maxchar, maxchar2); PyObject *result = PyUnicode_New(new_len, maxchar); if (unlikely(result == NULL)) { return NULL; } _NuitkaUnicode_FastCopyCharacters(result, 0, left, 0, left_len); _NuitkaUnicode_FastCopyCharacters(result, left_len, right, 0, right_len); return result; } bool UNICODE_APPEND(PyObject **p_left, PyObject *right) { assert(p_left); PyObject *left = *p_left; if (left == const_str_empty) { Py_DECREF(left); Py_INCREF(right); *p_left = right; return true; } if (right == const_str_empty) return true; if (PyUnicode_READY(left) == -1 || PyUnicode_READY(right) == -1) { return false; } Py_ssize_t left_len = PyUnicode_GET_LENGTH(left); Py_ssize_t right_len = PyUnicode_GET_LENGTH(right); if (left_len > PY_SSIZE_T_MAX - right_len) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_OverflowError, "strings are too large to concat"); return false; } Py_ssize_t new_len = left_len + right_len; if (_NuitkaUnicode_modifiable(left) && PyUnicode_KIND(right) <= PyUnicode_KIND(left) && !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right))) { if (unlikely(_NuitkaUnicode_resize(p_left, new_len) != 0)) { return false; } _NuitkaUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len); } else { Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(left); Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(right); maxchar = Py_MAX(maxchar, maxchar2); PyObject *res = PyUnicode_New(new_len, maxchar); if (unlikely(res == NULL)) { return false; } _NuitkaUnicode_FastCopyCharacters(res, 0, left, 0, left_len); _NuitkaUnicode_FastCopyCharacters(res, left_len, right, 0, right_len); Py_DECREF(left); *p_left = res; } return true; } #endif PyObject *UNICODE_JOIN(PyObject *str, PyObject *iterable) { CHECK_OBJECT(str); CHECK_OBJECT(iterable); assert(PyUnicode_CheckExact(str)); return PyUnicode_Join(str, iterable); } PyObject *UNICODE_PARTITION(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); CHECK_OBJECT(sep); assert(PyUnicode_CheckExact(str)); return PyUnicode_Partition(str, sep); } PyObject *UNICODE_RPARTITION(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); CHECK_OBJECT(sep); assert(PyUnicode_CheckExact(str)); return PyUnicode_RPartition(str, sep); } #if PYTHON_VERSION < 0x300 PyObject *STR_JOIN(PyObject *str, PyObject *iterable) { CHECK_OBJECT(str); CHECK_OBJECT(iterable); assert(PyString_CheckExact(str)); return _PyString_Join(str, iterable); } #endif PyObject *NuitkaUnicode_FromWideChar(const wchar_t *str, Py_ssize_t size) { #if PYTHON_VERSION < 0x300 if (size == -1) { size = wcslen(str); } #endif return PyUnicode_FromWideChar(str, size); }Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceBitxor.c0000600000372100037210000015450214166627112033141 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "^" (BITXOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_xor : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_xor available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_xor == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITXOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_BITXOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_xor : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_xor available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_xor == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_BITXOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_xor available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_xor == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITXOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_BITXOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_xor available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_xor == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITXOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_LONG_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static inline bool _BINARY_OPERATION_BITXOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_BITXOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_SET_SET_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_xor : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'set'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = PySet_Type.tp_as_number->nb_inplace_xor; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = PySet_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'set' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PySet_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_BITXOR_SET_SET_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_inplace_xor(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return true; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_xor : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceMult.c0000600000372100037210000061326314166627112032617 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "*" (MULT) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MULT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. if (type1->tp_as_sequence == NULL) { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, *operand1); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_MULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. if (type1->tp_as_sequence == NULL) { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, *operand1); obj_result = result; goto exit_inplace_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } bool BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. if (type1->tp_as_sequence == NULL) { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, *operand1); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; } return __BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } if (type1->tp_as_sequence == NULL) { if (unlikely(!PyIndex_Check(*operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(*operand1); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'str'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_STR_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_MULT_INT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'str'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_STR_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "STR" to Python2 'str'. */ static inline bool _BINARY_OPERATION_MULT_LONG_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'str'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_STR_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_STR_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyString_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_STR_LONG_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } if (type1->tp_as_sequence == NULL) { if (unlikely(!PyIndex_Check(*operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(*operand1); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'unicode'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'str'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_UNICODE_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static inline bool _BINARY_OPERATION_MULT_INT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'unicode'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_UNICODE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_UNICODE_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "UNICODE" to Python2 'unicode', Python3 * 'str'. */ static inline bool _BINARY_OPERATION_MULT_LONG_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'unicode'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'str'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_UNICODE_INPLACE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ static inline bool _BINARY_OPERATION_MULT_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyUnicode_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_UNICODE_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } if (type1->tp_as_sequence == NULL) { if (unlikely(!PyIndex_Check(*operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(*operand1); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'tuple'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyTuple_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_TUPLE_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MULT_INT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'tuple'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_TUPLE_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "TUPLE" corresponds to Python 'tuple' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_TUPLE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyTuple_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_TUPLE_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_TUPLE_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "TUPLE" to Python 'tuple'. */ static inline bool _BINARY_OPERATION_MULT_LONG_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'tuple'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'tuple'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_TUPLE_INPLACE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_TUPLE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyTuple_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_TUPLE_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_TUPLE_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } if (type1->tp_as_sequence == NULL) { if (unlikely(!PyIndex_Check(*operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(*operand1); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'list'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LIST_INPLACE(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LIST_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MULT_INT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'list'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_LIST_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LIST" corresponds to Python 'list' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_LIST_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LIST_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LIST_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LIST" to Python 'list'. */ static inline bool _BINARY_OPERATION_MULT_LONG_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'list'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'list'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_LIST_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_LIST_INPLACE(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_LIST_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyList_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_inplace_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_inplace_repeat; if (repeatfunc == NULL) { repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LIST_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LIST_LONG_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } if (type1->tp_as_sequence == NULL) { if (unlikely(!PyIndex_Check(*operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(*operand1); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'bytes'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_BYTES_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_inplace_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_BYTES_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "BYTES" to Python3 'bytes'. */ static inline bool _BINARY_OPERATION_MULT_LONG_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !0) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } if (type1->tp_as_sequence == NULL) { if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_inplace_exception; } { PyObject *index_value = *operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_inplace_result_object; } } } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'bytes'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_BYTES_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_BYTES_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyBytes_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_inplace_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); goto exit_inplace_exception; } { ssizeargfunc repeatfunc = NULL; if (repeatfunc == NULL) { repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; } PyObject *r = (*repeatfunc)(*operand1, count); obj_result = r; goto exit_inplace_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_BYTES_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MULT_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_MULT_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_MULT_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_MULT_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_multiply available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_multiply == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); // No inplace sequence repeat slot sq_inplace_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_inplace_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_FLOAT_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_MULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_MULT_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_multiply : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_repeat : NULL; if (sq_slot == NULL) { sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; } if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, *operand1, operand2); obj_result = result; goto exit_inplace_result_object; } } // Special case for "*", also work with sequence repeat from right argument. if (type1->tp_as_sequence == NULL) { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, *operand1); obj_result = result; goto exit_inplace_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_MULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonGe.c0000600000372100037210000156470214166627112031113 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">=" (GE) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_GE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a >= b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_GE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a >= b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_GE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a >= b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GE_OBJECT_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GE_CBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; bool result = r; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_GE_NBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_GE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_GE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_GE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_GE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_GE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_GE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_GE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GE); CHECK_OBJECT(r); return r; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_GE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GE); CHECK_OBJECT(r); // Convert to target type if necessary bool result = r == Py_True; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_GE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_GE); CHECK_OBJECT(r); // Convert to target type if necessary nuitka_bool result = r == Py_True ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_GE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_GE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_GE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_GE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_GE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_GE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_GE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_GE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c >= 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_GE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_GE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_GE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_GE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_GE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_GE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_GE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_GE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_GE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_GE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) > 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] > b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_GE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() >= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a >= b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_GE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_GE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a >= b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_GE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_GE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a >= b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_GE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_GE_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_GE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_GE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_GE_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_GE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_GE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_GE_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_GE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_GE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_GE_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_GE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_GE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_GE_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_GE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_GE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a >= len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_GE_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_GE_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_GE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_GE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() >= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_GE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_GE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_GE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_GE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_GE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_GE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() >= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'>=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/InspectPatcher.c0000600000372100037210000003235714166627112030111 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** * This is responsible for updating parts of CPython to better work with Nuitka * by replacing CPython implementations with enhanced versions. */ #include "nuitka/prelude.h" #if PYTHON_VERSION >= 0x300 static PyObject *module_inspect; #if PYTHON_VERSION >= 0x350 static PyObject *module_types; #endif static char *kwlist[] = {(char *)"object", NULL}; static PyObject *old_getgeneratorstate = NULL; static PyObject *_inspect_getgeneratorstate_replacement(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *object; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:getgeneratorstate", kwlist, &object, NULL)) { return NULL; } if (Nuitka_Generator_Check(object)) { struct Nuitka_GeneratorObject *generator = (struct Nuitka_GeneratorObject *)object; if (generator->m_running) { return PyObject_GetAttrString(module_inspect, "GEN_RUNNING"); } else if (generator->m_status == status_Finished) { return PyObject_GetAttrString(module_inspect, "GEN_CLOSED"); } else if (generator->m_status == status_Unused) { return PyObject_GetAttrString(module_inspect, "GEN_CREATED"); } else { return PyObject_GetAttrString(module_inspect, "GEN_SUSPENDED"); } } else { return old_getgeneratorstate->ob_type->tp_call(old_getgeneratorstate, args, kwds); } } #if PYTHON_VERSION >= 0x350 static PyObject *old_getcoroutinestate = NULL; static PyObject *_inspect_getcoroutinestate_replacement(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *object; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:getcoroutinestate", kwlist, &object, NULL)) { return NULL; } if (Nuitka_Coroutine_Check(object)) { struct Nuitka_CoroutineObject *coroutine = (struct Nuitka_CoroutineObject *)object; if (coroutine->m_running) { return PyObject_GetAttrString(module_inspect, "CORO_RUNNING"); } else if (coroutine->m_status == status_Finished) { return PyObject_GetAttrString(module_inspect, "CORO_CLOSED"); } else if (coroutine->m_status == status_Unused) { return PyObject_GetAttrString(module_inspect, "CORO_CREATED"); } else { return PyObject_GetAttrString(module_inspect, "CORO_SUSPENDED"); } } else { return old_getcoroutinestate->ob_type->tp_call(old_getcoroutinestate, args, kwds); } } static PyObject *old_types_coroutine = NULL; static char *kwlist_func[] = {(char *)"func", NULL}; static PyObject *_types_coroutine_replacement(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *func; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:coroutine", kwlist_func, &func, NULL)) { return NULL; } if (Nuitka_Function_Check(func)) { struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)func; if (function->m_code_object->co_flags & CO_GENERATOR) { function->m_code_object->co_flags |= 0x100; } } return old_types_coroutine->ob_type->tp_call(old_types_coroutine, args, kwds); } #endif #endif #if PYTHON_VERSION >= 0x300 static PyMethodDef _method_def_inspect_getgeneratorstate_replacement = { "getgeneratorstate", (PyCFunction)_inspect_getgeneratorstate_replacement, METH_VARARGS | METH_KEYWORDS, NULL}; #if PYTHON_VERSION >= 0x350 static PyMethodDef _method_def_inspect_getcoroutinestate_replacement = { "getcoroutinestate", (PyCFunction)_inspect_getcoroutinestate_replacement, METH_VARARGS | METH_KEYWORDS, NULL}; static PyMethodDef _method_def_types_coroutine_replacement = {"coroutine", (PyCFunction)_types_coroutine_replacement, METH_VARARGS | METH_KEYWORDS, NULL}; #endif /* Replace inspect functions with ones that handle compiles types too. */ void patchInspectModule(void) { static bool is_done = false; if (is_done) return; #if PYTHON_VERSION >= 0x300 #if defined(_NUITKA_EXE) && !defined(_NUITKA_STANDALONE) // May need to import the "site" module, because otherwise the patching can // fail with it being unable to load it (yet) if (Py_NoSiteFlag == 0) { PyObject *site_module = IMPORT_MODULE5(const_str_plain_site, Py_None, Py_None, const_tuple_empty, const_int_0); if (site_module == NULL) { // Ignore "ImportError", having a "site" module is not a must. CLEAR_ERROR_OCCURRED(); } } #endif // TODO: Change this into an import hook that is executed after it is imported. module_inspect = IMPORT_MODULE5(const_str_plain_inspect, Py_None, Py_None, const_tuple_empty, const_int_0); if (module_inspect == NULL) { PyErr_PrintEx(0); Py_Exit(1); } CHECK_OBJECT(module_inspect); // Patch "inspect.getgeneratorstate" unless it is already patched. old_getgeneratorstate = PyObject_GetAttrString(module_inspect, "getgeneratorstate"); CHECK_OBJECT(old_getgeneratorstate); if (PyFunction_Check(old_getgeneratorstate)) { PyObject *inspect_getgeneratorstate_replacement = PyCFunction_New(&_method_def_inspect_getgeneratorstate_replacement, NULL); CHECK_OBJECT(inspect_getgeneratorstate_replacement); PyObject_SetAttrString(module_inspect, "getgeneratorstate", inspect_getgeneratorstate_replacement); } #if PYTHON_VERSION >= 0x350 // Patch "inspect.getcoroutinestate" unless it is already patched. old_getcoroutinestate = PyObject_GetAttrString(module_inspect, "getcoroutinestate"); CHECK_OBJECT(old_getcoroutinestate); if (PyFunction_Check(old_getcoroutinestate)) { PyObject *inspect_getcoroutinestate_replacement = PyCFunction_New(&_method_def_inspect_getcoroutinestate_replacement, NULL); CHECK_OBJECT(inspect_getcoroutinestate_replacement); PyObject_SetAttrString(module_inspect, "getcoroutinestate", inspect_getcoroutinestate_replacement); } module_types = IMPORT_MODULE5(const_str_plain_types, Py_None, Py_None, const_tuple_empty, const_int_0); if (module_types == NULL) { PyErr_PrintEx(0); Py_Exit(1); } CHECK_OBJECT(module_types); // Patch "types.coroutine" unless it is already patched. old_types_coroutine = PyObject_GetAttrString(module_types, "coroutine"); CHECK_OBJECT(old_types_coroutine); if (PyFunction_Check(old_types_coroutine)) { PyObject *types_coroutine_replacement = PyCFunction_New(&_method_def_types_coroutine_replacement, NULL); CHECK_OBJECT(types_coroutine_replacement); PyObject_SetAttrString(module_types, "coroutine", types_coroutine_replacement); } static char const *wrapper_enhancement_code = "\n\ import types\n\ _old_GeneratorWrapper = types._GeneratorWrapper\n\ class GeneratorWrapperEnhanced(_old_GeneratorWrapper):\n\ def __init__(self, gen):\n\ _old_GeneratorWrapper.__init__(self, gen)\n\ \n\ if hasattr(gen, 'gi_code'):\n\ if gen.gi_code.co_flags & 0x0020:\n\ self._GeneratorWrapper__isgen = True\n\ \n\ types._GeneratorWrapper = GeneratorWrapperEnhanced\ "; PyObject *wrapper_enhencement_codeobject = Py_CompileString(wrapper_enhancement_code, "", Py_file_input); CHECK_OBJECT(wrapper_enhencement_codeobject); { PyObject *module = PyImport_ExecCodeModule("nuitka_types_patch", wrapper_enhencement_codeobject); CHECK_OBJECT(module); int res = PyDict_DelItemString(PyImport_GetModuleDict(), "nuitka_types_patch"); assert(res == 0); Py_DECREF(module); } #endif #endif is_done = true; } #endif #if !defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) extern int Nuitka_IsInstance(PyObject *inst, PyObject *cls); extern PyObject *original_isinstance; static PyObject *_builtin_isinstance_replacement(PyObject *self, PyObject *args) { PyObject *inst, *cls; if (unlikely(PyArg_UnpackTuple(args, "isinstance", 2, 2, &inst, &cls) == 0)) { return NULL; } int res = Nuitka_IsInstance(inst, cls); if (unlikely(res < 0)) { return NULL; } PyObject *result = BOOL_FROM(res != 0); Py_INCREF(result); return result; } #endif #if !defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) static PyMethodDef _method_def_builtin_isinstance_replacement = { "isinstance", (PyCFunction)_builtin_isinstance_replacement, METH_VARARGS, NULL}; #endif extern PyModuleObject *builtin_module; void patchBuiltinModule() { #if defined(_NUITKA_MODULE) static bool init_done = false; if (init_done == true) return; init_done = true; #endif CHECK_OBJECT(builtin_module); #if !defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) // Patch "inspect.isinstance" unless it is already patched. original_isinstance = PyObject_GetAttrString((PyObject *)builtin_module, "isinstance"); CHECK_OBJECT(original_isinstance); // Copy the doc attribute over, needed for "inspect.signature" at least. if (PyCFunction_Check(original_isinstance)) { _method_def_builtin_isinstance_replacement.ml_doc = ((PyCFunctionObject *)original_isinstance)->m_ml->ml_doc; } PyObject *builtin_isinstance_replacement = PyCFunction_New(&_method_def_builtin_isinstance_replacement, NULL); CHECK_OBJECT(builtin_isinstance_replacement); PyObject_SetAttrString((PyObject *)builtin_module, "isinstance", builtin_isinstance_replacement); #endif } static richcmpfunc original_PyType_tp_richcompare = NULL; static PyObject *Nuitka_type_tp_richcompare(PyObject *a, PyObject *b, int op) { if (likely(op == Py_EQ || op == Py_NE)) { if (a == (PyObject *)&Nuitka_Function_Type) { a = (PyObject *)&PyFunction_Type; } else if (a == (PyObject *)&Nuitka_Method_Type) { a = (PyObject *)&PyMethod_Type; } else if (a == (PyObject *)&Nuitka_Generator_Type) { a = (PyObject *)&PyGen_Type; #if PYTHON_VERSION >= 0x350 } else if (a == (PyObject *)&Nuitka_Coroutine_Type) { a = (PyObject *)&PyCoro_Type; #endif #if PYTHON_VERSION >= 0x360 } else if (a == (PyObject *)&Nuitka_Asyncgen_Type) { a = (PyObject *)&PyAsyncGen_Type; #endif } if (b == (PyObject *)&Nuitka_Function_Type) { b = (PyObject *)&PyFunction_Type; } else if (b == (PyObject *)&Nuitka_Method_Type) { b = (PyObject *)&PyMethod_Type; } else if (b == (PyObject *)&Nuitka_Generator_Type) { b = (PyObject *)&PyGen_Type; #if PYTHON_VERSION >= 0x350 } else if (b == (PyObject *)&Nuitka_Coroutine_Type) { b = (PyObject *)&PyCoro_Type; #endif #if PYTHON_VERSION >= 0x360 } else if (b == (PyObject *)&Nuitka_Asyncgen_Type) { b = (PyObject *)&PyAsyncGen_Type; #endif } } CHECK_OBJECT(a); CHECK_OBJECT(b); assert(original_PyType_tp_richcompare); return original_PyType_tp_richcompare(a, b, op); } void patchTypeComparison() { if (original_PyType_tp_richcompare == NULL) { original_PyType_tp_richcompare = PyType_Type.tp_richcompare; PyType_Type.tp_richcompare = Nuitka_type_tp_richcompare; } } #include "nuitka/freelists.h" #define MAX_TRACEBACK_FREE_LIST_COUNT 1000 static PyTracebackObject *free_list_tracebacks = NULL; static int free_list_tracebacks_count = 0; // Create a traceback for a given frame, using a freelist hacked into the // existing type. PyTracebackObject *MAKE_TRACEBACK(struct Nuitka_FrameObject *frame, int lineno) { #if 0 PRINT_STRING("MAKE_TRACEBACK: Enter"); PRINT_ITEM((PyObject *)frame); PRINT_NEW_LINE(); dumpFrameStack(); #endif CHECK_OBJECT(frame); assert(lineno != 0); PyTracebackObject *result; allocateFromFreeListFixed(free_list_tracebacks, PyTracebackObject, PyTraceBack_Type); result->tb_next = NULL; result->tb_frame = (PyFrameObject *)frame; Py_INCREF(frame); result->tb_lasti = 0; result->tb_lineno = lineno; Nuitka_GC_Track(result); return result; } static void Nuitka_tb_dealloc(PyTracebackObject *tb) { // Need to use official method as it checks for recursion. PyObject_GC_UnTrack(tb); #if 0 #if PYTHON_VERSION >= 0x380 Py_TRASHCAN_BEGIN(tb, Nuitka_tb_dealloc); #else Py_TRASHCAN_SAFE_BEGIN(tb); #endif #endif Py_XDECREF(tb->tb_next); Py_XDECREF(tb->tb_frame); releaseToFreeList(free_list_tracebacks, tb, MAX_TRACEBACK_FREE_LIST_COUNT); #if 0 #if PYTHON_VERSION >= 0x380 Py_TRASHCAN_END; #else Py_TRASHCAN_SAFE_END(tb); #endif #endif } void patchTracebackDealloc(void) { PyTraceBack_Type.tp_dealloc = (destructor)Nuitka_tb_dealloc; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinarySub.c0000600000372100037210000035511614166627112032300 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "-" (SUB) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) - MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } Py_SIZE(z) = -(Py_SIZE(z)); } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a - b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_subtract; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_subtract; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_FLOAT_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_SUB_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_subtract(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_SUB_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a - b); bool no_overflow = ((x ^ a) >= 0 || (x ^ ~b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_subtract : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_subtract : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_subtract; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for -: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_SUB_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplacePow.c0000600000372100037210000023141014166627112032431 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "**" (POW) operations */ /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_right: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = operand2; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(0.0); goto exit_result_ok; exit_result_ok_const_float_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(1.0); goto exit_result_ok; exit_result_ok_const_float_minus_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(-1.0); goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_power : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_right: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = operand2; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(0.0); goto exit_result_ok; exit_result_ok_const_float_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(1.0); goto exit_result_ok; exit_result_ok_const_float_minus_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(-1.0); goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_power available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_power == NULL); { ternaryfunc slot1 = PyFloat_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_right: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = operand2; goto exit_result_ok; exit_result_ok_const_float_0_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(0.0); goto exit_result_ok; exit_result_ok_const_float_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(1.0); goto exit_result_ok; exit_result_ok_const_float_minus_1_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(-1.0); goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_POW_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(*operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_POW_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_power : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(*operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_power available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_power == NULL); { ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(*operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_POW_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_POW_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_power : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_POW_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_power available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_power == NULL); { ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_POW_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_POW_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_POW_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_POW_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_POW_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_power available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_power == NULL); { ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_POW_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_POW_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_power available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_power == NULL); { ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_POW_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_INT_LONG_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_POW_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_POW_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_power : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_POW_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceRshift.c0000600000372100037210000013564414166627112033137 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place ">>" (RSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_rshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_rshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_rshift == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_const_int_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_0); *operand1 = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_neg_1); *operand1 = const_int_neg_1; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_rshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_const_int_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_0); *operand1 = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_neg_1); *operand1 = const_int_neg_1; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_rshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_rshift == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_const_int_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_0); *operand1 = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_neg_1); *operand1 = const_int_neg_1; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_RSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_rshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_rshift == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_RSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_RSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_rshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_rshift == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_RSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_LONG_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_ok_const_int_0: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_0); *operand1 = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: // We got an object handed, that we have to release. Py_DECREF(*operand1); Py_INCREF(const_int_neg_1); *operand1 = const_int_neg_1; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_rshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersProfiling.c0000600000372100037210000000622314166627112030442 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** * This is responsible for profiling Nuitka using "vmprof". */ #if _NUITKA_PROFILE #include struct timespec diff(struct timespec start, struct timespec end); static struct timespec getTimespecDiff(struct timespec start, struct timespec end) { struct timespec temp; if ((end.tv_nsec - start.tv_nsec) < 0) { temp.tv_sec = end.tv_sec - start.tv_sec - 1; temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; } else { temp.tv_sec = end.tv_sec - start.tv_sec; temp.tv_nsec = end.tv_nsec - start.tv_nsec; } return temp; } static FILE *tempfile_profile; static PyObject *vmprof_module; static struct timespec time1, time2; void startProfiling(void) { tempfile_profile = fopen("nuitka-performance.dat", "w+b"); // Might be necessary to import "site" module to find "vmprof", lets just // hope we don't suffer too much from that. If we do, what might be done // is to try and just have the "PYTHONPATH" from it from out user. PyImport_ImportModule("site"); vmprof_module = PyImport_ImportModule("vmprof"); // Abort if it's not there. if (vmprof_module == NULL) { PyErr_Print(); abort(); } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(PyObject_GetAttrString(vmprof_module, "enable"), PyInt_FromLong(fileno(tempfile_profile))); if (result == NULL) { PyErr_Print(); abort(); } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); } void stopProfiling(void) { clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); PyObject *result = CALL_FUNCTION_NO_ARGS(PyObject_GetAttrString(vmprof_module, "disable")); if (result == NULL) CLEAR_ERROR_OCCURRED(); fclose(tempfile_profile); FILE *tempfile_times = fopen("nuitka-times.dat", "wb"); struct timespec diff = getTimespecDiff(time1, time2); long delta_ns = diff.tv_sec * 1000000000 + diff.tv_nsec; fprintf(tempfile_times, "%ld\n", delta_ns); fclose(tempfile_times); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersDictionaries.c0000600000372100037210000006240714166627112031134 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This helpers is used to work with dictionaries. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif PyObject *DICT_GET_ITEM0(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return NULL; } } else { hash = HASH_VALUE_WITHOUT_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { return NULL; } CHECK_OBJECT(entry->me_value); return entry->me_value; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITHOUT_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { return NULL; } #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *result; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result); #endif if (unlikely(ix < 0)) { return NULL; } #endif #if PYTHON_VERSION < 0x370 assert(value_addr != NULL); PyObject *result = *value_addr; #endif if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; #endif } PyObject *DICT_GET_ITEM1(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return NULL; } } else { hash = HASH_VALUE_WITHOUT_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { return NULL; } CHECK_OBJECT(entry->me_value); Py_INCREF(entry->me_value); return entry->me_value; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITHOUT_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { return NULL; } #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *result; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result); #endif if (unlikely(ix < 0)) { return NULL; } #endif #if PYTHON_VERSION < 0x370 assert(value_addr != NULL); PyObject *result = *value_addr; #endif if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); Py_INCREF(result); return result; #endif } static void SET_KEY_ERROR_EXCEPTION(PyObject *key) { /* Wrap all kinds of tuples, because normalization will later unwrap * it, but then that changes the key for the KeyError, which is not * welcome. The check is inexact, as the unwrapping one is too. */ if (PyTuple_Check(key) || key == Py_None) { PyObject *tuple = PyTuple_Pack(1, key); SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyExc_KeyError, tuple); } else { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_KeyError, key); } } // TODO: This gives a reference, where would often be one time immediate users // of the value, forcing temporary variable releases on the outside. We need // to add indication of how long a value is going to be used, so in case where // we have the knowledge, we can provide the reference or not. Maybe we can // also include temporary nature of the key and/or dict releases to be done // inside of such helper code, possibly in template generation, where also // the hashing check wouldn't be needed anymore. PyObject *DICT_GET_ITEM_WITH_ERROR(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return NULL; } } else { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { SET_KEY_ERROR_EXCEPTION(key); return NULL; } CHECK_OBJECT(entry->me_value); Py_INCREF(entry->me_value); return entry->me_value; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } SET_KEY_ERROR_EXCEPTION(key); return NULL; } #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *result; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result); #endif if (unlikely(ix < 0)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } SET_KEY_ERROR_EXCEPTION(key); return NULL; } #endif #if PYTHON_VERSION < 0x370 assert(value_addr != NULL); PyObject *result = *value_addr; #endif if (unlikely(result == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } SET_KEY_ERROR_EXCEPTION(key); return NULL; } CHECK_OBJECT(result); Py_INCREF(result); return result; #endif } PyObject *DICT_GET_ITEM_WITH_HASH_ERROR0(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return NULL; } } else { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { return NULL; } CHECK_OBJECT(entry->me_value); return entry->me_value; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *result; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result); #endif if (unlikely(ix < 0)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } #endif #if PYTHON_VERSION < 0x370 assert(value_addr != NULL); PyObject *result = *value_addr; #endif if (unlikely(result == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } CHECK_OBJECT(result); return result; #endif } // TODO: Exact copy of DICT_GET_ITEM_WITH_HASH_ERROR0 with just a Py_INCREF added, we should // generate these and all other variants rather than manually maintaining them, so we can // also specialize by type and not just result needs. PyObject *DICT_GET_ITEM_WITH_HASH_ERROR1(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return NULL; } } else { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { return NULL; } CHECK_OBJECT(entry->me_value); Py_INCREF(entry->me_value); return entry->me_value; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return NULL; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *result; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result); #endif if (unlikely(ix < 0)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } #endif #if PYTHON_VERSION < 0x370 assert(value_addr != NULL); PyObject *result = *value_addr; #endif if (unlikely(result == NULL)) { if (unlikely(ERROR_OCCURRED())) { return NULL; } return NULL; } CHECK_OBJECT(result); Py_INCREF(result); return result; #endif } int DICT_HAS_ITEM(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); CHECK_OBJECT(key); Py_hash_t hash; // This variant is uncertain about the hashing. #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(key)) { hash = ((PyStringObject *)key)->ob_shash; if (unlikely(hash == -1)) { hash = HASH_VALUE_WITHOUT_ERROR(key); } if (unlikely(hash == -1)) { return -1; } } else { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return -1; } } PyDictObject *dict_object = (PyDictObject *)dict; PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash); if (unlikely(entry == NULL || entry->me_value == NULL)) { return 0; } return 1; #else if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) { hash = HASH_VALUE_WITH_ERROR(key); if (unlikely(hash == -1)) { return -1; } } PyDictObject *dict_object = (PyDictObject *)dict; #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr); if (unlikely(entry == NULL || *value_addr == NULL)) { return 0; } return 1; #else #if PYTHON_VERSION < 0x370 PyObject **value_addr; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL); #else PyObject *value; Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value); #endif if (unlikely(ix < 0)) { if (unlikely(ERROR_OCCURRED())) { return -1; } return 0; } #endif return 1; #endif } #if PYTHON_VERSION < 0x300 PyObject *DICT_ITEMS(PyObject *dict) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); PyDictObject *mp = (PyDictObject *)dict; PyObject *result; Py_ssize_t size; /* Preallocate the list of tuples, to avoid allocations during * the loop over the items, which could trigger GC, which * could resize the dict. :-( */ retry: size = mp->ma_used; result = PyList_New(size); CHECK_OBJECT(result); for (Py_ssize_t i = 0; i < size; i++) { PyObject *item = PyTuple_New(2); CHECK_OBJECT(item); PyList_SET_ITEM(result, i, item); } if (unlikely(size != mp->ma_used)) { // Garbage collection can compatify dictionaries. Py_DECREF(result); goto retry; } // Nothing must cause any functions to be called PyDictEntry *ep = mp->ma_table; Py_ssize_t mask = mp->ma_mask; for (Py_ssize_t i = 0, j = 0; i <= mask; i++) { PyObject *value = ep[i].me_value; if (value != NULL) { PyObject *key = ep[i].me_key; PyObject *item = PyList_GET_ITEM(result, j); PyTuple_SET_ITEM0(item, 0, key); PyTuple_SET_ITEM0(item, 1, value); j++; } } assert(PyList_GET_SIZE(result) == size); return result; } #if PYTHON_VERSION < 0x300 PyObject *DICT_KEYS(PyObject *dict) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); PyDictObject *mp = (PyDictObject *)dict; PyObject *result; Py_ssize_t size; /* Preallocate the list of tuples, to avoid allocations during * the loop over the items, which could trigger GC, which * could resize the dict. :-( */ retry: size = mp->ma_used; result = PyList_New(size); CHECK_OBJECT(result); if (unlikely(size != mp->ma_used)) { // Garbage collection can compatify dictionaries. Py_DECREF(result); goto retry; } // Nothing must cause any functions to be called PyDictEntry *ep = mp->ma_table; Py_ssize_t mask = mp->ma_mask; for (Py_ssize_t i = 0, j = 0; i <= mask; i++) { PyObject *value = ep[i].me_value; if (value != NULL) { PyObject *key = ep[i].me_key; PyList_SET_ITEM0(result, j, key); j++; } } assert(PyList_GET_SIZE(result) == size); return result; } #endif #if PYTHON_VERSION < 0x300 PyObject *DICT_VALUES(PyObject *dict) { CHECK_OBJECT(dict); assert(PyDict_Check(dict)); PyDictObject *mp = (PyDictObject *)dict; PyObject *result; Py_ssize_t size; /* Preallocate the list of tuples, to avoid allocations during * the loop over the items, which could trigger GC, which * could resize the dict. :-( */ retry: size = mp->ma_used; result = PyList_New(size); CHECK_OBJECT(result); if (unlikely(size != mp->ma_used)) { // Garbage collection can compatify dictionaries. Py_DECREF(result); goto retry; } // Nothing must cause any functions to be called PyDictEntry *ep = mp->ma_table; Py_ssize_t mask = mp->ma_mask; for (Py_ssize_t i = 0, j = 0; i <= mask; i++) { PyObject *value = ep[i].me_value; if (value != NULL) { PyList_SET_ITEM0(result, j, value); j++; } } assert(PyList_GET_SIZE(result) == size); return result; } #endif #endif #if PYTHON_VERSION < 0x300 typedef struct { PyObject_HEAD PyDictObject *di_dict; Py_ssize_t di_used; Py_ssize_t di_pos; PyObject *di_result; Py_ssize_t len; } dictiterobject; #endif #if PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x350 typedef struct { PyObject_HEAD PyDictObject *dv_dict; } _PyDictViewObject; #endif // Generic helper for various dictionary iterations, to be inlined. static inline PyObject *_MAKE_DICT_ITERATOR(PyDictObject *dict, PyTypeObject *type, bool is_iteritems) { CHECK_OBJECT((PyObject *)dict); assert(PyDict_CheckExact((PyObject *)dict)); #if PYTHON_VERSION < 0x300 dictiterobject *di = PyObject_GC_New(dictiterobject, type); CHECK_OBJECT(di); Py_INCREF(dict); di->di_dict = dict; di->di_used = dict->ma_used; di->di_pos = 0; di->len = dict->ma_used; if (is_iteritems) { // TODO: Have this as faster variants, we do these sometimes. di->di_result = PyTuple_Pack(2, Py_None, Py_None); CHECK_OBJECT(di->di_result); } else { di->di_result = NULL; } Nuitka_GC_Track(di); return (PyObject *)di; #else _PyDictViewObject *dv = PyObject_GC_New(_PyDictViewObject, type); CHECK_OBJECT(dv); Py_INCREF(dict); dv->dv_dict = dict; Nuitka_GC_Track(dv); return (PyObject *)dv; #endif } PyObject *DICT_ITERITEMS(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictiteritems_type = NULL; if (unlikely(dictiteritems_type)) { dictiteritems_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "iteritems"))); } return _MAKE_DICT_ITERATOR((PyDictObject *)dict, dictiteritems_type, true); #elif PYTHON_VERSION < 0x300 return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictIterItem_Type, true); #else return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictItems_Type, true); #endif } PyObject *DICT_ITERKEYS(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictiterkeys_type = NULL; if (unlikely(dictiterkeys_type)) { dictiterkeys_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "iterkeys"))); } return _MAKE_DICT_ITERATOR((PyDictObject *)dict, dictiterkeys_type, false); #elif PYTHON_VERSION < 0x300 return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictIterKey_Type, false); #else return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictKeys_Type, false); #endif } PyObject *DICT_ITERVALUES(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictitervalues_type = NULL; if (unlikely(dictitervalues_type)) { dictitervalues_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "itervalues"))); } return _MAKE_DICT_ITERATOR((PyDictObject *)dict, dictitervalues_type, false); #elif PYTHON_VERSION < 0x300 return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictIterValue_Type, false); #else return _MAKE_DICT_ITERATOR((PyDictObject *)dict, &PyDictValues_Type, false); #endif } typedef struct { PyObject_HEAD PyDictObject *dv_dict; } dictviewobject; static PyObject *_MAKE_DICT_VIEW(PyDictObject *dict, PyTypeObject *type) { dictviewobject *dv = PyObject_GC_New(dictviewobject, type); CHECK_OBJECT(dv); Py_INCREF(dict); dv->dv_dict = (PyDictObject *)dict; Nuitka_GC_Track(dv); return (PyObject *)dv; } PyObject *DICT_VIEWKEYS(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictkeysview_type = NULL; if (unlikely(dictkeysview_type)) { dictkeysview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "viewkeys"))); } return _MAKE_DICT_VIEW((PyDictObject *)dict, dictkeysview_type); #else return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictKeys_Type); #endif } PyObject *DICT_VIEWVALUES(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictvaluesview_type = NULL; if (unlikely(dictvaluesview_type)) { dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "viewvalues"))); } return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type); #else return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictValues_Type); #endif } PyObject *DICT_VIEWITEMS(PyObject *dict) { #if PYTHON_VERSION < 0x270 static PyTypeObject *dictvaluesview_type = NULL; if (unlikely(dictvaluesview_type)) { dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty, "viewitems"))); } return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type); #else return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictItems_Type); #endif } PyObject *DICT_COPY(PyObject *value) { CHECK_OBJECT(value); assert(PyDict_CheckExact(value)); #if PYTHON_VERSION < 0x300 // For Python3, this can be done much faster in the same way as it is // done in parameter parsing. PyObject *result = _PyDict_NewPresized(((PyDictObject *)value)->ma_used); for (Py_ssize_t i = 0; i <= ((PyDictObject *)value)->ma_mask; i++) { PyDictEntry *entry = &((PyDictObject *)value)->ma_table[i]; if (entry->me_value != NULL) { int res = PyDict_SetItem(result, entry->me_key, entry->me_value); if (unlikely(res != 0)) { return NULL; } } } return result; #else /* Python 3 */ if (_PyDict_HasSplitTable((PyDictObject *)value)) { PyDictObject *mp = (PyDictObject *)value; PyObject **newvalues = PyMem_NEW(PyObject *, mp->ma_keys->dk_size); assert(newvalues != NULL); PyDictObject *result = PyObject_GC_New(PyDictObject, &PyDict_Type); assert(result != NULL); result->ma_values = newvalues; result->ma_keys = mp->ma_keys; result->ma_used = mp->ma_used; mp->ma_keys->dk_refcnt += 1; Nuitka_GC_Track(result); #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = DK_USABLE_FRACTION(DK_SIZE(mp->ma_keys)); #endif for (Py_ssize_t i = 0; i < size; i++) { if (mp->ma_values[i]) { result->ma_values[i] = mp->ma_values[i]; Py_INCREF(result->ma_values[i]); } else { result->ma_values[i] = NULL; } } return (PyObject *)result; } else { PyObject *result = _PyDict_NewPresized(((PyDictObject *)value)->ma_used); PyDictObject *mp = (PyDictObject *)value; #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = mp->ma_keys->dk_nentries; #endif for (Py_ssize_t i = 0; i < size; i++) { #if PYTHON_VERSION < 0x360 PyDictKeyEntry *entry = &mp->ma_keys->dk_entries[i]; #else PyDictKeyEntry *entry = &DK_ENTRIES(mp->ma_keys)[i]; #endif if (entry->me_value != NULL) { PyDict_SetItem(result, entry->me_key, entry->me_value); } } return result; } #endif } void DICT_CLEAR(PyObject *dict) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); // TODO: Could inline this for enhanced optimization, but it does // some pretty sophisticated memory handling. PyDict_Clear(dict); }Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryRshift.c0000600000372100037210000023217514166627112033005 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">>" (RSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_rshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_int_0: Py_INCREF(const_int_0); result = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: Py_INCREF(const_int_neg_1); result = const_int_neg_1; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_int_0: Py_INCREF(const_int_0); result = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: Py_INCREF(const_int_neg_1); result = const_int_neg_1; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_int_0: Py_INCREF(const_int_0); result = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: Py_INCREF(const_int_neg_1); result = const_int_neg_1; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_0: result = 0 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_neg_1: result = -1 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_0: result = 0 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_neg_1: result = -1 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_0: result = 0 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_neg_1: result = -1 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_rshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_rshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_LONG_INT(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_int_0: Py_INCREF(const_int_0); result = const_int_0; goto exit_result_ok; exit_result_ok_const_int_neg_1: Py_INCREF(const_int_neg_1); result = const_int_neg_1; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { if (a < 0) { goto exit_result_ok_const_int_neg_1; } else { goto exit_result_ok_const_int_0; } } else { long r = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); clong_result = r; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_0: result = 0 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_int_neg_1: result = -1 != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_rshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_rshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_rshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryLshift.c0000600000372100037210000024612114166627112032773 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<<" (LSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_LONG_INT(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyInt_AS_LONG(operand1) != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceOlddiv.c0000600000372100037210000022556014166627112033116 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "/" (OLDDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "float division by zero"); goto exit_result_exception; } { double r = a / b; cfloat_result = r; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_OLDDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_FLOAT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_OLDDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_LONG_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_OLDDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_FLOAT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INPLACE(operand1, operand2); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersBuiltinTypeMethods.c0000600000372100037210000013032214166627112032303 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_capitalize = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_center = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_count = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_decode = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_encode = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_endswith = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_expandtabs = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_find = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_format = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_index = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_isalnum = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_isalpha = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_isdigit = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_islower = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_isspace = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_istitle = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_isupper = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_join = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_ljust = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_lower = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_lstrip = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_partition = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_replace = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rfind = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rindex = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rjust = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rpartition = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rsplit = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_rstrip = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_split = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_splitlines = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_startswith = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_strip = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_swapcase = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_title = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_translate = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_upper = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *str_builtin_zfill = NULL; #endif #if PYTHON_VERSION < 0x300 static void _initStrBuiltinMethods() { #if PYTHON_VERSION < 0x300 str_builtin_capitalize = PyObject_GetAttrString((PyObject *)&PyString_Type, "capitalize"); #endif #if PYTHON_VERSION < 0x300 str_builtin_center = PyObject_GetAttrString((PyObject *)&PyString_Type, "center"); #endif #if PYTHON_VERSION < 0x300 str_builtin_count = PyObject_GetAttrString((PyObject *)&PyString_Type, "count"); #endif #if PYTHON_VERSION < 0x300 str_builtin_decode = PyObject_GetAttrString((PyObject *)&PyString_Type, "decode"); #endif #if PYTHON_VERSION < 0x300 str_builtin_encode = PyObject_GetAttrString((PyObject *)&PyString_Type, "encode"); #endif #if PYTHON_VERSION < 0x300 str_builtin_endswith = PyObject_GetAttrString((PyObject *)&PyString_Type, "endswith"); #endif #if PYTHON_VERSION < 0x300 str_builtin_expandtabs = PyObject_GetAttrString((PyObject *)&PyString_Type, "expandtabs"); #endif #if PYTHON_VERSION < 0x300 str_builtin_find = PyObject_GetAttrString((PyObject *)&PyString_Type, "find"); #endif #if PYTHON_VERSION < 0x300 str_builtin_format = PyObject_GetAttrString((PyObject *)&PyString_Type, "format"); #endif #if PYTHON_VERSION < 0x300 str_builtin_index = PyObject_GetAttrString((PyObject *)&PyString_Type, "index"); #endif #if PYTHON_VERSION < 0x300 str_builtin_isalnum = PyObject_GetAttrString((PyObject *)&PyString_Type, "isalnum"); #endif #if PYTHON_VERSION < 0x300 str_builtin_isalpha = PyObject_GetAttrString((PyObject *)&PyString_Type, "isalpha"); #endif #if PYTHON_VERSION < 0x300 str_builtin_isdigit = PyObject_GetAttrString((PyObject *)&PyString_Type, "isdigit"); #endif #if PYTHON_VERSION < 0x300 str_builtin_islower = PyObject_GetAttrString((PyObject *)&PyString_Type, "islower"); #endif #if PYTHON_VERSION < 0x300 str_builtin_isspace = PyObject_GetAttrString((PyObject *)&PyString_Type, "isspace"); #endif #if PYTHON_VERSION < 0x300 str_builtin_istitle = PyObject_GetAttrString((PyObject *)&PyString_Type, "istitle"); #endif #if PYTHON_VERSION < 0x300 str_builtin_isupper = PyObject_GetAttrString((PyObject *)&PyString_Type, "isupper"); #endif #if PYTHON_VERSION < 0x300 str_builtin_join = PyObject_GetAttrString((PyObject *)&PyString_Type, "join"); #endif #if PYTHON_VERSION < 0x300 str_builtin_ljust = PyObject_GetAttrString((PyObject *)&PyString_Type, "ljust"); #endif #if PYTHON_VERSION < 0x300 str_builtin_lower = PyObject_GetAttrString((PyObject *)&PyString_Type, "lower"); #endif #if PYTHON_VERSION < 0x300 str_builtin_lstrip = PyObject_GetAttrString((PyObject *)&PyString_Type, "lstrip"); #endif #if PYTHON_VERSION < 0x300 str_builtin_partition = PyObject_GetAttrString((PyObject *)&PyString_Type, "partition"); #endif #if PYTHON_VERSION < 0x300 str_builtin_replace = PyObject_GetAttrString((PyObject *)&PyString_Type, "replace"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rfind = PyObject_GetAttrString((PyObject *)&PyString_Type, "rfind"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rindex = PyObject_GetAttrString((PyObject *)&PyString_Type, "rindex"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rjust = PyObject_GetAttrString((PyObject *)&PyString_Type, "rjust"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rpartition = PyObject_GetAttrString((PyObject *)&PyString_Type, "rpartition"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rsplit = PyObject_GetAttrString((PyObject *)&PyString_Type, "rsplit"); #endif #if PYTHON_VERSION < 0x300 str_builtin_rstrip = PyObject_GetAttrString((PyObject *)&PyString_Type, "rstrip"); #endif #if PYTHON_VERSION < 0x300 str_builtin_split = PyObject_GetAttrString((PyObject *)&PyString_Type, "split"); #endif #if PYTHON_VERSION < 0x300 str_builtin_splitlines = PyObject_GetAttrString((PyObject *)&PyString_Type, "splitlines"); #endif #if PYTHON_VERSION < 0x300 str_builtin_startswith = PyObject_GetAttrString((PyObject *)&PyString_Type, "startswith"); #endif #if PYTHON_VERSION < 0x300 str_builtin_strip = PyObject_GetAttrString((PyObject *)&PyString_Type, "strip"); #endif #if PYTHON_VERSION < 0x300 str_builtin_swapcase = PyObject_GetAttrString((PyObject *)&PyString_Type, "swapcase"); #endif #if PYTHON_VERSION < 0x300 str_builtin_title = PyObject_GetAttrString((PyObject *)&PyString_Type, "title"); #endif #if PYTHON_VERSION < 0x300 str_builtin_translate = PyObject_GetAttrString((PyObject *)&PyString_Type, "translate"); #endif #if PYTHON_VERSION < 0x300 str_builtin_upper = PyObject_GetAttrString((PyObject *)&PyString_Type, "upper"); #endif #if PYTHON_VERSION < 0x300 str_builtin_zfill = PyObject_GetAttrString((PyObject *)&PyString_Type, "zfill"); #endif } #endif static PyObject *unicode_builtin_capitalize = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_casefold = NULL; #endif static PyObject *unicode_builtin_center = NULL; static PyObject *unicode_builtin_count = NULL; #if PYTHON_VERSION < 0x300 static PyObject *unicode_builtin_decode = NULL; #endif static PyObject *unicode_builtin_encode = NULL; static PyObject *unicode_builtin_endswith = NULL; static PyObject *unicode_builtin_expandtabs = NULL; static PyObject *unicode_builtin_find = NULL; static PyObject *unicode_builtin_format = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_format_map = NULL; #endif static PyObject *unicode_builtin_index = NULL; static PyObject *unicode_builtin_isalnum = NULL; static PyObject *unicode_builtin_isalpha = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_isascii = NULL; #endif static PyObject *unicode_builtin_isdecimal = NULL; static PyObject *unicode_builtin_isdigit = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_isidentifier = NULL; #endif static PyObject *unicode_builtin_islower = NULL; static PyObject *unicode_builtin_isnumeric = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_isprintable = NULL; #endif static PyObject *unicode_builtin_isspace = NULL; static PyObject *unicode_builtin_istitle = NULL; static PyObject *unicode_builtin_isupper = NULL; static PyObject *unicode_builtin_join = NULL; static PyObject *unicode_builtin_ljust = NULL; static PyObject *unicode_builtin_lower = NULL; static PyObject *unicode_builtin_lstrip = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *unicode_builtin_maketrans = NULL; #endif static PyObject *unicode_builtin_partition = NULL; static PyObject *unicode_builtin_replace = NULL; static PyObject *unicode_builtin_rfind = NULL; static PyObject *unicode_builtin_rindex = NULL; static PyObject *unicode_builtin_rjust = NULL; static PyObject *unicode_builtin_rpartition = NULL; static PyObject *unicode_builtin_rsplit = NULL; static PyObject *unicode_builtin_rstrip = NULL; static PyObject *unicode_builtin_split = NULL; static PyObject *unicode_builtin_splitlines = NULL; static PyObject *unicode_builtin_startswith = NULL; static PyObject *unicode_builtin_strip = NULL; static PyObject *unicode_builtin_swapcase = NULL; static PyObject *unicode_builtin_title = NULL; static PyObject *unicode_builtin_translate = NULL; static PyObject *unicode_builtin_upper = NULL; static PyObject *unicode_builtin_zfill = NULL; static void _initUnicodeBuiltinMethods() { unicode_builtin_capitalize = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "capitalize"); #if PYTHON_VERSION >= 0x300 unicode_builtin_casefold = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "casefold"); #endif unicode_builtin_center = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "center"); unicode_builtin_count = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "count"); #if PYTHON_VERSION < 0x300 unicode_builtin_decode = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "decode"); #endif unicode_builtin_encode = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "encode"); unicode_builtin_endswith = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "endswith"); unicode_builtin_expandtabs = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "expandtabs"); unicode_builtin_find = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "find"); unicode_builtin_format = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "format"); #if PYTHON_VERSION >= 0x300 unicode_builtin_format_map = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "format_map"); #endif unicode_builtin_index = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "index"); unicode_builtin_isalnum = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isalnum"); unicode_builtin_isalpha = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isalpha"); #if PYTHON_VERSION >= 0x300 unicode_builtin_isascii = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isascii"); #endif unicode_builtin_isdecimal = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isdecimal"); unicode_builtin_isdigit = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isdigit"); #if PYTHON_VERSION >= 0x300 unicode_builtin_isidentifier = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isidentifier"); #endif unicode_builtin_islower = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "islower"); unicode_builtin_isnumeric = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isnumeric"); #if PYTHON_VERSION >= 0x300 unicode_builtin_isprintable = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isprintable"); #endif unicode_builtin_isspace = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isspace"); unicode_builtin_istitle = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "istitle"); unicode_builtin_isupper = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "isupper"); unicode_builtin_join = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "join"); unicode_builtin_ljust = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "ljust"); unicode_builtin_lower = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "lower"); unicode_builtin_lstrip = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "lstrip"); #if PYTHON_VERSION >= 0x300 unicode_builtin_maketrans = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "maketrans"); #endif unicode_builtin_partition = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "partition"); unicode_builtin_replace = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "replace"); unicode_builtin_rfind = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rfind"); unicode_builtin_rindex = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rindex"); unicode_builtin_rjust = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rjust"); unicode_builtin_rpartition = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rpartition"); unicode_builtin_rsplit = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rsplit"); unicode_builtin_rstrip = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "rstrip"); unicode_builtin_split = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "split"); unicode_builtin_splitlines = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "splitlines"); unicode_builtin_startswith = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "startswith"); unicode_builtin_strip = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "strip"); unicode_builtin_swapcase = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "swapcase"); unicode_builtin_title = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "title"); unicode_builtin_translate = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "translate"); unicode_builtin_upper = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "upper"); unicode_builtin_zfill = PyObject_GetAttrString((PyObject *)&PyUnicode_Type, "zfill"); } static PyObject *dict_builtin_clear = NULL; static PyObject *dict_builtin_copy = NULL; static PyObject *dict_builtin_fromkeys = NULL; static PyObject *dict_builtin_get = NULL; #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_has_key = NULL; #endif static PyObject *dict_builtin_items = NULL; #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_iteritems = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_iterkeys = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_itervalues = NULL; #endif static PyObject *dict_builtin_keys = NULL; static PyObject *dict_builtin_pop = NULL; static PyObject *dict_builtin_popitem = NULL; static PyObject *dict_builtin_setdefault = NULL; static PyObject *dict_builtin_update = NULL; static PyObject *dict_builtin_values = NULL; #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_viewitems = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_viewkeys = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *dict_builtin_viewvalues = NULL; #endif static void _initDictBuiltinMethods() { dict_builtin_clear = PyObject_GetAttrString((PyObject *)&PyDict_Type, "clear"); dict_builtin_copy = PyObject_GetAttrString((PyObject *)&PyDict_Type, "copy"); dict_builtin_fromkeys = PyObject_GetAttrString((PyObject *)&PyDict_Type, "fromkeys"); dict_builtin_get = PyObject_GetAttrString((PyObject *)&PyDict_Type, "get"); #if PYTHON_VERSION < 0x300 dict_builtin_has_key = PyObject_GetAttrString((PyObject *)&PyDict_Type, "has_key"); #endif dict_builtin_items = PyObject_GetAttrString((PyObject *)&PyDict_Type, "items"); #if PYTHON_VERSION < 0x300 dict_builtin_iteritems = PyObject_GetAttrString((PyObject *)&PyDict_Type, "iteritems"); #endif #if PYTHON_VERSION < 0x300 dict_builtin_iterkeys = PyObject_GetAttrString((PyObject *)&PyDict_Type, "iterkeys"); #endif #if PYTHON_VERSION < 0x300 dict_builtin_itervalues = PyObject_GetAttrString((PyObject *)&PyDict_Type, "itervalues"); #endif dict_builtin_keys = PyObject_GetAttrString((PyObject *)&PyDict_Type, "keys"); dict_builtin_pop = PyObject_GetAttrString((PyObject *)&PyDict_Type, "pop"); dict_builtin_popitem = PyObject_GetAttrString((PyObject *)&PyDict_Type, "popitem"); dict_builtin_setdefault = PyObject_GetAttrString((PyObject *)&PyDict_Type, "setdefault"); dict_builtin_update = PyObject_GetAttrString((PyObject *)&PyDict_Type, "update"); dict_builtin_values = PyObject_GetAttrString((PyObject *)&PyDict_Type, "values"); #if PYTHON_VERSION < 0x300 dict_builtin_viewitems = PyObject_GetAttrString((PyObject *)&PyDict_Type, "viewitems"); #endif #if PYTHON_VERSION < 0x300 dict_builtin_viewkeys = PyObject_GetAttrString((PyObject *)&PyDict_Type, "viewkeys"); #endif #if PYTHON_VERSION < 0x300 dict_builtin_viewvalues = PyObject_GetAttrString((PyObject *)&PyDict_Type, "viewvalues"); #endif } PyObject *DICT_POP2(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); PyObject *args[2] = {dict, key}; return CALL_METHODDESCR_WITH_ARGS2(dict_builtin_pop, args); } PyObject *DICT_POP3(PyObject *dict, PyObject *key, PyObject *default_value) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); CHECK_OBJECT(default_value); PyObject *args[3] = {dict, key, default_value}; return CALL_METHODDESCR_WITH_ARGS3(dict_builtin_pop, args); } PyObject *DICT_SETDEFAULT2(PyObject *dict, PyObject *key) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); PyObject *args[2] = {dict, key}; return CALL_METHODDESCR_WITH_ARGS2(dict_builtin_setdefault, args); } PyObject *DICT_SETDEFAULT3(PyObject *dict, PyObject *key, PyObject *default_value) { CHECK_OBJECT(dict); assert(PyDict_CheckExact(dict)); CHECK_OBJECT(key); CHECK_OBJECT(default_value); PyObject *args[3] = {dict, key, default_value}; return CALL_METHODDESCR_WITH_ARGS3(dict_builtin_setdefault, args); } #if PYTHON_VERSION < 0x300 PyObject *STR_CAPITALIZE(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_capitalize, str); } PyObject *STR_DECODE1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_decode, str); } PyObject *STR_DECODE2(PyObject *str, PyObject *encoding) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(encoding); PyObject *args[2] = {str, encoding}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_decode, args); } PyObject *STR_DECODE3(PyObject *str, PyObject *encoding, PyObject *errors) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(encoding); CHECK_OBJECT(errors); PyObject *args[3] = {str, encoding, errors}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_decode, args); } PyObject *STR_ENCODE1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_encode, str); } PyObject *STR_ENCODE2(PyObject *str, PyObject *encoding) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(encoding); PyObject *args[2] = {str, encoding}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_encode, args); } PyObject *STR_ENCODE3(PyObject *str, PyObject *encoding, PyObject *errors) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(encoding); CHECK_OBJECT(errors); PyObject *args[3] = {str, encoding, errors}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_encode, args); } PyObject *STR_ENDSWITH2(PyObject *str, PyObject *suffix) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(suffix); PyObject *args[2] = {str, suffix}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_endswith, args); } PyObject *STR_ENDSWITH3(PyObject *str, PyObject *suffix, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(suffix); CHECK_OBJECT(start); PyObject *args[3] = {str, suffix, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_endswith, args); } PyObject *STR_ENDSWITH4(PyObject *str, PyObject *suffix, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(suffix); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, suffix, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_endswith, args); } PyObject *STR_FIND2(PyObject *str, PyObject *sub) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); PyObject *args[2] = {str, sub}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_find, args); } PyObject *STR_FIND3(PyObject *str, PyObject *sub, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {str, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_find, args); } PyObject *STR_FIND4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_find, args); } PyObject *STR_INDEX2(PyObject *str, PyObject *sub) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); PyObject *args[2] = {str, sub}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_index, args); } PyObject *STR_INDEX3(PyObject *str, PyObject *sub, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {str, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_index, args); } PyObject *STR_INDEX4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_index, args); } PyObject *STR_ISALNUM(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_isalnum, str); } PyObject *STR_ISALPHA(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_isalpha, str); } PyObject *STR_ISDIGIT(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_isdigit, str); } PyObject *STR_ISLOWER(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_islower, str); } PyObject *STR_ISSPACE(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_isspace, str); } PyObject *STR_ISTITLE(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_istitle, str); } PyObject *STR_ISUPPER(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_isupper, str); } PyObject *STR_LOWER(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_lower, str); } PyObject *STR_LSTRIP1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_lstrip, str); } PyObject *STR_LSTRIP2(PyObject *str, PyObject *chars) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(chars); PyObject *args[2] = {str, chars}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_lstrip, args); } PyObject *STR_PARTITION(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); PyObject *args[2] = {str, sep}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_partition, args); } PyObject *STR_REPLACE3(PyObject *str, PyObject *old, PyObject *new_value) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(old); CHECK_OBJECT(new_value); PyObject *args[3] = {str, old, new_value}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_replace, args); } PyObject *STR_REPLACE4(PyObject *str, PyObject *old, PyObject *new_value, PyObject *count) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(old); CHECK_OBJECT(new_value); CHECK_OBJECT(count); PyObject *args[4] = {str, old, new_value, count}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_replace, args); } PyObject *STR_RFIND2(PyObject *str, PyObject *sub) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); PyObject *args[2] = {str, sub}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_rfind, args); } PyObject *STR_RFIND3(PyObject *str, PyObject *sub, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {str, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_rfind, args); } PyObject *STR_RFIND4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_rfind, args); } PyObject *STR_RINDEX2(PyObject *str, PyObject *sub) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); PyObject *args[2] = {str, sub}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_rindex, args); } PyObject *STR_RINDEX3(PyObject *str, PyObject *sub, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {str, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_rindex, args); } PyObject *STR_RINDEX4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_rindex, args); } PyObject *STR_RPARTITION(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); PyObject *args[2] = {str, sep}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_rpartition, args); } PyObject *STR_RSPLIT1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_rsplit, str); } PyObject *STR_RSPLIT2(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); PyObject *args[2] = {str, sep}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_rsplit, args); } PyObject *STR_RSPLIT3(PyObject *str, PyObject *sep, PyObject *maxsplit) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); CHECK_OBJECT(maxsplit); PyObject *args[3] = {str, sep, maxsplit}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_rsplit, args); } PyObject *STR_RSTRIP1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_rstrip, str); } PyObject *STR_RSTRIP2(PyObject *str, PyObject *chars) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(chars); PyObject *args[2] = {str, chars}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_rstrip, args); } PyObject *STR_SPLIT1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_split, str); } PyObject *STR_SPLIT2(PyObject *str, PyObject *sep) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); PyObject *args[2] = {str, sep}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_split, args); } PyObject *STR_SPLIT3(PyObject *str, PyObject *sep, PyObject *maxsplit) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(sep); CHECK_OBJECT(maxsplit); PyObject *args[3] = {str, sep, maxsplit}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_split, args); } PyObject *STR_STARTSWITH2(PyObject *str, PyObject *prefix) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(prefix); PyObject *args[2] = {str, prefix}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_startswith, args); } PyObject *STR_STARTSWITH3(PyObject *str, PyObject *prefix, PyObject *start) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(prefix); CHECK_OBJECT(start); PyObject *args[3] = {str, prefix, start}; return CALL_METHODDESCR_WITH_ARGS3(str_builtin_startswith, args); } PyObject *STR_STARTSWITH4(PyObject *str, PyObject *prefix, PyObject *start, PyObject *end) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(prefix); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {str, prefix, start, end}; return CALL_METHODDESCR_WITH_ARGS4(str_builtin_startswith, args); } PyObject *STR_STRIP1(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_strip, str); } PyObject *STR_STRIP2(PyObject *str, PyObject *chars) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); CHECK_OBJECT(chars); PyObject *args[2] = {str, chars}; return CALL_METHODDESCR_WITH_ARGS2(str_builtin_strip, args); } PyObject *STR_SWAPCASE(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_swapcase, str); } PyObject *STR_TITLE(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_title, str); } PyObject *STR_UPPER(PyObject *str) { CHECK_OBJECT(str); assert(PyString_CheckExact(str)); return CALL_METHODDESCR_WITH_SINGLE_ARG(str_builtin_upper, str); } #endif PyObject *UNICODE_CAPITALIZE(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_capitalize, unicode); } PyObject *UNICODE_ENCODE1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_encode, unicode); } PyObject *UNICODE_ENCODE2(PyObject *unicode, PyObject *encoding) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(encoding); PyObject *args[2] = {unicode, encoding}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_encode, args); } PyObject *UNICODE_ENCODE3(PyObject *unicode, PyObject *encoding, PyObject *errors) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(encoding); CHECK_OBJECT(errors); PyObject *args[3] = {unicode, encoding, errors}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_encode, args); } PyObject *UNICODE_ENDSWITH2(PyObject *unicode, PyObject *suffix) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(suffix); PyObject *args[2] = {unicode, suffix}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_endswith, args); } PyObject *UNICODE_ENDSWITH3(PyObject *unicode, PyObject *suffix, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(suffix); CHECK_OBJECT(start); PyObject *args[3] = {unicode, suffix, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_endswith, args); } PyObject *UNICODE_ENDSWITH4(PyObject *unicode, PyObject *suffix, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(suffix); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, suffix, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_endswith, args); } PyObject *UNICODE_FIND2(PyObject *unicode, PyObject *sub) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); PyObject *args[2] = {unicode, sub}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_find, args); } PyObject *UNICODE_FIND3(PyObject *unicode, PyObject *sub, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {unicode, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_find, args); } PyObject *UNICODE_FIND4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_find, args); } PyObject *UNICODE_INDEX2(PyObject *unicode, PyObject *sub) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); PyObject *args[2] = {unicode, sub}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_index, args); } PyObject *UNICODE_INDEX3(PyObject *unicode, PyObject *sub, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {unicode, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_index, args); } PyObject *UNICODE_INDEX4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_index, args); } PyObject *UNICODE_ISALNUM(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_isalnum, unicode); } PyObject *UNICODE_ISALPHA(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_isalpha, unicode); } PyObject *UNICODE_ISDIGIT(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_isdigit, unicode); } PyObject *UNICODE_ISLOWER(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_islower, unicode); } PyObject *UNICODE_ISSPACE(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_isspace, unicode); } PyObject *UNICODE_ISTITLE(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_istitle, unicode); } PyObject *UNICODE_ISUPPER(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_isupper, unicode); } PyObject *UNICODE_LOWER(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_lower, unicode); } PyObject *UNICODE_LSTRIP1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_lstrip, unicode); } PyObject *UNICODE_LSTRIP2(PyObject *unicode, PyObject *chars) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(chars); PyObject *args[2] = {unicode, chars}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_lstrip, args); } PyObject *UNICODE_REPLACE3(PyObject *unicode, PyObject *old, PyObject *new_value) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(old); CHECK_OBJECT(new_value); PyObject *args[3] = {unicode, old, new_value}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_replace, args); } PyObject *UNICODE_REPLACE4(PyObject *unicode, PyObject *old, PyObject *new_value, PyObject *count) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(old); CHECK_OBJECT(new_value); CHECK_OBJECT(count); PyObject *args[4] = {unicode, old, new_value, count}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_replace, args); } PyObject *UNICODE_RFIND2(PyObject *unicode, PyObject *sub) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); PyObject *args[2] = {unicode, sub}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_rfind, args); } PyObject *UNICODE_RFIND3(PyObject *unicode, PyObject *sub, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {unicode, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_rfind, args); } PyObject *UNICODE_RFIND4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_rfind, args); } PyObject *UNICODE_RINDEX2(PyObject *unicode, PyObject *sub) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); PyObject *args[2] = {unicode, sub}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_rindex, args); } PyObject *UNICODE_RINDEX3(PyObject *unicode, PyObject *sub, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); PyObject *args[3] = {unicode, sub, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_rindex, args); } PyObject *UNICODE_RINDEX4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sub); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, sub, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_rindex, args); } PyObject *UNICODE_RSPLIT1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_rsplit, unicode); } PyObject *UNICODE_RSPLIT2(PyObject *unicode, PyObject *sep) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sep); PyObject *args[2] = {unicode, sep}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_rsplit, args); } PyObject *UNICODE_RSPLIT3(PyObject *unicode, PyObject *sep, PyObject *maxsplit) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sep); CHECK_OBJECT(maxsplit); PyObject *args[3] = {unicode, sep, maxsplit}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_rsplit, args); } PyObject *UNICODE_RSTRIP1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_rstrip, unicode); } PyObject *UNICODE_RSTRIP2(PyObject *unicode, PyObject *chars) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(chars); PyObject *args[2] = {unicode, chars}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_rstrip, args); } PyObject *UNICODE_SPLIT1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_split, unicode); } PyObject *UNICODE_SPLIT2(PyObject *unicode, PyObject *sep) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sep); PyObject *args[2] = {unicode, sep}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_split, args); } PyObject *UNICODE_SPLIT3(PyObject *unicode, PyObject *sep, PyObject *maxsplit) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(sep); CHECK_OBJECT(maxsplit); PyObject *args[3] = {unicode, sep, maxsplit}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_split, args); } PyObject *UNICODE_STARTSWITH2(PyObject *unicode, PyObject *prefix) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(prefix); PyObject *args[2] = {unicode, prefix}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_startswith, args); } PyObject *UNICODE_STARTSWITH3(PyObject *unicode, PyObject *prefix, PyObject *start) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(prefix); CHECK_OBJECT(start); PyObject *args[3] = {unicode, prefix, start}; return CALL_METHODDESCR_WITH_ARGS3(unicode_builtin_startswith, args); } PyObject *UNICODE_STARTSWITH4(PyObject *unicode, PyObject *prefix, PyObject *start, PyObject *end) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(prefix); CHECK_OBJECT(start); CHECK_OBJECT(end); PyObject *args[4] = {unicode, prefix, start, end}; return CALL_METHODDESCR_WITH_ARGS4(unicode_builtin_startswith, args); } PyObject *UNICODE_STRIP1(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_strip, unicode); } PyObject *UNICODE_STRIP2(PyObject *unicode, PyObject *chars) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); CHECK_OBJECT(chars); PyObject *args[2] = {unicode, chars}; return CALL_METHODDESCR_WITH_ARGS2(unicode_builtin_strip, args); } PyObject *UNICODE_SWAPCASE(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_swapcase, unicode); } PyObject *UNICODE_TITLE(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_title, unicode); } PyObject *UNICODE_UPPER(PyObject *unicode) { CHECK_OBJECT(unicode); assert(PyUnicode_CheckExact(unicode)); return CALL_METHODDESCR_WITH_SINGLE_ARG(unicode_builtin_upper, unicode); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryPow.c0000600000372100037210000040501714166627112032310 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersOperationBinaryPowUtils.c" /* C helpers for type specialized "**" (POW) operations */ /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_right: result = operand2; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_1_0: Py_INCREF(const_float_1_0); result = const_float_1_0; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: Py_INCREF(const_float_minus_1_0); result = const_float_minus_1_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyFloat_AS_DOUBLE(operand1) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_right: result = PyFloat_AS_DOUBLE(operand2) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_0_0: result = 0.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_1_0: result = 1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: result = -1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_right: result = operand2; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_1_0: Py_INCREF(const_float_1_0); result = const_float_1_0; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: Py_INCREF(const_float_minus_1_0); result = const_float_minus_1_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyFloat_AS_DOUBLE(operand1) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_right: result = PyFloat_AS_DOUBLE(operand2) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_0_0: result = 0.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_1_0: result = 1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: result = -1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyFloat_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok_left: result = operand1; Py_INCREF(result); goto exit_result_ok; exit_result_ok_right: result = operand2; Py_INCREF(result); goto exit_result_ok; exit_result_ok_const_float_0_0: Py_INCREF(const_float_0_0); result = const_float_0_0; goto exit_result_ok; exit_result_ok_const_float_1_0: Py_INCREF(const_float_1_0); result = const_float_1_0; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: Py_INCREF(const_float_minus_1_0); result = const_float_minus_1_0; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyFloat_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); if (b == 0) { goto exit_result_ok_const_float_1_0; } if (Py_IS_NAN(a)) { goto exit_result_ok_left; } if (Py_IS_NAN(b)) { if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else { goto exit_result_ok_right; } } if (Py_IS_INFINITY(b)) { a = fabs(a); if (a == 1.0) { goto exit_result_ok_const_float_1_0; } else if ((b > 0.0) == (a > 1.0)) { long r = (long)fabs(b); cfloat_result = r; goto exit_result_ok_cfloat; } else { goto exit_result_ok_const_float_0_0; } } if (Py_IS_INFINITY(a)) { bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r; if (b > 0.0) { r = b_is_odd ? a : fabs(a); } else { r = b_is_odd ? copysign(0.0, a) : 0.0; } cfloat_result = r; goto exit_result_ok_cfloat; } if (a == 0.0) { if (unlikely(b < 0.0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "0.0 cannot be raised to a negative power"); goto exit_result_exception; } bool b_is_odd = DOUBLE_IS_ODD_INTEGER(b); double r = b_is_odd ? a : 0.0; cfloat_result = r; goto exit_result_ok_cfloat; } { bool negate_result = false; if (a < 0.0) { if (unlikely(b != floor(b))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative number cannot be raised to a fractional power"); goto exit_result_exception; } a = -a; negate_result = DOUBLE_IS_ODD_INTEGER(b); } if (a == 1.0) { if (negate_result) { goto exit_result_ok_const_float_minus_1_0; } else { goto exit_result_ok_const_float_1_0; } } else { errno = 0; double r = pow(a, b); if (unlikely(errno != 0)) { PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError : PyExc_ValueError); goto exit_result_exception; } r = negate_result ? -r : r; cfloat_result = r; goto exit_result_ok_cfloat; } } exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_left: result = PyFloat_AS_DOUBLE(operand1) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_right: result = PyFloat_AS_DOUBLE(operand2) != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_0_0: result = 0.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_1_0: result = 1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok_const_float_minus_1_0: result = -1.0 != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_power(operand1, operand2, Py_None); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_POW_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_POW_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_POW_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_POW_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_POW_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_POW_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_POW_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_POW_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_POW_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyLong_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = PyInt_Type.tp_as_number->nb_power; ternaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_power; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_INT_LONG(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_POW_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_POW_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); if (b < 0) { // TODO: Use CFLOAT once available. PyObject *operand1_float = PyFloat_FromDouble(a); PyObject *operand2_float = PyFloat_FromDouble(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(operand1_float, operand2_float); Py_DECREF(operand1_float); Py_DECREF(operand2_float); obj_result = r; goto exit_result_object; } else { long temp = a; long ix = 1; long bb = b; while (bb > 0) { long prev = ix; if (bb & 1) { ix = (unsigned long)ix * temp; if (temp == 0) { break; } if (ix / temp != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } bb >>= 1; if (bb == 0) { break; } prev = temp; temp = (unsigned long)temp * temp; if (prev != 0 && temp / prev != prev) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); PyObject *r = _BINARY_OPERATION_POW_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } } clong_result = ix; goto exit_result_ok_clong; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif ternaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_power : NULL; ternaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_power : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2, Py_None); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { ternaryfunc slot = mv->nb_power; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2, Py_None); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_POW_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryMult.c0000600000372100037210000066555314166627112032501 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersOperationBinaryMultUtils.c" /* C helpers for type specialized "*" (MULT) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_multiply(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a * b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "CLONG" corresponds to C platform long value and "CLONG" to C platform long value. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_CLONG_CLONG(long operand1, long operand2) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif const long a = operand1; const long b = operand2; const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = PyLong_FromLong(operand1); PyObject *operand2_object = PyLong_FromLong(operand2); PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); Py_DECREF(operand1_object); Py_DECREF(operand2_object); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_CLONG_CLONG(long operand1, long operand2) { return _BINARY_OPERATION_MULT_OBJECT_CLONG_CLONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "CLONG" to C platform long value. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_CLONG(PyObject *operand1, long operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); const long a = PyInt_AS_LONG(operand1); const long b = operand2; const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = PyLong_FromLong(operand2); PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); Py_DECREF(operand2_object); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_CLONG(PyObject *operand1, long operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_CLONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "CLONG" corresponds to C platform long value and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_CLONG_INT(long operand1, PyObject *operand2) { CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = operand1; const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = PyLong_FromLong(operand1); PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); Py_DECREF(operand1_object); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_CLONG_INT(long operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_CLONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } if (unlikely(!PyIndex_Check(operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand1); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_STR_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_STR_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyString_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_STR_LONG(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } if (unlikely(!PyIndex_Check(operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand1); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_UNICODE_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_UNICODE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_UNICODE_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "UNICODE" to Python2 'unicode', Python3 * 'str'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyUnicode_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_UNICODE_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } if (unlikely(!PyIndex_Check(operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand1); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_TUPLE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_TUPLE_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_TUPLE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "TUPLE" corresponds to Python 'tuple' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_TUPLE_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_TUPLE_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_TUPLE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_TUPLE_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyTuple_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_TUPLE_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } if (unlikely(!PyIndex_Check(operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand1); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_LIST(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LIST_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_LIST(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LIST" corresponds to Python 'list' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LIST_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = PyInt_AS_LONG(index_value); { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LIST_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_LIST(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LIST_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_OverflowError, "cannot fit 'long' into an index-sized integer"); #else PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); #endif goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyList_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LIST_LONG(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } if (unlikely(!PyIndex_Check(operand1))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand1); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type1->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!PyIndex_Check(operand2))) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = PyNumber_Index(operand2); if (unlikely(index_value == NULL)) { goto exit_binary_exception; } { Py_ssize_t count = CONVERT_TO_REPEAT_FACTOR(index_value); Py_DECREF(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit '%s' into an index-sized integer", type2->tp_name); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_BYTES_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "BYTES" to Python3 'bytes'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_multiply == NULL || type1->tp_as_number->nb_multiply == type2->tp_as_number->nb_multiply); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !0) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type1->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand1; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand2, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !1) { coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif if (unlikely(!1)) { PyErr_Format(PyExc_TypeError, "can't multiply sequence by non-int of type '%s'", type2->tp_name); goto exit_binary_exception; } { PyObject *index_value = operand2; { Py_ssize_t count = CONVERT_LONG_TO_REPEAT_FACTOR(index_value); /* Above conversion indicates an error as -1 */ if (unlikely(count == -1)) { PyErr_Format(PyExc_OverflowError, "cannot fit 'int' into an index-sized integer"); goto exit_binary_exception; } { ssizeargfunc repeatfunc = PyBytes_Type.tp_as_sequence->sq_repeat; PyObject *r = (*repeatfunc)(operand1, count); obj_result = r; goto exit_binary_result_object; } } } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_BYTES_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_multiply; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_multiply; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_repeat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_repeat == NULL); } // No sequence repeat slot sq_repeat available for this type. assert(type2->tp_as_sequence == NULL || type2->tp_as_sequence->sq_repeat == NULL); #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_FLOAT_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_MULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_MULT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long longprod = (long)((unsigned long)a * b); const double doubleprod = (double)a * (double)b; const double doubled_longprod = (double)longprod; if (likely(doubled_longprod == doubleprod)) { clong_result = longprod; goto exit_result_ok_clong; } else { const double diff = doubled_longprod - doubleprod; const double absdiff = diff >= 0.0 ? diff : -diff; const double absprod = doubleprod >= 0.0 ? doubleprod : -doubleprod; if (likely(32.0 * absdiff <= absprod)) { clong_result = longprod; goto exit_result_ok_clong; } } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_multiply(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_multiply : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_multiply : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_multiply; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. ssizeargfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand1, operand2); obj_result = result; goto exit_binary_result_object; } } // Special case for "*", also work with sequence repeat from right argument. { ssizeargfunc sq_slot = type2->tp_as_sequence != NULL ? type2->tp_as_sequence->sq_repeat : NULL; if (sq_slot != NULL) { PyObject *result = SEQUENCE_REPEAT(sq_slot, operand2, operand1); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for *: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_MULT_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledCoroutineType.c0000600000372100037210000020535114166627112031457 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Compiled Coroutines. * * Unlike in CPython, we have one type for just coroutines, this doesn't do generators * nor asyncgen. * * It strives to be full replacement for normal coroutines. * */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/freelists.h" #include "nuitka/prelude.h" #include "structmember.h" #endif // For reporting about reference counts per type. #if _DEBUG_REFCOUNTS int count_active_Nuitka_Coroutine_Type = 0; int count_allocated_Nuitka_Coroutine_Type = 0; int count_released_Nuitka_Coroutine_Type = 0; int count_active_Nuitka_CoroutineWrapper_Type = 0; int count_allocated_Nuitka_CoroutineWrapper_Type = 0; int count_released_Nuitka_CoroutineWrapper_Type = 0; int count_active_Nuitka_AIterWrapper_Type = 0; int count_allocated_Nuitka_AIterWrapper_Type = 0; int count_released_Nuitka_AIterWrapper_Type = 0; #endif static PyObject *_Nuitka_Coroutine_send(struct Nuitka_CoroutineObject *coroutine, PyObject *value, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb); static long Nuitka_Coroutine_tp_hash(struct Nuitka_CoroutineObject *coroutine) { return coroutine->m_counter; } static PyObject *Nuitka_Coroutine_get_name(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); Py_INCREF(coroutine->m_name); return coroutine->m_name; } static int Nuitka_Coroutine_set_name(struct Nuitka_CoroutineObject *coroutine, PyObject *value) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(value); // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } PyObject *tmp = coroutine->m_name; Py_INCREF(value); coroutine->m_name = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Coroutine_get_qualname(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); Py_INCREF(coroutine->m_qualname); return coroutine->m_qualname; } static int Nuitka_Coroutine_set_qualname(struct Nuitka_CoroutineObject *coroutine, PyObject *value) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(value); // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } PyObject *tmp = coroutine->m_qualname; Py_INCREF(value); coroutine->m_qualname = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Coroutine_get_cr_await(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(coroutine->m_yieldfrom); if (coroutine->m_yieldfrom) { Py_INCREF(coroutine->m_yieldfrom); return coroutine->m_yieldfrom; } else { Py_INCREF(Py_None); return Py_None; } } static PyObject *Nuitka_Coroutine_get_code(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); CHECK_OBJECT(coroutine->m_code_object); Py_INCREF(coroutine->m_code_object); return (PyObject *)coroutine->m_code_object; } static int Nuitka_Coroutine_set_code(struct Nuitka_CoroutineObject *coroutine, PyObject *value) { CHECK_OBJECT(coroutine); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cr_code is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Coroutine_get_frame(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(coroutine->m_frame); if (coroutine->m_frame) { Py_INCREF(coroutine->m_frame); return (PyObject *)coroutine->m_frame; } else { Py_INCREF(Py_None); return Py_None; } } static int Nuitka_Coroutine_set_frame(struct Nuitka_CoroutineObject *coroutine, PyObject *value) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(value); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "gi_frame is not writable in Nuitka"); return -1; } static void Nuitka_Coroutine_release_closure(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); for (Py_ssize_t i = 0; i < coroutine->m_closure_given; i++) { CHECK_OBJECT(coroutine->m_closure[i]); Py_DECREF(coroutine->m_closure[i]); } coroutine->m_closure_given = 0; } // Note: Shared with asyncgen. static PyObject *_Nuitka_YieldFromCore(PyObject *yieldfrom, PyObject *send_value, PyObject **returned_value, bool mode) { // Send iteration value to the sub-generator, which may be a CPython // generator object, something with an iterator next, or a send method, // where the later is only required if values other than "None" need to // be passed in. CHECK_OBJECT(yieldfrom); CHECK_OBJECT_X(send_value); assert(send_value != NULL || ERROR_OCCURRED()); PyObject *retval; PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); if (exception_type != NULL) { // Exception, was thrown into us, need to send that to sub-generator. // We acquired ownership of the published exception and need to release it potentially. // Transfer exception owner this. retval = _Nuitka_YieldFromPassExceptionTo(yieldfrom, exception_type, exception_value, exception_tb); if (unlikely(send_value == NULL)) { PyObject *error = GET_ERROR_OCCURRED(); if (error != NULL && EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopIteration)) { *returned_value = ERROR_GET_STOP_ITERATION_VALUE(); assert(!ERROR_OCCURRED()); return NULL; } } } else if (PyGen_CheckExact(yieldfrom) || PyCoro_CheckExact(yieldfrom)) { retval = Nuitka_PyGen_Send((PyGenObject *)yieldfrom, Py_None); } else if (send_value == Py_None && Nuitka_CoroutineWrapper_Check(yieldfrom)) { struct Nuitka_CoroutineObject *yieldfrom_coroutine = ((struct Nuitka_CoroutineWrapperObject *)yieldfrom)->m_coroutine; retval = _Nuitka_Coroutine_send(yieldfrom_coroutine, Py_None, mode ? false : true, NULL, NULL, NULL); } else if (send_value == Py_None && Py_TYPE(yieldfrom)->tp_iternext != NULL) { retval = Py_TYPE(yieldfrom)->tp_iternext(yieldfrom); } else { #if 0 // TODO: Add slow mode traces. PRINT_ITEM(yieldfrom); PRINT_NEW_LINE(); #endif retval = PyObject_CallMethodObjArgs(yieldfrom, const_str_plain_send, send_value, NULL); } // Check the sub-generator result if (retval == NULL) { PyObject *error = GET_ERROR_OCCURRED(); if (error == NULL) { Py_INCREF(Py_None); *returned_value = Py_None; } else if (likely(EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopIteration))) { // The sub-generator has given an exception. In case of // StopIteration, we need to check the value, as it is going to be // the expression value of this "yield from", and we are done. All // other errors, we need to raise. *returned_value = ERROR_GET_STOP_ITERATION_VALUE(); assert(*returned_value != NULL); assert(!ERROR_OCCURRED()); } else { *returned_value = NULL; } return NULL; } else { assert(!ERROR_OCCURRED()); return retval; } } static PyObject *_Nuitka_YieldFromCoroutineCore(struct Nuitka_CoroutineObject *coroutine, PyObject *send_value, bool mode) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(send_value); PyObject *yieldfrom = coroutine->m_yieldfrom; CHECK_OBJECT(yieldfrom); // Need to make it unaccessible while using it. coroutine->m_yieldfrom = NULL; PyObject *returned_value; PyObject *yielded = _Nuitka_YieldFromCore(yieldfrom, send_value, &returned_value, mode); if (yielded == NULL) { assert(coroutine->m_yieldfrom == NULL); Py_DECREF(yieldfrom); yielded = ((coroutine_code)coroutine->m_code)(coroutine, returned_value); } else { assert(coroutine->m_yieldfrom == NULL); coroutine->m_yieldfrom = yieldfrom; } return yielded; } #if _DEBUG_COROUTINE NUITKA_MAY_BE_UNUSED static void _PRINT_COROUTINE_STATUS(char const *descriptor, char const *context, struct Nuitka_CoroutineObject *coroutine) { char const *status; switch (coroutine->m_status) { case status_Finished: status = "(finished)"; break; case status_Running: status = "(running)"; break; case status_Unused: status = "(unused)"; break; default: status = "(ILLEGAL)"; break; } PRINT_STRING(descriptor); PRINT_STRING(" : "); PRINT_STRING(context); PRINT_STRING(" "); PRINT_ITEM((PyObject *)coroutine); PRINT_STRING(" "); PRINT_REFCOUNT((PyObject *)coroutine); PRINT_STRING(status); PRINT_NEW_LINE(); } #define PRINT_COROUTINE_STATUS(context, coroutine) _PRINT_COROUTINE_STATUS(__FUNCTION__, context, coroutine) #endif static PyObject *Nuitka_YieldFromCoroutineNext(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_NEW_LINE(); #endif PyObject *result = _Nuitka_YieldFromCoroutineCore(coroutine, Py_None, true); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave", coroutine); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static PyObject *Nuitka_YieldFromCoroutineInitial(struct Nuitka_CoroutineObject *coroutine, PyObject *send_value) { CHECK_OBJECT(coroutine); CHECK_OBJECT_X(send_value); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_NEW_LINE(); #endif PyObject *result = _Nuitka_YieldFromCoroutineCore(coroutine, send_value, false); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave", coroutine); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return result; } static void Nuitka_SetStopIterationValue(PyObject *value); // This function is called when sending a value or exception to be handled in the coroutine // Note: // Exception arguments are passed for ownership and must be released before returning. The // value of exception_type may be NULL, and the actual exception will not necessarily // be normalized. static PySendResult _Nuitka_Coroutine_sendR(struct Nuitka_CoroutineObject *coroutine, PyObject *value, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb, PyObject **result) { CHECK_OBJECT(coroutine); assert(Nuitka_Coroutine_Check((PyObject *)coroutine)); CHECK_OBJECT_X(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); CHECK_OBJECT_X(value); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_COROUTINE_STRING("closing", closing ? "(closing) " : "(not closing) "); PRINT_COROUTINE_VALUE("value", value); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif if (value != NULL) { assert(exception_type == NULL); assert(exception_value == NULL); assert(exception_tb == NULL); } if (coroutine->m_status == status_Unused && value != NULL && value != Py_None) { // No exception if value is given. SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't send non-None value to a just-started coroutine"); return PYGEN_ERROR; } if (coroutine->m_status != status_Finished) { if (coroutine->m_running) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "coroutine already executing"); return PYGEN_ERROR; } PyThreadState *thread_state = PyThreadState_GET(); // Put the coroutine back on the frame stack. // First take of running frame from the stack, owning a reference. PyFrameObject *return_frame = thread_state->frame; #ifndef __NUITKA_NO_ASSERT__ if (return_frame) { assertFrameObject((struct Nuitka_FrameObject *)return_frame); } #endif if (coroutine->m_resume_frame) { // It would be nice if our frame were still alive. Nobody had the // right to release it. assertFrameObject(coroutine->m_resume_frame); // It's not supposed to be on the top right now. assert(return_frame != &coroutine->m_resume_frame->m_frame); thread_state->frame = &coroutine->m_resume_frame->m_frame; coroutine->m_resume_frame = NULL; } // Consider it as running. if (coroutine->m_status == status_Unused) { coroutine->m_status = status_Running; } // Continue the yielder function while preventing recursion. coroutine->m_running = true; // Check for thrown exception, publish it to the coroutine code. if (unlikely(exception_type)) { assert(value == NULL); // Transfer exception ownership to published. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); } if (coroutine->m_frame) { Nuitka_Frame_MarkAsExecuting(coroutine->m_frame); } #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Switching to coroutine", coroutine); PRINT_COROUTINE_VALUE("value", value); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); // dumpFrameStack(); #endif PyObject *yielded; if (coroutine->m_yieldfrom == NULL) { yielded = ((coroutine_code)coroutine->m_code)(coroutine, value); } else { yielded = Nuitka_YieldFromCoroutineInitial(coroutine, value); } // If the coroutine returns with m_yieldfrom set, it wants us to yield // from that value from now on. while (yielded == NULL && coroutine->m_yieldfrom != NULL) { yielded = Nuitka_YieldFromCoroutineNext(coroutine); } if (coroutine->m_frame) { Nuitka_Frame_MarkAsNotExecuting(coroutine->m_frame); } coroutine->m_running = false; thread_state = PyThreadState_GET(); // Remove the back frame from coroutine if it's there. if (coroutine->m_frame) { // assert(thread_state->frame == &coroutine->m_frame->m_frame); assertFrameObject(coroutine->m_frame); Py_CLEAR(coroutine->m_frame->m_frame.f_back); // Remember where to resume from. coroutine->m_resume_frame = (struct Nuitka_FrameObject *)thread_state->frame; } // Return back to the frame that called us. thread_state->frame = return_frame; #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Returned from coroutine", coroutine); // dumpFrameStack(); #endif #ifndef __NUITKA_NO_ASSERT__ if (return_frame) { assertFrameObject((struct Nuitka_FrameObject *)return_frame); } #endif if (yielded == NULL) { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("finishing from yield", coroutine); PRINT_COROUTINE_STRING("closing", closing ? "(closing) " : "(not closing) "); PRINT_STRING("-> finishing coroutine sets status_Finished\n"); PRINT_COROUTINE_VALUE("return_value", coroutine->m_returned); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif coroutine->m_status = status_Finished; if (coroutine->m_frame != NULL) { coroutine->m_frame->m_frame.f_gen = NULL; Py_DECREF(coroutine->m_frame); coroutine->m_frame = NULL; } Nuitka_Coroutine_release_closure(coroutine); // Create StopIteration if necessary, i.e. return value that is not "None" was // given. TODO: Push this further down the user line, we might be able to avoid // it for some uses, e.g. quick iteration entirely. if (coroutine->m_returned) { *result = coroutine->m_returned; coroutine->m_returned = NULL; #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Return value to exception set", coroutine); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif return PYGEN_RETURN; } else { PyObject *error = GET_ERROR_OCCURRED(); if (error == NULL) { *result = NULL; return PYGEN_RETURN; } else if (error == PyExc_StopIteration) { PyObject *saved_exception_type, *saved_exception_value; PyTracebackObject *saved_exception_tb; FETCH_ERROR_OCCURRED(&saved_exception_type, &saved_exception_value, &saved_exception_tb); NORMALIZE_EXCEPTION(&saved_exception_type, &saved_exception_value, &saved_exception_tb); PyErr_Format(PyExc_RuntimeError, "coroutine raised StopIteration"); FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); RAISE_EXCEPTION_WITH_CAUSE(&exception_type, &exception_value, &exception_tb, saved_exception_value); CHECK_OBJECT(exception_value); CHECK_OBJECT(saved_exception_value); Py_INCREF(saved_exception_value); PyException_SetContext(exception_value, saved_exception_value); Py_DECREF(saved_exception_type); Py_XDECREF(saved_exception_tb); RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave with exception set", coroutine); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } return PYGEN_ERROR; } } else { *result = yielded; return PYGEN_NEXT; } } else { // Release exception if any, we are finished with it and will raise another. Py_XDECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); /* This is for status_Finished */ assert(coroutine->m_status == status_Finished); /* This check got added in Python 3.5.2 only. It's good to do it, but * not fully compatible, therefore guard it. */ #if PYTHON_VERSION >= 0x352 || !defined(_NUITKA_FULL_COMPAT) if (closing == false) { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Finished coroutine sent into -> RuntimeError", coroutine); PRINT_NEW_LINE(); #endif PyErr_Format(PyExc_RuntimeError, #if !defined(_NUITKA_FULL_COMPAT) "cannot reuse already awaited compiled_coroutine %S", coroutine->m_qualname #else "cannot reuse already awaited coroutine" #endif ); return PYGEN_ERROR; } else #endif { *result = NULL; return PYGEN_RETURN; } } } static PyObject *_Nuitka_Coroutine_send(struct Nuitka_CoroutineObject *coroutine, PyObject *value, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { PyObject *result; PySendResult res = _Nuitka_Coroutine_sendR(coroutine, value, closing, exception_type, exception_value, exception_tb, &result); switch (res) { case PYGEN_RETURN: if (result == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } else { if (result != Py_None) { Nuitka_SetStopIterationValue(result); } Py_DECREF(result); } return NULL; case PYGEN_NEXT: return result; case PYGEN_ERROR: return NULL; default: NUITKA_CANNOT_GET_HERE("invalid PYGEN_ result"); } } static PyObject *Nuitka_Coroutine_send(struct Nuitka_CoroutineObject *coroutine, PyObject *value) { CHECK_OBJECT(coroutine); CHECK_OBJECT(value); // TODO: Does it release value ? // Py_INCREF(value); PyObject *result = _Nuitka_Coroutine_send(coroutine, value, false, NULL, NULL, NULL); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } return result; } // Note: Used by compiled frames. static bool _Nuitka_Coroutine_close(struct Nuitka_CoroutineObject *coroutine) { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); #endif CHECK_OBJECT(coroutine); if (coroutine->m_status == status_Running) { Py_INCREF(PyExc_GeneratorExit); PyObject *result = _Nuitka_Coroutine_send(coroutine, NULL, true, PyExc_GeneratorExit, NULL, NULL); if (unlikely(result)) { Py_DECREF(result); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "coroutine ignored GeneratorExit"); return false; } else { PyObject *error = GET_ERROR_OCCURRED(); assert(error != NULL); if (EXCEPTION_MATCH_GENERATOR(error)) { CLEAR_ERROR_OCCURRED(); return true; } return false; } } return true; } static PyObject *Nuitka_Coroutine_close(struct Nuitka_CoroutineObject *coroutine) { bool r = _Nuitka_Coroutine_close(coroutine); if (unlikely(r == false)) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } #if PYTHON_VERSION >= 0x360 static bool Nuitka_AsyncgenAsend_Check(PyObject *object); struct Nuitka_AsyncgenAsendObject; static PyObject *_Nuitka_AsyncgenAsend_throw2(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb); #endif static bool _Nuitka_Generator_check_throw2(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); // This function is called when yielding to a coroutine through "_Nuitka_YieldFromPassExceptionTo" // and potentially wrapper objects used by generators, or by the throw method itself. // Note: // Exception arguments are passed for ownership and must be released before returning. The // value of exception_type will not be NULL, but the actual exception will not necessarily // be normalized. static PyObject *_Nuitka_Coroutine_throw2(struct Nuitka_CoroutineObject *coroutine, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { CHECK_OBJECT(coroutine); assert(Nuitka_Coroutine_Check((PyObject *)coroutine)); CHECK_OBJECT(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_COROUTINE_STRING("closing", closing ? "(closing) " : "(not closing) "); PRINT_COROUTINE_VALUE("yieldfrom", coroutine->m_yieldfrom); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif if (coroutine->m_yieldfrom != NULL) { if (EXCEPTION_MATCH_BOOL_SINGLE(exception_type, PyExc_GeneratorExit)) { // Coroutines need to close the yield_from. coroutine->m_running = 1; bool res = Nuitka_gen_close_iter(coroutine->m_yieldfrom); coroutine->m_running = 0; if (res == false) { // Release exception, we are done with it now and pick up the new one. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); } // Transferred exception ownership to "_Nuitka_Coroutine_send". return _Nuitka_Coroutine_send(coroutine, NULL, false, exception_type, exception_value, exception_tb); } PyObject *ret; #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Passing to yielded from", coroutine); PRINT_COROUTINE_VALUE("m_yieldfrom", coroutine->m_yieldfrom); PRINT_NEW_LINE(); #endif if (PyGen_CheckExact(coroutine->m_yieldfrom) || PyCoro_CheckExact(coroutine->m_yieldfrom)) { PyGenObject *gen = (PyGenObject *)coroutine->m_yieldfrom; // Transferred exception ownership to "Nuitka_UncompiledGenerator_throw". coroutine->m_running = 1; ret = Nuitka_UncompiledGenerator_throw(gen, 1, exception_type, exception_value, exception_tb); coroutine->m_running = 0; } else if (Nuitka_Generator_Check(coroutine->m_yieldfrom)) { struct Nuitka_GeneratorObject *gen = ((struct Nuitka_GeneratorObject *)coroutine->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Generator_throw2". coroutine->m_running = 1; ret = _Nuitka_Generator_throw2(gen, exception_type, exception_value, exception_tb); coroutine->m_running = 0; } else if (Nuitka_Coroutine_Check(coroutine->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineObject *)coroutine->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Coroutine_throw2". coroutine->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); coroutine->m_running = 0; } else if (Nuitka_CoroutineWrapper_Check(coroutine->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineWrapperObject *)coroutine->m_yieldfrom)->m_coroutine; // Transferred exception ownership to "_Nuitka_Coroutine_throw2". coroutine->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); coroutine->m_running = 0; #if PYTHON_VERSION >= 0x360 } else if (Nuitka_AsyncgenAsend_Check(coroutine->m_yieldfrom)) { struct Nuitka_AsyncgenAsendObject *asyncgen_asend = ((struct Nuitka_AsyncgenAsendObject *)coroutine->m_yieldfrom); // Transferred exception ownership to "_Nuitka_AsyncgenAsend_throw2". coroutine->m_running = 1; ret = _Nuitka_AsyncgenAsend_throw2(asyncgen_asend, exception_type, exception_value, exception_tb); coroutine->m_running = 0; #endif } else { PyObject *meth = PyObject_GetAttr(coroutine->m_yieldfrom, const_str_plain_throw); if (unlikely(meth == NULL)) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } CLEAR_ERROR_OCCURRED(); // Passing exception ownership to that code. goto throw_here; } CHECK_OBJECT(exception_type); #if 0 // TODO: Add slow mode traces. PRINT_ITEM(coroutine->m_yieldfrom); PRINT_NEW_LINE(); #endif coroutine->m_running = 1; ret = PyObject_CallFunctionObjArgs(meth, exception_type, exception_value, exception_tb, NULL); coroutine->m_running = 0; Py_DECREF(meth); // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); } if (unlikely(ret == NULL)) { // Return value or exception, not to continue with yielding from. if (coroutine->m_yieldfrom != NULL) { CHECK_OBJECT(coroutine->m_yieldfrom); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Null return, yield from removal:", coroutine); PRINT_COROUTINE_VALUE("yieldfrom", coroutine->m_yieldfrom); #endif Py_DECREF(coroutine->m_yieldfrom); coroutine->m_yieldfrom = NULL; } PyObject *val; if (_PyGen_FetchStopIterationValue(&val) == 0) { CHECK_OBJECT(val); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Sending return value into ourselves", coroutine); PRINT_COROUTINE_VALUE("value", val); PRINT_NEW_LINE(); #endif ret = _Nuitka_Coroutine_send(coroutine, val, false, NULL, NULL, NULL); } else { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Sending exception value into ourselves", coroutine); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif ret = _Nuitka_Coroutine_send(coroutine, NULL, false, NULL, NULL, NULL); } #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave with value/exception from sending into ourselves:", coroutine); PRINT_COROUTINE_STRING("closing", closing ? "(closing) " : "(not closing) "); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } else { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave with return value:", coroutine); PRINT_COROUTINE_STRING("closing", closing ? "(closing) " : "(not closing) "); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } return ret; } throw_here: // We continue to have exception ownership here. if (unlikely(_Nuitka_Generator_check_throw2(&exception_type, &exception_value, &exception_tb) == false)) { // Exception was released by _Nuitka_Generator_check_throw2 already. return NULL; } if (coroutine->m_status == status_Running) { // Transferred exception ownership to "_Nuitka_Coroutine_send". PyObject *result = _Nuitka_Coroutine_send(coroutine, NULL, false, exception_type, exception_value, exception_tb); return result; } else if (coroutine->m_status == status_Finished) { /* This check got added in Python 3.5.2 only. It's good to do it, but * not fully compatible, therefore guard it. */ #if PYTHON_VERSION >= 0x352 || !defined(_NUITKA_FULL_COMPAT) if (closing == false) { #if _DEBUG_COROUTINE PRINT_STRING("Finished coroutine thrown into -> RuntimeError\n"); PRINT_ITEM(coroutine->m_qualname); PRINT_NEW_LINE(); #endif PyErr_Format(PyExc_RuntimeError, #if !defined(_NUITKA_FULL_COMPAT) "cannot reuse already awaited compiled_coroutine %S", coroutine->m_qualname #else "cannot reuse already awaited coroutine" #endif ); Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } #endif // Passing exception to publication. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; } else { if (exception_tb == NULL) { // TODO: Our compiled objects really need a way to store common // stuff in a "shared" part across all instances, and outside of // run time, so we could reuse this. struct Nuitka_FrameObject *frame = MAKE_FUNCTION_FRAME(coroutine->m_code_object, coroutine->m_module, 0); exception_tb = MAKE_TRACEBACK(frame, coroutine->m_code_object->co_firstlineno); Py_DECREF(frame); } // Passing exception to publication. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Finishing from exception", coroutine); PRINT_NEW_LINE(); #endif coroutine->m_status = status_Finished; return NULL; } } static PyObject *Nuitka_Coroutine_throw(struct Nuitka_CoroutineObject *coroutine, PyObject *args) { CHECK_OBJECT(coroutine); CHECK_OBJECT_DEEP(args); PyObject *exception_type; PyObject *exception_value = NULL; PyTracebackObject *exception_tb = NULL; // This takes no references, that is for us to do. int res = PyArg_UnpackTuple(args, "throw", 1, 3, &exception_type, &exception_value, &exception_tb); if (unlikely(res == 0)) { return NULL; } #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif // Handing ownership of exception over, we need not release it ourselves Py_INCREF(exception_type); Py_XINCREF(exception_value); Py_XINCREF(exception_tb); PyObject *result = _Nuitka_Coroutine_throw2(coroutine, false, exception_type, exception_value, exception_tb); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave", coroutine); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_COROUTINE_VALUE("return value", result); PRINT_CURRENT_EXCEPTION(); #endif return result; } static PyObject *Nuitka_Coroutine_tp_repr(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); CHECK_OBJECT(coroutine->m_qualname); return PyUnicode_FromFormat("", Nuitka_String_AsString(coroutine->m_qualname), coroutine); } static long Nuitka_Coroutine_tp_traverse(struct Nuitka_CoroutineObject *coroutine, visitproc visit, void *arg) { CHECK_OBJECT(coroutine); // TODO: Identify the impact of not visiting owned objects like module Py_VISIT(coroutine->m_yieldfrom); for (Py_ssize_t i = 0; i < coroutine->m_closure_given; i++) { Py_VISIT(coroutine->m_closure[i]); } Py_VISIT(coroutine->m_frame); return 0; } static struct Nuitka_CoroutineWrapperObject *free_list_coro_wrappers = NULL; static int free_list_coro_wrappers_count = 0; static PyObject *Nuitka_Coroutine_await(struct Nuitka_CoroutineObject *coroutine) { CHECK_OBJECT(coroutine); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_NEW_LINE(); #endif #if _DEBUG_REFCOUNTS count_active_Nuitka_CoroutineWrapper_Type += 1; count_allocated_Nuitka_CoroutineWrapper_Type += 1; #endif struct Nuitka_CoroutineWrapperObject *result; allocateFromFreeListFixed(free_list_coro_wrappers, struct Nuitka_CoroutineWrapperObject, Nuitka_CoroutineWrapper_Type); if (unlikely(result == NULL)) { return NULL; } result->m_coroutine = coroutine; Py_INCREF(result->m_coroutine); Nuitka_GC_Track(result); return (PyObject *)result; } #if PYTHON_VERSION >= 0x3a0 static PySendResult _Nuitka_Coroutine_amsend(struct Nuitka_CoroutineObject *coroutine, PyObject *arg, PyObject **result) { #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); #endif PySendResult res = _Nuitka_Coroutine_sendR(coroutine, arg, false, NULL, NULL, NULL, result); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Leave", coroutine); PRINT_COROUTINE_VALUE("result", *result); PRINT_NEW_LINE(); #endif return res; } #endif static void Nuitka_Coroutine_tp_finalize(struct Nuitka_CoroutineObject *coroutine) { if (coroutine->m_status != status_Running) { return; } PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); bool close_result = _Nuitka_Coroutine_close(coroutine); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)coroutine); } /* Restore the saved exception if any. */ RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } #define MAX_COROUTINE_FREE_LIST_COUNT 100 static struct Nuitka_CoroutineObject *free_list_coros = NULL; static int free_list_coros_count = 0; static void Nuitka_Coroutine_tp_dealloc(struct Nuitka_CoroutineObject *coroutine) { #if _DEBUG_REFCOUNTS count_active_Nuitka_Coroutine_Type -= 1; count_released_Nuitka_Coroutine_Type += 1; #endif // Revive temporarily. assert(Py_REFCNT(coroutine) == 0); Py_REFCNT(coroutine) = 1; // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); #if _DEBUG_COROUTINE PRINT_COROUTINE_STATUS("Enter", coroutine); PRINT_NEW_LINE(); #endif bool close_result = _Nuitka_Coroutine_close(coroutine); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)coroutine); } Nuitka_Coroutine_release_closure(coroutine); // Allow for above code to resurrect the coroutine. Py_REFCNT(coroutine) -= 1; if (Py_REFCNT(coroutine) >= 1) { RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); return; } if (coroutine->m_frame) { coroutine->m_frame->m_frame.f_gen = NULL; Py_DECREF(coroutine->m_frame); coroutine->m_frame = NULL; } // Now it is safe to release references and memory for it. Nuitka_GC_UnTrack(coroutine); if (coroutine->m_weakrefs != NULL) { PyObject_ClearWeakRefs((PyObject *)coroutine); assert(!ERROR_OCCURRED()); } Py_DECREF(coroutine->m_name); Py_DECREF(coroutine->m_qualname); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_coros, coroutine, MAX_COROUTINE_FREE_LIST_COUNT); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } // TODO: Set "__doc__" automatically for method clones of compiled types from // the documentation of built-in original type. static PyMethodDef Nuitka_Coroutine_methods[] = {{"send", (PyCFunction)Nuitka_Coroutine_send, METH_O, NULL}, {"throw", (PyCFunction)Nuitka_Coroutine_throw, METH_VARARGS, NULL}, {"close", (PyCFunction)Nuitka_Coroutine_close, METH_NOARGS, NULL}, {NULL}}; // TODO: Set "__doc__" automatically for method clones of compiled types from // the documentation of built-in original type. static PyGetSetDef Nuitka_Coroutine_getsetlist[] = { {(char *)"__name__", (getter)Nuitka_Coroutine_get_name, (setter)Nuitka_Coroutine_set_name, NULL}, {(char *)"__qualname__", (getter)Nuitka_Coroutine_get_qualname, (setter)Nuitka_Coroutine_set_qualname, NULL}, {(char *)"cr_await", (getter)Nuitka_Coroutine_get_cr_await, (setter)NULL, NULL}, {(char *)"cr_code", (getter)Nuitka_Coroutine_get_code, (setter)Nuitka_Coroutine_set_code, NULL}, {(char *)"cr_frame", (getter)Nuitka_Coroutine_get_frame, (setter)Nuitka_Coroutine_set_frame, NULL}, {NULL}}; static PyMemberDef Nuitka_Coroutine_members[] = { {(char *)"cr_running", T_BOOL, offsetof(struct Nuitka_CoroutineObject, m_running), READONLY}, #if PYTHON_VERSION >= 0x370 {(char *)"cr_origin", T_OBJECT, offsetof(struct Nuitka_CoroutineObject, m_origin), READONLY}, #endif {NULL}}; static PyAsyncMethods Nuitka_Coroutine_as_async = { (unaryfunc)Nuitka_Coroutine_await, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ #if PYTHON_VERSION >= 0x3a0 , (sendfunc)_Nuitka_Coroutine_amsend /* am_send */ #endif }; PyTypeObject Nuitka_Coroutine_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_coroutine", /* tp_name */ sizeof(struct Nuitka_CoroutineObject), /* tp_basicsize */ sizeof(struct Nuitka_CellObject *), /* tp_itemsize */ (destructor)Nuitka_Coroutine_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ &Nuitka_Coroutine_as_async, /* tp_as_async */ (reprfunc)Nuitka_Coroutine_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Nuitka_Coroutine_tp_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Coroutine_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(struct Nuitka_CoroutineObject, m_weakrefs), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Coroutine_methods, /* tp_methods */ Nuitka_Coroutine_members, /* tp_members */ Nuitka_Coroutine_getsetlist, /* tp_getset */ #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyCoro_Type, /* tp_base */ #else 0, /* tp_base */ #endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ (destructor)Nuitka_Coroutine_tp_finalize, /* tp_finalize */ }; static void Nuitka_CoroutineWrapper_tp_dealloc(struct Nuitka_CoroutineWrapperObject *cw) { Nuitka_GC_UnTrack((PyObject *)cw); assert(Py_REFCNT(cw) == 0); Py_REFCNT(cw) = 1; #if _DEBUG_REFCOUNTS count_active_Nuitka_CoroutineWrapper_Type -= 1; count_released_Nuitka_CoroutineWrapper_Type += 1; #endif CHECK_OBJECT(cw->m_coroutine); Py_DECREF(cw->m_coroutine); cw->m_coroutine = NULL; assert(Py_REFCNT(cw) == 1); Py_REFCNT(cw) = 0; releaseToFreeList(free_list_coro_wrappers, cw, MAX_COROUTINE_FREE_LIST_COUNT); } static PyObject *Nuitka_CoroutineWrapper_tp_iternext(struct Nuitka_CoroutineWrapperObject *cw) { CHECK_OBJECT(cw); return Nuitka_Coroutine_send(cw->m_coroutine, Py_None); } static int Nuitka_CoroutineWrapper_tp_traverse(struct Nuitka_CoroutineWrapperObject *cw, visitproc visit, void *arg) { CHECK_OBJECT(cw); Py_VISIT((PyObject *)cw->m_coroutine); return 0; } static PyObject *Nuitka_CoroutineWrapper_send(struct Nuitka_CoroutineWrapperObject *cw, PyObject *arg) { CHECK_OBJECT(cw); CHECK_OBJECT(arg); return Nuitka_Coroutine_send(cw->m_coroutine, arg); } static PyObject *Nuitka_CoroutineWrapper_throw(struct Nuitka_CoroutineWrapperObject *cw, PyObject *args) { CHECK_OBJECT(cw); CHECK_OBJECT_DEEP(args); return Nuitka_Coroutine_throw(cw->m_coroutine, args); } static PyObject *Nuitka_CoroutineWrapper_close(struct Nuitka_CoroutineWrapperObject *cw) { CHECK_OBJECT(cw); return Nuitka_Coroutine_close(cw->m_coroutine); } static PyObject *Nuitka_CoroutineWrapper_tp_repr(struct Nuitka_CoroutineWrapperObject *cw) { CHECK_OBJECT(cw); CHECK_OBJECT(cw->m_coroutine); CHECK_OBJECT(cw->m_coroutine->m_qualname); return PyUnicode_FromFormat("", Nuitka_String_AsString(cw->m_coroutine->m_qualname), cw); } static PyMethodDef Nuitka_CoroutineWrapper_methods[] = { {"send", (PyCFunction)Nuitka_CoroutineWrapper_send, METH_O, NULL}, {"throw", (PyCFunction)Nuitka_CoroutineWrapper_throw, METH_VARARGS, NULL}, {"close", (PyCFunction)Nuitka_CoroutineWrapper_close, METH_NOARGS, NULL}, {NULL}}; PyTypeObject Nuitka_CoroutineWrapper_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_coroutine_wrapper", sizeof(struct Nuitka_CoroutineWrapperObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_CoroutineWrapper_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)Nuitka_CoroutineWrapper_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_CoroutineWrapper_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)Nuitka_CoroutineWrapper_tp_iternext, /* tp_iternext */ Nuitka_CoroutineWrapper_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ }; #if PYTHON_VERSION >= 0x370 static PyObject *computeCoroutineOrigin(int origin_depth) { PyFrameObject *frame = PyEval_GetFrame(); int frame_count = 0; while (frame != NULL && frame_count < origin_depth) { frame = frame->f_back; frame_count += 1; } PyObject *cr_origin = PyTuple_New(frame_count); frame = PyEval_GetFrame(); for (int i = 0; i < frame_count; i++) { PyObject *frameinfo = Py_BuildValue("OiO", frame->f_code->co_filename, PyFrame_GetLineNumber(frame), frame->f_code->co_name); assert(frameinfo); PyTuple_SET_ITEM(cr_origin, i, frameinfo); frame = frame->f_back; } return cr_origin; } #endif PyObject *Nuitka_Coroutine_New(coroutine_code code, PyObject *module, PyObject *name, PyObject *qualname, PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size) { #if _DEBUG_REFCOUNTS count_active_Nuitka_Coroutine_Type += 1; count_allocated_Nuitka_Coroutine_Type += 1; #endif struct Nuitka_CoroutineObject *result; // TODO: Change the var part of the type to 1 maybe Py_ssize_t full_size = closure_given + (heap_storage_size + sizeof(void *) - 1) / sizeof(void *); // Macro to assign result memory from GC or free list. allocateFromFreeList(free_list_coros, struct Nuitka_CoroutineObject, Nuitka_Coroutine_Type, full_size); // For quicker access of generator heap. result->m_heap_storage = &result->m_closure[closure_given]; result->m_code = (void *)code; CHECK_OBJECT(module); result->m_module = module; CHECK_OBJECT(name); result->m_name = name; Py_INCREF(name); // The "qualname" defaults to NULL for most compact C code. if (qualname == NULL) { qualname = name; } CHECK_OBJECT(qualname); result->m_qualname = qualname; Py_INCREF(qualname); result->m_yieldfrom = NULL; memcpy(&result->m_closure[0], closure, closure_given * sizeof(struct Nuitka_CellObject *)); result->m_closure_given = closure_given; result->m_weakrefs = NULL; result->m_status = status_Unused; result->m_running = false; result->m_awaiting = false; result->m_yield_return_index = 0; result->m_returned = NULL; result->m_frame = NULL; result->m_code_object = code_object; result->m_resume_frame = NULL; #if PYTHON_VERSION >= 0x370 PyThreadState *tstate = PyThreadState_GET(); int origin_depth = tstate->coroutine_origin_tracking_depth; if (origin_depth == 0) { result->m_origin = NULL; } else { result->m_origin = computeCoroutineOrigin(origin_depth); } #endif #if PYTHON_VERSION >= 0x370 result->m_exc_state.exc_type = NULL; result->m_exc_state.exc_value = NULL; result->m_exc_state.exc_traceback = NULL; #endif static long Nuitka_Coroutine_counter = 0; result->m_counter = Nuitka_Coroutine_counter++; Nuitka_GC_Track(result); return (PyObject *)result; } static int gen_is_coroutine(PyObject *object) { if (PyGen_CheckExact(object)) { PyCodeObject *code = (PyCodeObject *)((PyGenObject *)object)->gi_code; if (code->co_flags & CO_ITERABLE_COROUTINE) { return 1; } } return 0; } static PyObject *Nuitka_GetAwaitableIter(PyObject *value) { CHECK_OBJECT(value); #if _DEBUG_COROUTINE PRINT_STRING("Nuitka_GetAwaitableIter: Enter "); PRINT_ITEM(value); PRINT_NEW_LINE(); #endif unaryfunc getter = NULL; if (PyCoro_CheckExact(value) || gen_is_coroutine(value)) { Py_INCREF(value); return value; } if (Py_TYPE(value)->tp_as_async != NULL) { getter = Py_TYPE(value)->tp_as_async->am_await; } if (getter != NULL) { PyObject *result = (*getter)(value); if (result != NULL) { if (unlikely(PyCoro_CheckExact(result) || gen_is_coroutine(result) || Nuitka_Coroutine_Check(result))) { Py_DECREF(result); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__await__() returned a coroutine"); return NULL; } if (unlikely(!HAS_ITERNEXT(result))) { PyErr_Format(PyExc_TypeError, "__await__() returned non-iterator of type '%s'", Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } } return result; } PyErr_Format(PyExc_TypeError, "object %s can't be used in 'await' expression", Py_TYPE(value)->tp_name); return NULL; } #if PYTHON_VERSION >= 0x366 static void FORMAT_AWAIT_ERROR(PyObject *value, int await_kind) { CHECK_OBJECT(value); if (await_kind == await_enter) { PyErr_Format(PyExc_TypeError, "'async with' received an object from __aenter__ that does not implement __await__: %s", Py_TYPE(value)->tp_name); } else if (await_kind == await_exit) { PyErr_Format(PyExc_TypeError, "'async with' received an object from __aexit__ that does not implement __await__: %s", Py_TYPE(value)->tp_name); } assert(ERROR_OCCURRED()); } #endif PyObject *ASYNC_AWAIT(PyObject *awaitable, int await_kind) { CHECK_OBJECT(awaitable); #if _DEBUG_COROUTINE PRINT_STRING("ASYNC_AWAIT: Enter for awaitable "); PRINT_STRING(await_kind == await_enter ? "enter" : "exit"); PRINT_STRING(" "); PRINT_ITEM(awaitable); PRINT_NEW_LINE(); #endif PyObject *awaitable_iter = Nuitka_GetAwaitableIter(awaitable); if (unlikely(awaitable_iter == NULL)) { #if PYTHON_VERSION >= 0x366 FORMAT_AWAIT_ERROR(awaitable, await_kind); #endif return NULL; } #if PYTHON_VERSION >= 0x352 || !defined(_NUITKA_FULL_COMPAT) /* This check got added in Python 3.5.2 only. It's good to do it, but * not fully compatible, therefore guard it. */ if (Nuitka_Coroutine_Check(awaitable)) { struct Nuitka_CoroutineObject *awaited_coroutine = (struct Nuitka_CoroutineObject *)awaitable; if (awaited_coroutine->m_awaiting) { Py_DECREF(awaitable_iter); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "coroutine is being awaited already"); return NULL; } } #endif #if _DEBUG_COROUTINE PRINT_STRING("ASYNC_AWAIT: Result "); PRINT_ITEM(awaitable); PRINT_NEW_LINE(); #endif return awaitable_iter; } #if PYTHON_VERSION >= 0x352 /* Our "aiter" wrapper clone */ struct Nuitka_AIterWrapper { /* Python object folklore: */ PyObject_HEAD PyObject *aw_aiter; }; static PyObject *Nuitka_AIterWrapper_tp_repr(struct Nuitka_AIterWrapper *aw) { return PyUnicode_FromFormat("", aw->aw_aiter, aw); } static PyObject *Nuitka_AIterWrapper_iternext(struct Nuitka_AIterWrapper *aw) { CHECK_OBJECT(aw); #if PYTHON_VERSION < 0x360 SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_StopIteration, aw->aw_aiter); #else if (!PyTuple_Check(aw->aw_aiter) && !PyExceptionInstance_Check(aw->aw_aiter)) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_StopIteration, aw->aw_aiter); } else { PyObject *result = PyObject_CallFunctionObjArgs(PyExc_StopIteration, aw->aw_aiter, NULL); if (unlikely(result == NULL)) { return NULL; } SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyExc_StopIteration, result); } #endif return NULL; } static int Nuitka_AIterWrapper_traverse(struct Nuitka_AIterWrapper *aw, visitproc visit, void *arg) { CHECK_OBJECT(aw); Py_VISIT((PyObject *)aw->aw_aiter); return 0; } static struct Nuitka_AIterWrapper *free_list_coroutine_aiter_wrappers = NULL; static int free_list_coroutine_aiter_wrappers_count = 0; static void Nuitka_AIterWrapper_dealloc(struct Nuitka_AIterWrapper *aw) { #if _DEBUG_REFCOUNTS count_active_Nuitka_AIterWrapper_Type -= 1; count_released_Nuitka_AIterWrapper_Type += 1; #endif Nuitka_GC_UnTrack((PyObject *)aw); CHECK_OBJECT(aw->aw_aiter); Py_DECREF(aw->aw_aiter); /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_coroutine_aiter_wrappers, aw, MAX_COROUTINE_FREE_LIST_COUNT); } static PyAsyncMethods Nuitka_AIterWrapper_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ }; PyTypeObject Nuitka_AIterWrapper_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_aiter_wrapper", sizeof(struct Nuitka_AIterWrapper), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_AIterWrapper_dealloc, /* destructor tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ &Nuitka_AIterWrapper_as_async, /* tp_as_async */ (reprfunc)Nuitka_AIterWrapper_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "A wrapper object for '__aiter__' backwards compatibility.", (traverseproc)Nuitka_AIterWrapper_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)Nuitka_AIterWrapper_iternext, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ }; static PyObject *Nuitka_AIterWrapper_New(PyObject *aiter) { CHECK_OBJECT(aiter); #if _DEBUG_REFCOUNTS count_active_Nuitka_AIterWrapper_Type += 1; count_allocated_Nuitka_AIterWrapper_Type += 1; #endif struct Nuitka_AIterWrapper *result; allocateFromFreeListFixed(free_list_coroutine_aiter_wrappers, struct Nuitka_AIterWrapper, Nuitka_AIterWrapper_Type); CHECK_OBJECT(aiter); Py_INCREF(aiter); result->aw_aiter = aiter; Nuitka_GC_Track(result); return (PyObject *)result; } #endif PyObject *ASYNC_MAKE_ITERATOR(PyObject *value) { CHECK_OBJECT(value); #if _DEBUG_COROUTINE PRINT_STRING("AITER entry:"); PRINT_ITEM(value); PRINT_NEW_LINE(); #endif unaryfunc getter = NULL; if (Py_TYPE(value)->tp_as_async) { getter = Py_TYPE(value)->tp_as_async->am_aiter; } if (unlikely(getter == NULL)) { PyErr_Format(PyExc_TypeError, "'async for' requires an object with __aiter__ method, got %s", Py_TYPE(value)->tp_name); return NULL; } PyObject *iter = (*getter)(value); if (unlikely(iter == NULL)) { return NULL; } #if PYTHON_VERSION >= 0x370 if (unlikely(Py_TYPE(iter)->tp_as_async == NULL || Py_TYPE(iter)->tp_as_async->am_anext == NULL)) { PyErr_Format(PyExc_TypeError, "'async for' received an object from __aiter__ that does not implement __anext__: %s", Py_TYPE(iter)->tp_name); Py_DECREF(iter); return NULL; } #endif #if PYTHON_VERSION >= 0x352 /* Starting with Python 3.5.2 it is acceptable to return an async iterator * directly, instead of an awaitable. */ if (Py_TYPE(iter)->tp_as_async != NULL && Py_TYPE(iter)->tp_as_async->am_anext != NULL) { PyObject *wrapper = Nuitka_AIterWrapper_New(iter); Py_DECREF(iter); iter = wrapper; } #endif PyObject *awaitable_iter = Nuitka_GetAwaitableIter(iter); if (unlikely(awaitable_iter == NULL)) { #if PYTHON_VERSION >= 0x360 _PyErr_FormatFromCause( #else PyErr_Format( #endif PyExc_TypeError, "'async for' received an invalid object from __aiter__: %s", Py_TYPE(iter)->tp_name); Py_DECREF(iter); return NULL; } Py_DECREF(iter); return awaitable_iter; } PyObject *ASYNC_ITERATOR_NEXT(PyObject *value) { CHECK_OBJECT(value); #if _DEBUG_COROUTINE PRINT_STRING("ANEXT entry:"); PRINT_ITEM(value); PRINT_NEW_LINE(); #endif unaryfunc getter = NULL; if (Py_TYPE(value)->tp_as_async) { getter = Py_TYPE(value)->tp_as_async->am_anext; } if (unlikely(getter == NULL)) { PyErr_Format(PyExc_TypeError, "'async for' requires an iterator with __anext__ method, got %s", Py_TYPE(value)->tp_name); return NULL; } PyObject *next_value = (*getter)(value); if (unlikely(next_value == NULL)) { return NULL; } PyObject *awaitable_iter = Nuitka_GetAwaitableIter(next_value); if (unlikely(awaitable_iter == NULL)) { #if PYTHON_VERSION >= 0x360 _PyErr_FormatFromCause( #else PyErr_Format( #endif PyExc_TypeError, "'async for' received an invalid object from __anext__: %s", Py_TYPE(next_value)->tp_name); Py_DECREF(next_value); return NULL; } Py_DECREF(next_value); return awaitable_iter; } static void _initCompiledCoroutineTypes(void) { PyType_Ready(&Nuitka_Coroutine_Type); // Be a paranoid subtype of uncompiled function, we want nothing shared. assert(Nuitka_Coroutine_Type.tp_doc != PyCoro_Type.tp_doc || PyCoro_Type.tp_doc == NULL); assert(Nuitka_Coroutine_Type.tp_traverse != PyCoro_Type.tp_traverse); assert(Nuitka_Coroutine_Type.tp_clear != PyCoro_Type.tp_clear || PyCoro_Type.tp_clear == NULL); assert(Nuitka_Coroutine_Type.tp_richcompare != PyCoro_Type.tp_richcompare || PyCoro_Type.tp_richcompare == NULL); assert(Nuitka_Coroutine_Type.tp_weaklistoffset != PyCoro_Type.tp_weaklistoffset); assert(Nuitka_Coroutine_Type.tp_iter != PyCoro_Type.tp_iter || PyCoro_Type.tp_iter == NULL); assert(Nuitka_Coroutine_Type.tp_iternext != PyCoro_Type.tp_iternext || PyCoro_Type.tp_iternext == NULL); assert(Nuitka_Coroutine_Type.tp_methods != PyCoro_Type.tp_methods); assert(Nuitka_Coroutine_Type.tp_members != PyCoro_Type.tp_members); assert(Nuitka_Coroutine_Type.tp_getset != PyCoro_Type.tp_getset); #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) assert(Nuitka_Coroutine_Type.tp_base != PyCoro_Type.tp_base); #endif assert(Nuitka_Coroutine_Type.tp_dict != PyCoro_Type.tp_dict); assert(Nuitka_Coroutine_Type.tp_descr_get != PyCoro_Type.tp_descr_get || PyCoro_Type.tp_descr_get == NULL); assert(Nuitka_Coroutine_Type.tp_descr_set != PyCoro_Type.tp_descr_set || PyCoro_Type.tp_descr_set == NULL); assert(Nuitka_Coroutine_Type.tp_dictoffset != PyCoro_Type.tp_dictoffset || PyCoro_Type.tp_dictoffset == 0); // TODO: These get changed and into the same thing, not sure what to compare against, project something // assert(Nuitka_Generator_Type.tp_init != PyCoro_Type.tp_init || PyCoro_Type.tp_init == NULL); // assert(Nuitka_Generator_Type.tp_alloc != PyCoro_Type.tp_alloc || PyCoro_Type.tp_alloc == NULL); // assert(Nuitka_Generator_Type.tp_new != PyCoro_Type.tp_new || PyCoro_Type.tp_new == NULL); // assert(Nuitka_Generator_Type.tp_free != PyCoro_Type.tp_free || PyCoro_Type.tp_free == NULL); assert(Nuitka_Coroutine_Type.tp_bases != PyCoro_Type.tp_bases); assert(Nuitka_Coroutine_Type.tp_mro != PyCoro_Type.tp_mro); assert(Nuitka_Coroutine_Type.tp_cache != PyCoro_Type.tp_cache || PyCoro_Type.tp_cache == NULL); assert(Nuitka_Coroutine_Type.tp_subclasses != PyCoro_Type.tp_subclasses || PyCoro_Type.tp_cache == NULL); assert(Nuitka_Coroutine_Type.tp_weaklist != PyCoro_Type.tp_weaklist); assert(Nuitka_Coroutine_Type.tp_del != PyCoro_Type.tp_del || PyCoro_Type.tp_del == NULL); assert(Nuitka_Coroutine_Type.tp_finalize != PyCoro_Type.tp_finalize || PyCoro_Type.tp_finalize == NULL); PyType_Ready(&Nuitka_CoroutineWrapper_Type); #if PYTHON_VERSION >= 0x352 PyType_Ready(&Nuitka_AIterWrapper_Type); #endif } // Chain asyncgen code to coroutine and generator code, as it uses same functions, // and then we can have some things static if both are in the same compilation unit. #if PYTHON_VERSION >= 0x360 #include "CompiledAsyncgenType.c" #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonLe.c0000600000372100037210000156470214166627112031120 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<=" (LE) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_LE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a <= b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_LE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a <= b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_LE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a <= b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LE_OBJECT_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LE_CBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; bool result = r; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_LE_NBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_LE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_LE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_LE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_LE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_LE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_LE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_LE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LE); CHECK_OBJECT(r); return r; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_LE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LE); CHECK_OBJECT(r); // Convert to target type if necessary bool result = r == Py_True; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_LE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } PyObject *r = PyUnicode_RichCompare((PyObject *)a, (PyObject *)b, Py_LE); CHECK_OBJECT(r); // Convert to target type if necessary nuitka_bool result = r == Py_True ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(r); return result; } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_LE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_LE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_LE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_LE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. bool result = c != 0; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_LE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_LE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. nuitka_bool result = c != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_LE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_LE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); Py_ssize_t min_len = (len_a < len_b) ? len_a : len_b; int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) { c = memcmp(a->ob_sval, b->ob_sval, min_len); } } else { c = 0; } if (c == 0) { c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; } c = c <= 0; // Convert to target type. PyObject *result = BOOL_FROM(c != 0); Py_INCREF(result); return result; } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_LE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_LE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_LE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_LE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_LE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_LE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_LE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_LE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_LE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_LE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = Py_SIZE(a) - Py_SIZE(b) < 0; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = a->ob_digit[i] < b->ob_digit[i]; if (Py_SIZE(a) < 0) r = !r; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_LE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() <= %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a <= b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_LE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_LE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a <= b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_LE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_LE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a <= b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_LE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_LE_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_LE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_LE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_LE_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_LE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_LE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_LE_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_LE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_LE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } return RICH_COMPARE_LE_OBJECT_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_LE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_LE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. bool result = r; return result; } return RICH_COMPARE_LE_CBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_LE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_LE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); bool found = false; nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { found = true; break; } } if (found == false) { bool r = len_a <= len_b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } return RICH_COMPARE_LE_NBOOL_OBJECT_OBJECT(a->ob_item[i], b->ob_item[i]); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_LE_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_LE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_LE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() <= list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_LE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LE_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_LE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LE_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_LE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_LE_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_LE) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_LE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_GE); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_LE) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() <= %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'<=' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersDeepcopy.c0000600000372100037210000004550314166627112030265 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** * This is responsible for deep copy and hashing of constants. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #if PYTHON_VERSION >= 0x390 typedef struct { PyObject_HEAD PyObject *origin; PyObject *args; PyObject *parameters; } GenericAliasObject; #endif typedef PyObject *(*copy_func)(PyObject *); static PyObject *DEEP_COPY_ITEM(PyObject *value, PyTypeObject **type, copy_func *copy_function); PyObject *DEEP_COPY_DICT(PyObject *value) { #if PYTHON_VERSION < 0x300 // For Python3, this can be done much faster in the same way as it is // done in parameter parsing. PyObject *result = _PyDict_NewPresized(((PyDictObject *)value)->ma_used); for (Py_ssize_t i = 0; i <= ((PyDictObject *)value)->ma_mask; i++) { PyDictEntry *entry = &((PyDictObject *)value)->ma_table[i]; if (entry->me_value != NULL) { PyObject *deep_copy = DEEP_COPY(entry->me_value); int res = PyDict_SetItem(result, entry->me_key, deep_copy); Py_DECREF(deep_copy); CHECK_OBJECT(deep_copy); if (unlikely(res != 0)) { return NULL; } } } return result; #else /* Python 3 */ if (_PyDict_HasSplitTable((PyDictObject *)value)) { PyDictObject *mp = (PyDictObject *)value; PyObject **newvalues = PyMem_NEW(PyObject *, mp->ma_keys->dk_size); assert(newvalues != NULL); PyDictObject *result = PyObject_GC_New(PyDictObject, &PyDict_Type); assert(result != NULL); result->ma_values = newvalues; result->ma_keys = mp->ma_keys; result->ma_used = mp->ma_used; mp->ma_keys->dk_refcnt += 1; Nuitka_GC_Track(result); #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = DK_USABLE_FRACTION(DK_SIZE(mp->ma_keys)); #endif for (Py_ssize_t i = 0; i < size; i++) { if (mp->ma_values[i]) { result->ma_values[i] = DEEP_COPY(mp->ma_values[i]); } else { result->ma_values[i] = NULL; } } return (PyObject *)result; } else { PyObject *result = _PyDict_NewPresized(((PyDictObject *)value)->ma_used); PyDictObject *mp = (PyDictObject *)value; #if PYTHON_VERSION < 0x360 Py_ssize_t size = mp->ma_keys->dk_size; #else Py_ssize_t size = mp->ma_keys->dk_nentries; #endif for (Py_ssize_t i = 0; i < size; i++) { #if PYTHON_VERSION < 0x360 PyDictKeyEntry *entry = &mp->ma_keys->dk_entries[i]; #else PyDictKeyEntry *entry = &DK_ENTRIES(mp->ma_keys)[i]; #endif if (entry->me_value != NULL) { PyObject *deep_copy = DEEP_COPY(entry->me_value); PyDict_SetItem(result, entry->me_key, deep_copy); Py_DECREF(deep_copy); CHECK_OBJECT(deep_copy); } } return result; } #endif } PyObject *DEEP_COPY_LIST(PyObject *value) { assert(PyList_CheckExact(value)); Py_ssize_t n = PyList_GET_SIZE(value); PyObject *result = PyList_New(n); PyTypeObject *type = NULL; copy_func copy_function = NULL; for (Py_ssize_t i = 0; i < n; i++) { PyObject *item = PyList_GET_ITEM(value, i); if (i == 0) { PyList_SET_ITEM(result, i, DEEP_COPY_ITEM(item, &type, ©_function)); } else { PyObject *new_item; if (likely(type == Py_TYPE(item))) { if (copy_function) { new_item = copy_function(item); } else { new_item = item; Py_INCREF(item); } } else { new_item = DEEP_COPY_ITEM(item, &type, ©_function); } PyList_SET_ITEM(result, i, new_item); } } return result; } PyObject *DEEP_COPY_TUPLE(PyObject *value) { assert(PyTuple_CheckExact(value)); Py_ssize_t n = PyTuple_GET_SIZE(value); PyObject *result = PyTuple_New(n); for (Py_ssize_t i = 0; i < n; i++) { PyTuple_SET_ITEM(result, i, DEEP_COPY(PyTuple_GET_ITEM(value, i))); } return result; } PyObject *DEEP_COPY_SET(PyObject *value) { // Sets cannot contain unhashable types, so these all must be immutable, // but the set itself might be changed, so we need to copy it. return PySet_New(value); } #if PYTHON_VERSION >= 0x390 PyObject *DEEP_COPY_GENERICALIAS(PyObject *value) { assert(Py_TYPE(value) == &Py_GenericAliasType); GenericAliasObject *generic_alias = (GenericAliasObject *)value; PyObject *args = DEEP_COPY(generic_alias->args); PyObject *origin = DEEP_COPY(generic_alias->origin); if (generic_alias->args == args && generic_alias->origin == origin) { Py_INCREF(value); return value; } else { return Py_GenericAlias(origin, args); } } #endif static PyObject *_deep_copy_dispatch = NULL; static PyObject *_deep_noop = NULL; static PyObject *Nuitka_CapsuleNew(void *pointer) { #if PYTHON_VERSION < 0x300 return PyCObject_FromVoidPtr(pointer, NULL); #else return PyCapsule_New(pointer, "", NULL); #endif } #if PYTHON_VERSION >= 0x300 typedef struct { PyObject_HEAD void *pointer; const char *name; void *context; PyCapsule_Destructor destructor; } Nuitka_PyCapsule; #define Nuitka_CapsuleGetPointer(capsule) (((Nuitka_PyCapsule *)(capsule))->pointer) #else #define Nuitka_CapsuleGetPointer(capsule) (PyCObject_AsVoidPtr(capsule)) #endif static void _initDeepCopy() { _deep_copy_dispatch = PyDict_New(); _deep_noop = Py_None; CHECK_OBJECT(_deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyDict_Type, Nuitka_CapsuleNew((void *)DEEP_COPY_DICT)); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyList_Type, Nuitka_CapsuleNew((void *)DEEP_COPY_LIST)); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyTuple_Type, Nuitka_CapsuleNew((void *)DEEP_COPY_TUPLE)); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PySet_Type, Nuitka_CapsuleNew((void *)DEEP_COPY_SET)); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyByteArray_Type, Nuitka_CapsuleNew((void *)BYTEARRAY_COPY)); #if PYTHON_VERSION >= 0x390 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&Py_GenericAliasType, Nuitka_CapsuleNew((void *)DEEP_COPY_GENERICALIAS)); #endif #if PYTHON_VERSION >= 0x3a0 { PyObject *args[2] = {(PyObject *)&PyFloat_Type, (PyObject *)&PyTuple_Type}; PyObject *args_tuple = MAKE_TUPLE(args, 2); PyObject *union_value = MAKE_UNION_TYPE(args_tuple); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(union_value), _deep_noop); Py_DECREF(union_value); Py_DECREF(args_tuple); } #endif #if PYTHON_VERSION < 0x300 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyString_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyInt_Type, _deep_noop); #else PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyBytes_Type, _deep_noop); #endif PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyUnicode_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyLong_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_None), _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyBool_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyFloat_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyRange_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyType_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PySlice_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyComplex_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyCFunction_Type, _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_Ellipsis), _deep_noop); PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_NotImplemented), _deep_noop); // Sets can be changed, but frozensets not. PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyFrozenSet_Type, _deep_noop); } static PyObject *DEEP_COPY_ITEM(PyObject *value, PyTypeObject **type, copy_func *copy_function) { *type = Py_TYPE(value); PyObject *dispatcher = DICT_GET_ITEM0(_deep_copy_dispatch, (PyObject *)*type); if (unlikely(dispatcher == NULL)) { NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type"); } if (dispatcher == Py_None) { *copy_function = NULL; Py_INCREF(value); return value; } else { *copy_function = (copy_func)(Nuitka_CapsuleGetPointer(dispatcher)); return (*copy_function)(value); } } PyObject *DEEP_COPY(PyObject *value) { #if 1 PyObject *dispatcher = DICT_GET_ITEM0(_deep_copy_dispatch, (PyObject *)Py_TYPE(value)); if (unlikely(dispatcher == NULL)) { NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type"); } if (dispatcher == Py_None) { Py_INCREF(value); return value; } else { copy_func copy_function = (copy_func)(Nuitka_CapsuleGetPointer(dispatcher)); return copy_function(value); } #else if (PyDict_CheckExact(value)) { return DEEP_COPY_DICT(value); } else if (PyList_CheckExact(value)) { return DEEP_COPY_LIST(value); } else if (PyTuple_CheckExact(value)) { return DEEP_COPY_TUPLE(value); } else if (PySet_CheckExact(value)) { return DEEP_COPY_SET(value); } else if (PyFrozenSet_CheckExact(value)) { // Sets cannot contain unhashable types, so they must be immutable and // the frozenset itself is immutable. return value; } else if ( #if PYTHON_VERSION < 0x300 PyString_Check(value) || #endif PyUnicode_Check(value) || #if PYTHON_VERSION < 0x300 PyInt_CheckExact(value) || #endif PyLong_CheckExact(value) || value == Py_None || PyBool_Check(value) || PyFloat_CheckExact(value) || PyBytes_CheckExact(value) || PyRange_Check(value) || PyType_Check(value) || PySlice_Check(value) || PyComplex_CheckExact(value) || PyCFunction_Check(value) || value == Py_Ellipsis || value == Py_NotImplemented) { Py_INCREF(value); return value; } else if (PyByteArray_CheckExact(value)) { // TODO: Could make an exception for zero size. return PyByteArray_FromObject(value); #if PYTHON_VERSION >= 0x390 } else if (Py_TYPE(value) == &Py_GenericAliasType) { GenericAliasObject *generic_alias = (GenericAliasObject *)value; PyObject *args = DEEP_COPY(generic_alias->args); PyObject *origin = DEEP_COPY(generic_alias->origin); if (generic_alias->args == args && generic_alias->origin == origin) { Py_INCREF(value); return value; } else { return Py_GenericAlias(origin, args); } #endif } else { NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type"); } #endif } #ifndef __NUITKA_NO_ASSERT__ static Py_hash_t DEEP_HASH_INIT(PyObject *value) { // To avoid warnings about reduced sizes, we put an intermediate value // that is size_t. size_t value2 = (size_t)value; Py_hash_t result = (Py_hash_t)(value2); if (Py_TYPE(value) != &PyType_Type) { result ^= DEEP_HASH((PyObject *)Py_TYPE(value)); } return result; } static void DEEP_HASH_BLOB(Py_hash_t *hash, char const *s, Py_ssize_t size) { while (size > 0) { *hash = (1000003 * (*hash)) ^ (Py_hash_t)(*s++); size--; } } static void DEEP_HASH_CSTR(Py_hash_t *hash, char const *s) { DEEP_HASH_BLOB(hash, s, strlen(s)); } // Hash function that actually verifies things done to the bit level. Can be // used to detect corruption. Py_hash_t DEEP_HASH(PyObject *value) { assert(value != NULL); if (PyType_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); DEEP_HASH_CSTR(&result, ((PyTypeObject *)value)->tp_name); return result; } else if (PyDict_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t ppos = 0; PyObject *key, *dict_value; while (PyDict_Next(value, &ppos, &key, &dict_value)) { if (key != NULL && value != NULL) { result ^= DEEP_HASH(key); result ^= DEEP_HASH(dict_value); } } return result; } else if (PyTuple_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t n = PyTuple_GET_SIZE(value); for (Py_ssize_t i = 0; i < n; i++) { result ^= DEEP_HASH(PyTuple_GET_ITEM(value, i)); } return result; } else if (PyList_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t n = PyList_GET_SIZE(value); for (Py_ssize_t i = 0; i < n; i++) { result ^= DEEP_HASH(PyList_GET_ITEM(value, i)); } return result; } else if (PySet_Check(value) || PyFrozenSet_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); PyObject *iterator = PyObject_GetIter(value); CHECK_OBJECT(iterator); while (true) { PyObject *item = PyIter_Next(iterator); if (!item) break; CHECK_OBJECT(item); result ^= DEEP_HASH(item); Py_DECREF(item); } Py_DECREF(iterator); return result; } else if (PyLong_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED_UNTRACED(&exception_type, &exception_value, &exception_tb); // Use string to hash the long value, which relies on that to not // use the object address. PyObject *str = PyObject_Str(value); result ^= DEEP_HASH(str); Py_DECREF(str); RESTORE_ERROR_OCCURRED_UNTRACED(exception_type, exception_value, exception_tb); return result; } else if (PyUnicode_Check(value)) { Py_hash_t result = DEEP_HASH((PyObject *)Py_TYPE(value)); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED_UNTRACED(&exception_type, &exception_value, &exception_tb); #if PYTHON_VERSION >= 0x300 char const *s = (char const *)PyUnicode_DATA(value); Py_ssize_t size = PyUnicode_GET_LENGTH(value) * PyUnicode_KIND(value); DEEP_HASH_BLOB(&result, s, size); #else PyObject *str = PyUnicode_AsUTF8String(value); if (str) { result ^= DEEP_HASH(str); } Py_DECREF(str); #endif RESTORE_ERROR_OCCURRED_UNTRACED(exception_type, exception_value, exception_tb); return result; } #if PYTHON_VERSION < 0x300 else if (PyString_Check(value)) { Py_hash_t result = DEEP_HASH((PyObject *)Py_TYPE(value)); Py_ssize_t size; char *s; int res = PyString_AsStringAndSize(value, &s, &size); assert(res != -1); DEEP_HASH_BLOB(&result, s, size); return result; } #else else if (PyBytes_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t size; char *s; int res = PyBytes_AsStringAndSize(value, &s, &size); assert(res != -1); DEEP_HASH_BLOB(&result, s, size); return result; } #endif else if (PyByteArray_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t size = PyByteArray_Size(value); assert(size >= 0); char *s = PyByteArray_AsString(value); DEEP_HASH_BLOB(&result, s, size); return result; } else if (value == Py_None || value == Py_Ellipsis || value == Py_NotImplemented) { return DEEP_HASH_INIT(value); } else if (PyComplex_Check(value)) { Py_complex c = PyComplex_AsCComplex(value); Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t size = sizeof(c); char *s = (char *)&c; DEEP_HASH_BLOB(&result, s, size); return result; } else if (PyFloat_Check(value)) { double f = PyFloat_AsDouble(value); Py_hash_t result = DEEP_HASH_INIT(value); Py_ssize_t size = sizeof(f); char *s = (char *)&f; DEEP_HASH_BLOB(&result, s, size); return result; } else if ( #if PYTHON_VERSION < 0x300 PyInt_Check(value) || #endif PyBool_Check(value) || PyRange_Check(value) || PySlice_Check(value) || PyCFunction_Check(value)) { Py_hash_t result = DEEP_HASH_INIT(value); #if 0 printf("Too simple deep hash: %s\n", Py_TYPE(value)->tp_name); #endif return result; #if PYTHON_VERSION >= 0x390 } else if (Py_TYPE(value) == &Py_GenericAliasType) { GenericAliasObject *generic_alias = (GenericAliasObject *)value; Py_hash_t result = DEEP_HASH_INIT(value); result ^= DEEP_HASH(generic_alias->args); result ^= DEEP_HASH(generic_alias->origin); return result; #endif } else { assert(false); return -1; } } #endif // Note: Not recursion safe, cannot do this everywhere. void CHECK_OBJECT_DEEP(PyObject *value) { CHECK_OBJECT(value); if (PyTuple_Check(value)) { for (Py_ssize_t i = 0, size = PyTuple_GET_SIZE(value); i < size; i++) { PyObject *element = PyTuple_GET_ITEM(value, i); CHECK_OBJECT_DEEP(element); } } else if (PyList_Check(value)) { for (Py_ssize_t i = 0, size = PyList_GET_SIZE(value); i < size; i++) { PyObject *element = PyList_GET_ITEM(value, i); CHECK_OBJECT_DEEP(element); } } else if (PyDict_Check(value)) { Py_ssize_t ppos = 0; PyObject *dict_key, *dict_value; while (PyDict_Next(value, &ppos, &dict_key, &dict_value)) { CHECK_OBJECT_DEEP(dict_key); CHECK_OBJECT_DEEP(dict_value); } } } void CHECK_OBJECTS_DEEP(PyObject *const *values, Py_ssize_t size) { for (Py_ssize_t i = 0; i < size; i++) { CHECK_OBJECT_DEEP(values[i]); } } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceFloordiv.c0000600000372100037210000023230314166627112033452 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "//" (FLOORDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_floor_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_floor_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_floor_divide(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_floor_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and 'float'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(*operand1); double b = PyFloat_AS_DOUBLE(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } { double mod = fmod(a, b); double div = (a - mod) / b; if (mod) { if ((a < 0) != (mod < 0)) { div -= 1.0; } } double floordiv; if (div) { floordiv = floor(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } else { floordiv = copysign(0.0, a / b); } cfloat_result = floordiv; goto exit_result_ok_cfloat; } exit_result_ok_cfloat: if (Py_REFCNT(*operand1) == 1) { PyFloat_AS_DOUBLE(*operand1) = cfloat_result; } else { // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = PyFloat_FromDouble(cfloat_result); } goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_LONG_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_FLOORDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_INT_FLOAT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_FLOAT_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static inline bool _BINARY_OPERATION_FLOORDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'int' and 'float'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_LONG_FLOAT_INPLACE(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_FLOORDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyFloat_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_floor_divide available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_floor_divide == NULL); { binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_floor_divide; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_floor_divide; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: 'float' and 'int'"); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_FLOAT_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ZeroDivisionError, "integer division or modulo by zero"); goto exit_result_exception; } /* TODO: Isn't this a very specific value only, of which we could * hardcode the constant result. Not sure how well the C compiler * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by * -1 has to be rare anyway. */ if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) { long a_div_b = a / b; long a_mod_b = (long)(a - (unsigned long)a_div_b * b); if (a_mod_b && (b ^ a_mod_b) < 0) { a_mod_b += b; a_div_b -= 1; } clong_result = a_div_b; goto exit_result_ok_clong; } { PyObject *operand1_object = *operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_floor_divide(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { if (PyFloat_CheckExact(operand2)) { return _BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_floor_divide : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_floor_divide : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_floor_divide : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_floor_divide; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for //: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/OnefileBootstrap.c0000600000372100037210000006261714166627112030456 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* The main program for onefile bootstrap. * * It needs to unpack the attached files and and then loads and executes * the compiled program. * */ #define _CRT_SECURE_NO_WARNINGS #if !defined(_WIN32) #define _POSIX_C_SOURCE 200809L #endif #ifdef __NUITKA_NO_ASSERT__ #define NDEBUG #endif #include #include #include #include #include #include #include /* Type bool */ #ifndef __cplusplus #include "stdbool.h" #endif #if defined(_WIN32) #include #include #include #ifndef CSIDL_LOCAL_APPDATA #define CSIDL_LOCAL_APPDATA 28 #endif #else #include #include #include #include #include #include #endif #ifndef __IDE_ONLY__ // Generated during build with optional defines. #include "onefile_definitions.h" #else #define ONEFILE_COMPANY "SomeVendor" #define ONEFILE_PRODUCT "SomeProduct" #define ONEFILE_VERSION "SomeVersion" #define _NUITKA_ONEFILE_TEMP_SPEC "%TEMP%/onefile_%PID%_%TIME%" #endif #ifdef _NUITKA_ONEFILE_COMPRESSION // Header goes first. #include "zstd.h" // Should be in our inline copy, we include all C files into this one. #include "common/error_private.c" #include "common/fse_decompress.c" #include "common/xxhash.c" #include "common/zstd_common.c" // Need to make sure this is last in common as it depends on the others. #include "common/entropy_common.c" // Decompression stuff. #include "decompress/huf_decompress.c" #include "decompress/zstd_ddict.c" #include "decompress/zstd_decompress.c" #include "decompress/zstd_decompress_block.c" #endif // Some handy macro definitions, e.g. unlikely. #include "nuitka/hedley.h" #define likely(x) HEDLEY_LIKELY(x) #define unlikely(x) HEDLEY_UNLIKELY(x) // Safe string operations. #include "HelpersSafeStrings.c" // For tracing outputs if enabled at compile time. #include "nuitka/tracing.h" static void printError(char const *message) { #if defined(_WIN32) LPCTSTR err_buffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&err_buffer, 0, NULL); puts(message); puts(err_buffer); #else perror(message); #endif } static void fatalError(char const *message) { printError(message); abort(); } static void fatalErrorTempFiles() { fatalError("Error, couldn't runtime expand temporary files."); } static void fatalErrorAttachedData() { fatalError("Error, couldn't decode attached data."); } static void fatalErrorMemory() { fatalError("Error, couldn't allocate memory."); } static void fatalErrorChild() { fatalError("Error, couldn't launch child."); } #if defined(_WIN32) static void appendWCharSafeW(wchar_t *target, wchar_t c, size_t buffer_size) { while (*target != 0) { target++; buffer_size -= 1; } if (buffer_size < 1) { abort(); } *target++ = c; *target = 0; } #endif // Have a type for filename type different on Linux and Win32. #if defined(_WIN32) #define filename_char_t wchar_t #define FILENAME_SEP_STR L"\\" #define FILENAME_SEP_CHAR L'\\' #define appendStringSafeFilename appendWStringSafeW #define appendCharSafeFilename appendWCharSafeW #else #define filename_char_t char #define FILENAME_SEP_STR "/" #define FILENAME_SEP_CHAR '/' #define appendStringSafeFilename appendStringSafe #define appendCharSafeFilename appendCharSafe #endif // Have a type for file type different on Linux and Win32. #if defined(_WIN32) #define FILE_HANDLE HANDLE #else #define FILE_HANDLE FILE * #endif static FILE_HANDLE createFileForWriting(filename_char_t const *filename) { #if defined(_WIN32) FILE_HANDLE result = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); if (result == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error, failed to open '%ls' for writing.", filename); exit(2); } #else FILE *result = fopen(filename, "wb"); if (result == NULL) { fprintf(stderr, "Error, failed to open '%s' for writing.", filename); exit(2); } #endif return result; } static void writeToFile(FILE_HANDLE target_file, void *chunk, size_t chunk_size) { #if defined(_WIN32) BOOL bool_res = WriteFile(target_file, chunk, (DWORD)chunk_size, NULL, NULL); if (bool_res == false) { fatalErrorTempFiles(); } #else long written = fwrite(chunk, 1, chunk_size, target_file); if (written != chunk_size) { fatalErrorTempFiles(); } #endif } static void closeFile(FILE_HANDLE target_file) { #if defined(_WIN32) CloseHandle(target_file); #else int r = fclose(target_file); if (r != 0) { fatalErrorTempFiles(); } #endif } static int getMyPid() { #if defined(_WIN32) return GetCurrentProcessId(); #else return getpid(); #endif } static void setEnvironVar(char const *var_name, char const *value) { #if defined(_WIN32) SetEnvironmentVariable("NUITKA_ONEFILE_PARENT", value); #else setenv(var_name, value, 1); #endif } // Note: Made payload file handle global until we properly abstracted compression. static FILE_HANDLE exe_file; #ifdef _NUITKA_ONEFILE_COMPRESSION static ZSTD_DCtx *dctx = NULL; static ZSTD_inBuffer input = {NULL, 0, 0}; static ZSTD_outBuffer output = {NULL, 0, 0}; static void initZSTD() { size_t const buffInSize = ZSTD_DStreamInSize(); input.src = malloc(buffInSize); if (input.src == NULL) { fatalErrorMemory(); } size_t const buffOutSize = ZSTD_DStreamOutSize(); output.dst = malloc(buffOutSize); if (output.dst == NULL) { fatalErrorMemory(); } dctx = ZSTD_createDCtx(); if (dctx == NULL) { fatalErrorMemory(); } } #endif static size_t stream_end_pos; static size_t getPosition() { #if defined(_WIN32) return SetFilePointer(exe_file, 0, NULL, FILE_CURRENT); #else return ftell(exe_file); #endif } static void readChunk(void *buffer, size_t size) { // printf("Reading %d\n", size); #if defined(_WIN32) DWORD read_size; BOOL bool_res = ReadFile(exe_file, buffer, (DWORD)size, &read_size, NULL); if (bool_res == false || read_size != size) { fatalErrorAttachedData(); } #else size_t read_size = fread(buffer, 1, size, exe_file); if (read_size != size) { fatalErrorAttachedData(); } #endif } static unsigned long long readSizeValue() { unsigned long long result; readChunk(&result, sizeof(unsigned long long)); return result; } static void readPayloadChunk(void *buffer, size_t size) { #ifdef _NUITKA_ONEFILE_COMPRESSION // bool no_payload = false; bool end_of_buffer = false; // Loop until finished with asked chunk. while (size > 0) { size_t available = output.size - output.pos; // printf("already available %d asking for %d\n", available, size); // Consider available data. if (available != 0) { size_t use = available; if (size < use) { use = size; } memcpy(buffer, ((char *)output.dst) + output.pos, use); buffer = (void *)(((char *)buffer) + use); size -= use; output.pos += use; // Loop end check may exist when "size" is "use". continue; } // Nothing available, make sure to make it available from existing input. if (input.pos < input.size || end_of_buffer) { output.pos = 0; output.size = ZSTD_DStreamOutSize(); size_t const ret = ZSTD_decompressStream(dctx, &output, &input); // printf("return output %d %d\n", output.pos, output.size); end_of_buffer = (output.pos == output.size); if (ZSTD_isError(ret)) { fatalErrorAttachedData(); } output.size = output.pos; output.pos = 0; // printf("made output %d %d\n", output.pos, output.size); // Above code gets a turn. continue; } if (input.size != input.pos) { fatalErrorAttachedData(); } // No input available, make it available from stream respecting end. size_t to_read = ZSTD_DStreamInSize(); size_t payload_available = stream_end_pos - getPosition(); static size_t payload_so_far = 0; if (payload_available == 0) { continue; } if (to_read > payload_available) { to_read = payload_available; } readChunk((void *)input.src, to_read); input.pos = 0; input.size = to_read; payload_so_far += to_read; } #else readChunk(buffer, size); #endif } static unsigned long long readPayloadSizeValue() { unsigned long long result; readPayloadChunk(&result, sizeof(unsigned long long)); return result; } static filename_char_t readPayloadChar() { filename_char_t result; readPayloadChunk(&result, sizeof(filename_char_t)); return result; } static filename_char_t *readPayloadFilename() { static filename_char_t buffer[1024]; filename_char_t *w = buffer; for (;;) { *w = readPayloadChar(); if (*w == 0) { break; } w += 1; } return buffer; } // Zero means, not yet created, created unsuccessfully, terminated already. #if defined(_WIN32) HANDLE handle_process = 0; #else pid_t handle_process = 0; #endif static filename_char_t payload_path[4096] = {0}; static bool payload_created = false; bool createDirectory(filename_char_t *path) { #if defined(_WIN32) BOOL bool_res = CreateDirectoryW(path, NULL); return bool_res; #else return mkdir(path, 0700) == 0; #endif } #if defined(_WIN32) void removeDirectory(wchar_t const *path) { // _putws(payload_path); SHFILEOPSTRUCTW fileop_struct = { NULL, FO_DELETE, payload_path, L"", FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT, false, 0, L""}; SHFileOperationW(&fileop_struct); } #else int removeDirectory(char const *path) { DIR *d = opendir(path); size_t path_len = strlen(path); int r = -1; if (d != NULL) { struct dirent *p; r = 0; while (!r && (p = readdir(d))) { int r2 = -1; size_t len; // Ignore special names if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { continue; } len = path_len + strlen(p->d_name) + 2; char *buf = malloc(len); if (buf == NULL) { fatalErrorMemory(); } struct stat statbuf; snprintf(buf, len, "%s/%s", path, p->d_name); if (!stat(buf, &statbuf)) { if (S_ISDIR(statbuf.st_mode)) r2 = removeDirectory(buf); else r2 = unlink(buf); } free(buf); r = r2; } closedir(d); } if (!r) { rmdir(path); } return r; } #endif static void cleanupChildProcess() { // Cause KeyboardInterrupt in the child process. if (handle_process != 0) { NUITKA_PRINT_TRACE("Sending CTRL-C to child\n"); #if defined(_WIN32) BOOL res = GenerateConsoleCtrlEvent(CTRL_C_EVENT, GetProcessId(handle_process)); if (res == false) { printError("Failed to send CTRL-C to child process."); // No error exit is done, we still want to cleanup when it does exit } #else kill(handle_process, SIGINT); #endif // We only need to wait if there is a need to cleanup files. #if _NUITKA_ONEFILE_TEMP == 1 #if defined(_WIN32) WaitForSingleObject(handle_process, INFINITE); CloseHandle(handle_process); #else waitpid(handle_process, NULL, 0); #endif #endif } #if _NUITKA_ONEFILE_TEMP == 1 if (payload_created) { removeDirectory(payload_path); } #endif } #if defined(_WIN32) static char *convertUnicodePathToAnsi(wchar_t const *path) { // first get short path as otherwise, conversion might not be reliable DWORD l = GetShortPathNameW(path, NULL, 0); wchar_t *shortPath = (wchar_t *)malloc(sizeof(wchar_t) * (l + 1)); if (shortPath == NULL) { fatalErrorMemory(); } l = GetShortPathNameW(path, shortPath, l); if (unlikely(l == 0)) { goto err_shortPath; } size_t i; if (unlikely(wcstombs_s(&i, NULL, 0, shortPath, _TRUNCATE) != 0)) { goto err_shortPath; } char *ansiPath = (char *)malloc(i); if (ansiPath == NULL) { fatalErrorMemory(); } if (unlikely(wcstombs_s(&i, ansiPath, i, shortPath, _TRUNCATE) != 0)) { goto err_ansiPath; } return ansiPath; err_ansiPath: free(ansiPath); err_shortPath: free(shortPath); return NULL; } #endif #if defined(_WIN32) BOOL WINAPI ourConsoleCtrlHandler(DWORD fdwCtrlType) { switch (fdwCtrlType) { // Handle the CTRL-C signal. case CTRL_C_EVENT: NUITKA_PRINT_TRACE("Ctrl-C event"); cleanupChildProcess(); return FALSE; // CTRL-CLOSE: confirm that the user wants to exit. case CTRL_CLOSE_EVENT: NUITKA_PRINT_TRACE("Ctrl-Close event"); cleanupChildProcess(); return FALSE; // Pass other signals to the next handler. case CTRL_BREAK_EVENT: NUITKA_PRINT_TRACE("Ctrl-Break event"); cleanupChildProcess(); return FALSE; case CTRL_LOGOFF_EVENT: NUITKA_PRINT_TRACE("Ctrl-Logoff event"); cleanupChildProcess(); return FALSE; case CTRL_SHUTDOWN_EVENT: NUITKA_PRINT_TRACE("Ctrl-Shutdown event"); cleanupChildProcess(); return FALSE; default: return FALSE; } } #else void ourConsoleCtrlHandler(int sig) { cleanupChildProcess(); } #endif #ifndef MAXPATHLEN #define MAXPATHLEN 2048 #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif #if !defined(_WIN32) char const *getBinaryPath() { static char binary_filename[MAXPATHLEN]; #if defined(__APPLE__) uint32_t bufsize = sizeof(binary_filename); int res = _NSGetExecutablePath(binary_filename, &bufsize); if (res != 0) { abort(); } #elif defined(__FreeBSD__) || defined(__OpenBSD__) /* Not all of FreeBSD has /proc file system, so use the appropriate * "sysctl" instead. */ int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; size_t cb = sizeof(binary_filename); int res = sysctl(mib, 4, binary_filename, &cb, NULL, 0); if (res != 0) { abort(); } #else /* The remaining platforms, mostly Linux or compatible. */ /* The "readlink" call does not terminate result, so fill zeros there, then * it is a proper C string right away. */ memset(binary_filename, 0, sizeof(binary_filename)); ssize_t res = readlink("/proc/self/exe", binary_filename, sizeof(binary_filename) - 1); if (res == -1) { abort(); } #endif return binary_filename; } #endif #if _NUITKA_ONEFILE_SPLASH_SCREEN #include "OnefileSplashScreen.cpp" #endif #ifdef _NUITKA_WINMAIN_ENTRY_POINT int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpCmdLine, int nCmdShow) { int argc = __argc; wchar_t **argv = __wargv; #else #if defined(_WIN32) int wmain(int argc, wchar_t **argv) { #else int main(int argc, char **argv) { #endif #endif NUITKA_PRINT_TIMING("ONEFILE: Entered main()."); #if defined(_WIN32) static wchar_t exe_filename[4096] = {0}; DWORD res = GetModuleFileNameW(NULL, exe_filename, sizeof(exe_filename) / sizeof(wchar_t)); if (res == 0) { printError("Error, failed to locate onefile filename."); return 1; } wchar_t const *pattern = L"" _NUITKA_ONEFILE_TEMP_SPEC; BOOL bool_res = expandTemplatePathW(payload_path, pattern, sizeof(payload_path) / sizeof(wchar_t)); if (bool_res == false) { puts("Error, couldn't runtime expand temporary directory pattern:"); _putws(pattern); abort(); } #else char const *pattern = "" _NUITKA_ONEFILE_TEMP_SPEC; bool bool_res = expandTemplatePath(payload_path, pattern, sizeof(payload_path)); if (bool_res == false) { puts("Error, couldn't runtime expand temporary directory pattern:"); puts(pattern); abort(); } #endif #if defined(_WIN32) bool_res = SetConsoleCtrlHandler(ourConsoleCtrlHandler, true); if (bool_res == false) { printError("Error, failed to register signal handler."); return 1; } #else signal(SIGINT, ourConsoleCtrlHandler); #endif NUITKA_PRINT_TIMING("ONEFILE: Unpacking payload."); createDirectory(payload_path); payload_created = true; #if defined(_WIN32) exe_file = CreateFileW(exe_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (exe_file == INVALID_HANDLE_VALUE) { printError("Error, failed to access unpacked executable."); return 1; } #else exe_file = fopen(getBinaryPath(), "rb"); #endif #if defined(_WIN32) /* if an application is signed, the signature is at the end of the file where we normally expect the start position of out container. the overcome this limitation, use the windows function MapAndLoad() to parse the PE header. The header contains information whether a signature is present and at which address the first signature start. so we can use that address to find the start position value */ DWORD cert_table_addr = 0; PSTR exe_filename_a = convertUnicodePathToAnsi(exe_filename); if (exe_filename_a) { LOADED_IMAGE loaded_image; if (MapAndLoad(exe_filename_a, "\\dont-search-path", &loaded_image, false, true)) { if (loaded_image.FileHeader) { if (loaded_image.FileHeader->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY) { cert_table_addr = loaded_image.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] .VirtualAddress; // printf("Certificate Table at: %d\n", cert_table_addr); } } UnMapAndLoad(&loaded_image); } free(exe_filename_a); } if (cert_table_addr == 0) { res = SetFilePointer(exe_file, -8, NULL, FILE_END); } else { res = SetFilePointer(exe_file, cert_table_addr - 8, NULL, FILE_BEGIN); } if (res == INVALID_SET_FILE_POINTER) { fatalErrorAttachedData(); } #else int res = fseek(exe_file, -8, SEEK_END); if (res != 0) { fatalErrorAttachedData(); } #endif stream_end_pos = getPosition(); unsigned long long start_pos = readSizeValue(); // printf("Start at %lld\n", start_pos); // printf("Start at %ld\n", (LONG)start_pos); // The start offset won't exceed LONG. #if defined(_WIN32) res = SetFilePointer(exe_file, (LONG)start_pos, NULL, FILE_BEGIN); if (res == INVALID_SET_FILE_POINTER) { fatalErrorAttachedData(); } #else res = fseek(exe_file, start_pos, SEEK_SET); if (res != 0) { fatalErrorAttachedData(); } #endif char header[3]; readChunk(&header, sizeof(header)); if (header[0] != 'K' || header[1] != 'A') { fatalErrorAttachedData(); } // The 'X' stands for no compression, 'Y' is compressed, handle that. #ifdef _NUITKA_ONEFILE_COMPRESSION if (header[2] != 'Y') { fatalErrorAttachedData(); } initZSTD(); #else if (header[2] != 'X') { fatalErrorAttachedData(); } #endif static filename_char_t first_filename[1024] = {0}; #if _NUITKA_ONEFILE_SPLASH_SCREEN initSplashScreen(); #endif // printf("Entering decompression loop:"); for (;;) { filename_char_t *filename = readPayloadFilename(); // printf("Filename: %s\n", filename); // Detect EOF from empty filename. if (filename[0] == 0) { break; } // puts("at:"); // _putws(filename); static filename_char_t target_path[4096] = {0}; target_path[0] = 0; filename_char_t *w = filename; while (*w) { if (*w == FILENAME_SEP_CHAR) { *w = 0; target_path[0] = 0; appendStringSafeFilename(target_path, payload_path, sizeof(target_path) / sizeof(filename_char_t)); appendCharSafeFilename(target_path, FILENAME_SEP_CHAR, sizeof(target_path) / sizeof(filename_char_t)); appendStringSafeFilename(target_path, filename, sizeof(target_path) / sizeof(filename_char_t)); *w = FILENAME_SEP_CHAR; // _putws(target_path); createDirectory(target_path); } w++; } target_path[0] = 0; appendStringSafeFilename(target_path, payload_path, sizeof(target_path) / sizeof(filename_char_t)); appendCharSafeFilename(target_path, FILENAME_SEP_CHAR, sizeof(target_path) / sizeof(filename_char_t)); appendStringSafeFilename(target_path, filename, sizeof(target_path) / sizeof(filename_char_t)); if (first_filename[0] == 0) { appendStringSafeFilename(first_filename, target_path, sizeof(target_path) / sizeof(filename_char_t)); } // _putws(target_path); FILE_HANDLE target_file = createFileForWriting(target_path); unsigned long long file_size = readPayloadSizeValue(); while (file_size > 0) { static char chunk[32768]; long chunk_size; // Doing min manually, as otherwise the compiler is confused from types. if (file_size <= sizeof(chunk)) { chunk_size = (long)file_size; } else { chunk_size = sizeof(chunk); } readPayloadChunk(chunk, chunk_size); writeToFile(target_file, chunk, chunk_size); file_size -= chunk_size; } if (file_size != 0) { fatalErrorAttachedData(); } closeFile(target_file); } // Pass our pid by value to the child. If we exit for some reason, re-parenting // might change it by the time the child looks at its parent. { char buffer[128]; snprintf(buffer, sizeof(buffer), "%d", getMyPid()); setEnvironVar("NUITKA_ONEFILE_PARENT", buffer); } NUITKA_PRINT_TIMING("ONEFILE: Preparing forking of slave process."); #if defined(_WIN32) STARTUPINFOW si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; bool_res = CreateProcessW(first_filename, // application name GetCommandLineW(), // command line NULL, // process attributes NULL, // thread attributes FALSE, // inherit handles CREATE_NEW_PROCESS_GROUP, // creation flags NULL, NULL, &si, &pi); NUITKA_PRINT_TIMING("ONEFILE: Started slave process."); if (bool_res == false) { fatalErrorChild(); } CloseHandle(pi.hThread); handle_process = pi.hProcess; DWORD exit_code = 0; #if _NUITKA_ONEFILE_SPLASH_SCREEN DWORD wait_time = 50; #else DWORD wait_time = INFINITE; #endif // Loop with splash screen, otherwise this will be only once. while (handle_process != 0) { WaitForSingleObject(handle_process, wait_time); if (!GetExitCodeProcess(handle_process, &exit_code)) { exit_code = 1; } #if _NUITKA_ONEFILE_SPLASH_SCREEN if (exit_code == STILL_ACTIVE) { bool done = checkSplashScreen(); // Stop checking splash screen, can increase timeout. if (done) { wait_time = INFINITE; } continue; } #endif CloseHandle(handle_process); handle_process = 0; } cleanupChildProcess(); #else int exit_code; chmod(first_filename, 0700); pid_t pid = fork(); if (pid < 0) { printError("fork"); exit_code = 2; } else if (pid == 0) { execv(first_filename, argv); printError("exec failed"); exit_code = 2; } else { handle_process = pid; int status; int res = waitpid(handle_process, &status, 0); if (res == -1 && errno != ECHILD) { printError("waitpid"); cleanupChildProcess(); exit_code = 2; } else { exit_code = WEXITSTATUS(status); cleanupChildProcess(); } } #endif NUITKA_PRINT_TIMING("ONEFILE: Exiting."); return exit_code; } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledFrameType.c0000600000372100037210000006430714166627112030546 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "nuitka/prelude.h" #include "nuitka/freelists.h" #include "structmember.h" // For reporting about reference counts per type. #if _DEBUG_REFCOUNTS int count_active_Nuitka_Frame_Type = 0; int count_allocated_Nuitka_Frame_Type = 0; int count_released_Nuitka_Frame_Type = 0; #endif // For reporting about frame cache usage #if _DEBUG_REFCOUNTS int count_active_frame_cache_instances = 0; int count_allocated_frame_cache_instances = 0; int count_released_frame_cache_instances = 0; int count_hit_frame_cache_instances = 0; #endif #define OFF(x) offsetof(PyFrameObject, x) static PyMemberDef Nuitka_Frame_memberlist[] = { {(char *)"f_back", T_OBJECT, OFF(f_back), READONLY | RESTRICTED}, {(char *)"f_code", T_OBJECT, OFF(f_code), READONLY | RESTRICTED}, {(char *)"f_builtins", T_OBJECT, OFF(f_builtins), READONLY | RESTRICTED}, {(char *)"f_globals", T_OBJECT, OFF(f_globals), READONLY | RESTRICTED}, {(char *)"f_lasti", T_INT, OFF(f_lasti), READONLY | RESTRICTED}, {NULL}}; #if PYTHON_VERSION < 0x300 static PyObject *Nuitka_Frame_get_exc_traceback(struct Nuitka_FrameObject *frame) { PyObject *result = frame->m_frame.f_exc_traceback; if (result == NULL) { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Frame_set_exc_traceback(struct Nuitka_FrameObject *frame, PyObject *traceback) { Py_XDECREF(frame->m_frame.f_exc_traceback); if (traceback == Py_None) { traceback = NULL; } frame->m_frame.f_exc_traceback = traceback; Py_XINCREF(traceback); return 0; } static PyObject *Nuitka_Frame_get_exc_type(struct Nuitka_FrameObject *frame) { PyObject *result; if (frame->m_frame.f_exc_type != NULL) { result = frame->m_frame.f_exc_type; } else { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Frame_set_exc_type(struct Nuitka_FrameObject *frame, PyObject *exception_type) { PyObject *old = frame->m_frame.f_exc_type; if (exception_type == Py_None) { exception_type = NULL; } frame->m_frame.f_exc_type = exception_type; Py_XINCREF(frame->m_frame.f_exc_type); Py_XDECREF(old); return 0; } static PyObject *Nuitka_Frame_get_exc_value(struct Nuitka_FrameObject *frame) { PyObject *result; if (frame->m_frame.f_exc_value != NULL) { result = frame->m_frame.f_exc_value; } else { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Frame_set_exc_value(struct Nuitka_FrameObject *frame, PyObject *exception_value) { PyObject *old = frame->m_frame.f_exc_value; if (exception_value == Py_None) { exception_value = NULL; } frame->m_frame.f_exc_value = exception_value; Py_XINCREF(exception_value); Py_XDECREF(old); return 0; } static PyObject *Nuitka_Frame_get_restricted(struct Nuitka_FrameObject *frame, void *closure) { Py_INCREF(Py_False); return Py_False; } #endif static PyObject *Nuitka_Frame_getlocals(struct Nuitka_FrameObject *frame, void *closure) { if (frame->m_type_description == NULL) { if (frame->m_frame.f_locals == NULL) { frame->m_frame.f_locals = PyDict_New(); } Py_INCREF(frame->m_frame.f_locals); return frame->m_frame.f_locals; } else { PyObject *result = PyDict_New(); PyObject **varnames = &PyTuple_GET_ITEM(frame->m_frame.f_code->co_varnames, 0); char const *w = frame->m_type_description; char const *t = frame->m_locals_storage; while (*w != 0) { switch (*w) { case NUITKA_TYPE_DESCRIPTION_OBJECT: case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: { PyObject *value = *(PyObject **)t; CHECK_OBJECT_X(value); if (value != NULL) { PyDict_SetItem(result, *varnames, value); } t += sizeof(PyObject *); break; } case NUITKA_TYPE_DESCRIPTION_CELL: { struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t; assert(Nuitka_Cell_Check((PyObject *)value)); CHECK_OBJECT(value); if (value->ob_ref != NULL) { PyDict_SetItem(result, *varnames, value->ob_ref); } t += sizeof(struct Nuitka_CellObject *); break; } case NUITKA_TYPE_DESCRIPTION_NULL: { break; } case NUITKA_TYPE_DESCRIPTION_BOOL: { int value = *(int *)t; t += sizeof(int); switch ((nuitka_bool)value) { case NUITKA_BOOL_TRUE: { PyDict_SetItem(result, *varnames, Py_True); break; } case NUITKA_BOOL_FALSE: { PyDict_SetItem(result, *varnames, Py_False); break; } default: break; } break; } default: assert(false); } w += 1; varnames += 1; } return result; } } static PyObject *Nuitka_Frame_getlineno(PyFrameObject *frame, void *closure) { return PyInt_FromLong(frame->f_lineno); } static PyObject *Nuitka_Frame_gettrace(PyFrameObject *frame, void *closure) { PyObject *result = frame->f_trace; Py_INCREF(result); return result; } static int Nuitka_Frame_settrace(PyFrameObject *frame, PyObject *v, void *closure) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "f_trace is not writable in Nuitka"); return -1; } #if PYTHON_VERSION >= 0x370 static PyObject *Nuitka_Frame_gettracelines(PyFrameObject *frame, void *closure) { PyObject *result = Py_False; Py_INCREF(result); return result; } static int Nuitka_Frame_settracelines(PyFrameObject *frame, PyObject *v, void *closure) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "f_trace_lines is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Frame_gettraceopcodes(PyFrameObject *frame, void *closure) { PyObject *result = Py_False; Py_INCREF(result); return result; } static int Nuitka_Frame_settraceopcodes(PyFrameObject *frame, PyObject *v, void *closure) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "f_trace_opcodes is not writable in Nuitka"); return -1; } #endif static PyGetSetDef Nuitka_Frame_getsetlist[] = { {(char *)"f_locals", (getter)Nuitka_Frame_getlocals, NULL, NULL}, {(char *)"f_lineno", (getter)Nuitka_Frame_getlineno, NULL, NULL}, {(char *)"f_trace", (getter)Nuitka_Frame_gettrace, (setter)Nuitka_Frame_settrace, NULL}, #if PYTHON_VERSION < 0x300 {(char *)"f_restricted", (getter)Nuitka_Frame_get_restricted, NULL, NULL}, {(char *)"f_exc_traceback", (getter)Nuitka_Frame_get_exc_traceback, (setter)Nuitka_Frame_set_exc_traceback, NULL}, {(char *)"f_exc_type", (getter)Nuitka_Frame_get_exc_type, (setter)Nuitka_Frame_set_exc_type, NULL}, {(char *)"f_exc_value", (getter)Nuitka_Frame_get_exc_value, (setter)Nuitka_Frame_set_exc_value, NULL}, #endif #if PYTHON_VERSION >= 0x370 {(char *)"f_trace_lines", (getter)Nuitka_Frame_gettracelines, (setter)Nuitka_Frame_settracelines, NULL}, {(char *)"f_trace_opcodes", (getter)Nuitka_Frame_gettraceopcodes, (setter)Nuitka_Frame_settraceopcodes, NULL}, #endif {NULL}}; // tp_repr slot, decide how a function shall be output static PyObject *Nuitka_Frame_tp_repr(struct Nuitka_FrameObject *nuitka_frame) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif #if PYTHON_VERSION >= 0x370 "", nuitka_frame, nuitka_frame->m_frame.f_code->co_filename, nuitka_frame->m_frame.f_lineno, nuitka_frame->m_frame.f_code->co_name #elif _DEBUG_FRAME || _DEBUG_REFRAME || _DEBUG_EXCEPTIONS "", Nuitka_String_AsString(nuitka_frame->m_frame.f_code->co_name), nuitka_frame #else "", nuitka_frame #endif ); } static void Nuitka_Frame_tp_clear(struct Nuitka_FrameObject *frame) { if (frame->m_type_description) { char const *w = frame->m_type_description; char const *t = frame->m_locals_storage; while (*w != 0) { switch (*w) { case NUITKA_TYPE_DESCRIPTION_OBJECT: case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: { PyObject *value = *(PyObject **)t; CHECK_OBJECT_X(value); Py_XDECREF(value); t += sizeof(PyObject *); break; } case NUITKA_TYPE_DESCRIPTION_CELL: { struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t; assert(Nuitka_Cell_Check((PyObject *)value)); CHECK_OBJECT(value); Py_DECREF(value); t += sizeof(struct Nuitka_CellObject *); break; } case NUITKA_TYPE_DESCRIPTION_NULL: { break; } case NUITKA_TYPE_DESCRIPTION_BOOL: { t += sizeof(int); break; } default: assert(false); } w += 1; } frame->m_type_description = NULL; } } #define MAX_FRAME_FREE_LIST_COUNT 100 static struct Nuitka_FrameObject *free_list_frames = NULL; static int free_list_frames_count = 0; static void Nuitka_Frame_tp_dealloc(struct Nuitka_FrameObject *nuitka_frame) { #if _DEBUG_REFCOUNTS count_active_Nuitka_Frame_Type -= 1; count_released_Nuitka_Frame_Type += 1; #endif #ifndef __NUITKA_NO_ASSERT__ // Save the current exception, if any, we must to not corrupt it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); #endif Nuitka_GC_UnTrack(nuitka_frame); PyFrameObject *frame = &nuitka_frame->m_frame; Py_XDECREF(frame->f_back); Py_DECREF(frame->f_builtins); Py_DECREF(frame->f_globals); Py_XDECREF(frame->f_locals); #if PYTHON_VERSION < 0x370 Py_XDECREF(frame->f_exc_type); Py_XDECREF(frame->f_exc_value); Py_XDECREF(frame->f_exc_traceback); #endif Nuitka_Frame_tp_clear(nuitka_frame); releaseToFreeList(free_list_frames, nuitka_frame, MAX_FRAME_FREE_LIST_COUNT); #ifndef __NUITKA_NO_ASSERT__ PyThreadState *tstate = PyThreadState_GET(); assert(tstate->curexc_type == save_exception_type); assert(tstate->curexc_value == save_exception_value); assert((PyTracebackObject *)tstate->curexc_traceback == save_exception_tb); #endif } static int Nuitka_Frame_tp_traverse(struct Nuitka_FrameObject *frame, visitproc visit, void *arg) { Py_VISIT(frame->m_frame.f_back); // Py_VISIT(frame->f_code); Py_VISIT(frame->m_frame.f_builtins); Py_VISIT(frame->m_frame.f_globals); // Py_VISIT(frame->f_locals); #if PYTHON_VERSION < 0x370 Py_VISIT(frame->m_frame.f_exc_type); Py_VISIT(frame->m_frame.f_exc_value); Py_VISIT(frame->m_frame.f_exc_traceback); #endif // Traverse attached locals too. char const *w = frame->m_type_description; char const *t = frame->m_locals_storage; while (w != NULL && *w != 0) { switch (*w) { case NUITKA_TYPE_DESCRIPTION_OBJECT: case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: { PyObject *value = *(PyObject **)t; CHECK_OBJECT_X(value); Py_VISIT(value); t += sizeof(PyObject *); break; } case NUITKA_TYPE_DESCRIPTION_CELL: { struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t; assert(Nuitka_Cell_Check((PyObject *)value)); CHECK_OBJECT(value); Py_VISIT(value); t += sizeof(struct Nuitka_CellObject *); break; } case NUITKA_TYPE_DESCRIPTION_NULL: { break; } case NUITKA_TYPE_DESCRIPTION_BOOL: { t += sizeof(int); break; } default: assert(false); } w += 1; } return 0; } #if PYTHON_VERSION >= 0x340 static PyObject *Nuitka_Frame_clear(struct Nuitka_FrameObject *frame) { if (Nuitka_Frame_IsExecuting(frame)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "cannot clear an executing frame"); return NULL; } #if PYTHON_VERSION >= 0x340 // For frames that are closed, we also need to close the generator. if (frame->m_frame.f_gen != NULL) { Py_INCREF(frame); CHECK_OBJECT(frame->m_frame.f_gen); PyObject *f_gen = frame->m_frame.f_gen; bool close_exception; if (Nuitka_Generator_Check(frame->m_frame.f_gen)) { struct Nuitka_GeneratorObject *generator = (struct Nuitka_GeneratorObject *)frame->m_frame.f_gen; frame->m_frame.f_gen = NULL; close_exception = !_Nuitka_Generator_close(generator); } #if PYTHON_VERSION >= 0x350 else if (Nuitka_Coroutine_Check(frame->m_frame.f_gen)) { struct Nuitka_CoroutineObject *coroutine = (struct Nuitka_CoroutineObject *)frame->m_frame.f_gen; frame->m_frame.f_gen = NULL; close_exception = !_Nuitka_Coroutine_close(coroutine); } #endif #if PYTHON_VERSION >= 0x360 else if (Nuitka_Asyncgen_Check(frame->m_frame.f_gen)) { struct Nuitka_AsyncgenObject *asyncgen = (struct Nuitka_AsyncgenObject *)frame->m_frame.f_gen; frame->m_frame.f_gen = NULL; close_exception = !_Nuitka_Asyncgen_close(asyncgen); } #endif else { // Compiled frames should only have our types, so this ought to not happen. assert(false); frame->m_frame.f_gen = NULL; close_exception = false; } if (unlikely(close_exception)) { PyErr_WriteUnraisable(f_gen); } Py_DECREF(frame); } #endif Nuitka_Frame_tp_clear(frame); Py_RETURN_NONE; } #endif static PyObject *Nuitka_Frame_sizeof(struct Nuitka_FrameObject *frame) { return PyInt_FromSsize_t(sizeof(struct Nuitka_FrameObject) + Py_SIZE(frame)); } static PyMethodDef Nuitka_Frame_methods[] = { #if PYTHON_VERSION >= 0x340 {"clear", (PyCFunction)Nuitka_Frame_clear, METH_NOARGS, "F.clear(): clear most references held by the frame"}, #endif {"__sizeof__", (PyCFunction)Nuitka_Frame_sizeof, METH_NOARGS, "F.__sizeof__() -> size of F in memory, in bytes"}, {NULL, NULL}}; PyTypeObject Nuitka_Frame_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_frame", sizeof(struct Nuitka_FrameObject), 1, (destructor)Nuitka_Frame_tp_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare (reprfunc)Nuitka_Frame_tp_repr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str PyObject_GenericGetAttr, // tp_getattro PyObject_GenericSetAttr, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags 0, // tp_doc (traverseproc)Nuitka_Frame_tp_traverse, // tp_traverse (inquiry)Nuitka_Frame_tp_clear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext Nuitka_Frame_methods, // tp_methods Nuitka_Frame_memberlist, // tp_members Nuitka_Frame_getsetlist, // tp_getset #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyFrame_Type, // tp_base #else 0, // tp_base #endif 0, // tp_dict }; void _initCompiledFrameType(void) { PyType_Ready(&Nuitka_Frame_Type); // These are to be used interchangeably. Make sure that's true. assert(offsetof(struct Nuitka_FrameObject, m_frame.f_localsplus) == offsetof(PyFrameObject, f_localsplus)); } static struct Nuitka_FrameObject *MAKE_FRAME(PyCodeObject *code, PyObject *module, bool is_module, Py_ssize_t locals_size) { assertCodeObject(code); #if _DEBUG_REFCOUNTS count_active_Nuitka_Frame_Type += 1; count_allocated_Nuitka_Frame_Type += 1; #endif PyObject *globals = ((PyModuleObject *)module)->md_dict; assert(PyDict_Check(globals)); struct Nuitka_FrameObject *result; // Macro to assign result memory from GC or free list. allocateFromFreeList(free_list_frames, struct Nuitka_FrameObject, Nuitka_Frame_Type, locals_size); result->m_type_description = NULL; PyFrameObject *frame = &result->m_frame; frame->f_code = code; frame->f_trace = Py_None; #if PYTHON_VERSION < 0x370 frame->f_exc_type = NULL; frame->f_exc_value = NULL; frame->f_exc_traceback = NULL; #else frame->f_trace_lines = 0; frame->f_trace_opcodes = 0; #endif Py_INCREF(dict_builtin); frame->f_builtins = (PyObject *)dict_builtin; frame->f_back = NULL; Py_INCREF(globals); frame->f_globals = globals; if (likely((code->co_flags & CO_OPTIMIZED) == CO_OPTIMIZED)) { frame->f_locals = NULL; } else if (is_module) { Py_INCREF(globals); frame->f_locals = globals; } else { frame->f_locals = PyDict_New(); if (unlikely(frame->f_locals == NULL)) { Py_DECREF(result); return NULL; } PyDict_SetItem(frame->f_locals, const_str_plain___module__, MODULE_NAME0(module)); } #if PYTHON_VERSION < 0x340 frame->f_tstate = PyThreadState_GET(); #endif frame->f_lasti = -1; frame->f_lineno = code->co_firstlineno; frame->f_iblock = 0; #if PYTHON_VERSION >= 0x340 frame->f_gen = NULL; Nuitka_Frame_MarkAsNotExecuting(result); #endif Nuitka_GC_Track(result); return result; } struct Nuitka_FrameObject *MAKE_MODULE_FRAME(PyCodeObject *code, PyObject *module) { return MAKE_FRAME(code, module, true, 0); } struct Nuitka_FrameObject *MAKE_FUNCTION_FRAME(PyCodeObject *code, PyObject *module, Py_ssize_t locals_size) { return MAKE_FRAME(code, module, false, locals_size); } // This is the backend of MAKE_CODEOBJ macro. PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name, PyObject *argnames, PyObject *freevars, int arg_count #if PYTHON_VERSION >= 0x300 , int kw_only_count #endif #if PYTHON_VERSION >= 0x380 , int pos_only_count #endif ) { CHECK_OBJECT(filename); assert(Nuitka_String_CheckExact(filename)); CHECK_OBJECT(function_name); assert(Nuitka_String_CheckExact(function_name)); if (argnames == NULL) { argnames = const_tuple_empty; } CHECK_OBJECT(argnames); assert(PyTuple_Check(argnames)); if (freevars == NULL) { freevars = const_tuple_empty; } CHECK_OBJECT(freevars); assert(PyTuple_Check(freevars)); // The PyCode_New has funny code that interns, mutating the tuple that owns // it. Really serious non-immutable shit. We have triggered that changes // behind our back in the past. #ifndef __NUITKA_NO_ASSERT__ Py_hash_t hash = DEEP_HASH(argnames); #endif #if PYTHON_VERSION < 0x300 PyObject *code = const_str_empty; PyObject *lnotab = const_str_empty; #else PyObject *code = const_bytes_empty; PyObject *lnotab = const_bytes_empty; #endif // Not using PyCode_NewEmpty, it doesn't given us much beyond this // and is not available for Python2. #if PYTHON_VERSION >= 0x380 PyCodeObject *result = PyCode_NewWithPosOnlyArgs(arg_count, // argcount #else PyCodeObject *result = PyCode_New(arg_count, // argcount #endif #if PYTHON_VERSION >= 0x300 #if PYTHON_VERSION >= 0x380 pos_only_count, // kw-only count #endif kw_only_count, // kw-only count #endif 0, // nlocals 0, // stacksize flags, // flags code, // code (bytecode) const_tuple_empty, // consts (we are not going to be compatible) const_tuple_empty, // names (we are not going to be compatible) argnames, // varnames (we are not going to be compatible) freevars, // freevars const_tuple_empty, // cellvars (we are not going to be compatible) filename, // filename function_name, // name line, // firstlineno (offset of the code object) lnotab // lnotab (table to translate code object) ); assert(DEEP_HASH(argnames) == hash); CHECK_OBJECT(result); return result; } void Nuitka_Frame_AttachLocals(struct Nuitka_FrameObject *frame, char const *type_description, ...) { assertFrameObject(frame); assert(frame->m_type_description == NULL); // TODO: Do not call this if there is nothing to do. Instead make all the // places handle NULL pointer and recognize that there is nothing to do. // assert(type_description != NULL && assert(strlen(type_description)>0)); if (type_description == NULL) { type_description = ""; } frame->m_type_description = type_description; char const *w = type_description; char *t = frame->m_locals_storage; va_list(ap); va_start(ap, type_description); while (*w != 0) { switch (*w) { case NUITKA_TYPE_DESCRIPTION_OBJECT: { PyObject *value = va_arg(ap, PyObject *); memcpy(t, &value, sizeof(PyObject *)); Py_XINCREF(value); t += sizeof(PyObject *); break; } case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: { /* Note: We store the pointed object only, so this is only a shortcut for the calling side. */ PyObject **value = va_arg(ap, PyObject **); CHECK_OBJECT_X(*value); memcpy(t, value, sizeof(PyObject *)); Py_XINCREF(*value); t += sizeof(PyObject *); break; } case NUITKA_TYPE_DESCRIPTION_CELL: { struct Nuitka_CellObject *value = va_arg(ap, struct Nuitka_CellObject *); assert(Nuitka_Cell_Check((PyObject *)value)); CHECK_OBJECT(value); CHECK_OBJECT_X(value->ob_ref); memcpy(t, &value, sizeof(struct Nuitka_CellObject *)); Py_INCREF(value); t += sizeof(struct Nuitka_CellObject *); break; } case NUITKA_TYPE_DESCRIPTION_NULL: { NUITKA_MAY_BE_UNUSED void *value = va_arg(ap, struct Nuitka_CellObject *); break; } case NUITKA_TYPE_DESCRIPTION_BOOL: { int value = va_arg(ap, int); memcpy(t, &value, sizeof(int)); t += sizeof(value); break; } default: assert(false); } w += 1; } va_end(ap); assert(t - frame->m_locals_storage <= Py_SIZE(frame)); } // Make a dump of the active frame stack. For debugging purposes only. void dumpFrameStack(void) { PyObject *saved_exception_type, *saved_exception_value; PyTracebackObject *saved_exception_tb; FETCH_ERROR_OCCURRED(&saved_exception_type, &saved_exception_value, &saved_exception_tb); PyFrameObject *current = PyThreadState_GET()->frame; int total = 0; while (current) { total++; current = current->f_back; } current = PyThreadState_GET()->frame; PRINT_STRING(">--------->\n"); while (current) { PyObject *current_repr = PyObject_Str((PyObject *)current); PyObject *code_repr = PyObject_Str((PyObject *)current->f_code); PRINT_FORMAT("Frame stack %d: %s %d %s\n", total--, Nuitka_String_AsString(current_repr), Py_REFCNT(current), Nuitka_String_AsString(code_repr)); Py_DECREF(current_repr); Py_DECREF(code_repr); current = current->f_back; } PRINT_STRING(">---------<\n"); RESTORE_ERROR_OCCURRED(saved_exception_type, saved_exception_value, saved_exception_tb); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersPythonPgo.c0000600000372100037210000000732514166627112030444 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** * This is responsible for collection of Nuitka Python PGO information. It writes * traces to files, for reuse in a future Python compilation of the same program. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif static FILE *pgo_output; // Saving space by not repeating strings. // Allocated strings static char const **PGO_ProbeNameMappings = NULL; static int PGO_ProbeNameMappings_size = 0; static uint32_t PGO_ProbeNameMappings_used = 0; int PGO_getStringID(char const *str) { for (int i = 0; i < PGO_ProbeNameMappings_used; i++) { if (str == PGO_ProbeNameMappings[i]) { return i; } } if (PGO_ProbeNameMappings_used == PGO_ProbeNameMappings_size) { PGO_ProbeNameMappings_size += 10000; PGO_ProbeNameMappings = realloc(PGO_ProbeNameMappings, PGO_ProbeNameMappings_size); } PGO_ProbeNameMappings[PGO_ProbeNameMappings_used] = str; PGO_ProbeNameMappings_used += 1; return PGO_ProbeNameMappings_used - 1; } static void PGO_writeString(char const *value) { uint32_t id = PGO_getStringID(value); fwrite(&id, sizeof(id), 1, pgo_output); } void PGO_Initialize() { // We expect an environment variable to guide us to where the PGO information // shall be written to. char const *output_filename = getenv("NUITKA_PGO_OUTPUT"); if (unlikely(output_filename == NULL)) { NUITKA_CANNOT_GET_HERE("NUITKA_PGO_OUTPUT needs to be set"); } pgo_output = fopen(output_filename, "wb"); if (unlikely(output_filename == NULL)) { fprintf(stderr, "Error, failed to open '%s' for writing.", output_filename); exit(27); } fputs("KAY.PGO", pgo_output); fflush(pgo_output); PGO_ProbeNameMappings_size = 10000; PGO_ProbeNameMappings = malloc(PGO_ProbeNameMappings_size * sizeof(char const *)); } void PGO_Finalize() { PGO_writeString("END"); uint32_t offset = (uint32_t)ftell(pgo_output); for (int i = 0; i < PGO_ProbeNameMappings_used; i++) { fputs(PGO_ProbeNameMappings[i], pgo_output); fputc(0, pgo_output); } fwrite(&PGO_ProbeNameMappings_used, sizeof(PGO_ProbeNameMappings_used), 1, pgo_output); fwrite(&offset, sizeof(offset), 1, pgo_output); fputs("YAK.PGO", pgo_output); fclose(pgo_output); } void PGO_onProbePassed(char const *probe_str, char const *module_name, uint32_t probe_arg) { PGO_writeString(probe_str); PGO_writeString(module_name); // TODO: Variable args depending on probe type? fwrite(&probe_arg, sizeof(probe_arg), 1, pgo_output); } void PGO_onModuleEntered(char const *module_name) { PGO_onProbePassed("ModuleEnter", module_name, 0); } void PGO_onModuleExit(char const *module_name, bool error) { PGO_onProbePassed("ModuleExit", module_name, error); } void PGO_onTechnicalModule(char const *module_name) { PGO_onProbePassed("ModuleTechnical", module_name, 0); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryAdd.c0000600000372100037210000055744714166627112032252 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersOperationBinaryAddUtils.c" /* C helpers for type specialized "+" (ADD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; if (Py_ABS(Py_SIZE(operand1)) <= 1 && Py_ABS(Py_SIZE(operand2)) <= 1) { PyObject *r = Nuitka_LongFromCLong(MEDIUM_VALUE(operand1) + MEDIUM_VALUE(operand2)); obj_result = r; goto exit_result_object; } { PyLongObject *z; digit const *a = Nuitka_LongGetDigitPointer(operand1); Py_ssize_t size_a = Nuitka_LongGetDigitSize(operand1); digit const *b = Nuitka_LongGetDigitPointer(operand2); Py_ssize_t size_b = Nuitka_LongGetDigitSize(operand2); if (Py_SIZE(operand1) < 0) { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); Py_SIZE(z) = -(Py_SIZE(z)); } else { z = _Nuitka_LongSubDigits(b, size_b, a, size_a); } } else { if (Py_SIZE(operand2) < 0) { z = _Nuitka_LongSubDigits(a, size_a, b, size_b); } else { z = _Nuitka_LongAddDigits(a, size_a, b, size_b); } } obj_result = (PyObject *)z; goto exit_result_object; } exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyObject *result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = PyFloat_FromDouble(cfloat_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); nuitka_bool result; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyFloat_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'float'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyFloat_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(operand1, operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); double a = PyFloat_AS_DOUBLE(operand1); double b = PyFloat_AS_DOUBLE(operand2); double r = a + b; cfloat_result = r; goto exit_result_ok_cfloat; exit_result_ok_cfloat: result = cfloat_result != 0.0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'str'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_STR_STR(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; #if PYTHON_VERSION < 0x300 exit_binary_exception: return NULL; #endif } static PyObject *_BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_STR_STR(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(operand1, operand2); } #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'unicode'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'str'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; #if PYTHON_VERSION < 0x300 exit_binary_exception: return NULL; #endif } static PyObject *_BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = UNICODE_CONCAT(operand1, operand2); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(operand1, operand2); } #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'bytes'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyBytes_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; #if PYTHON_VERSION < 0x300 exit_binary_exception: return NULL; #endif } static PyObject *_BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(operand1, operand2); } #endif /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'tuple'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(operand1, operand2); } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyTuple_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; #if PYTHON_VERSION < 0x300 exit_binary_exception: return NULL; #endif } static PyObject *_BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = TUPLE_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'list'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_LIST_LIST(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyList_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; #if PYTHON_VERSION < 0x300 exit_binary_exception: return NULL; #endif } static PyObject *_BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_ADD_OBJECT_LIST_LIST(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and 'list'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_LIST_LIST(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(operand1, operand2); } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { PyObject *o = PyList_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } #if PYTHON_VERSION < 0x300 exit_binary_exception: return NUITKA_BOOL_EXCEPTION; #endif } static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_ADD_NBOOL_LIST_LIST(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = LIST_CONCAT(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_FLOAT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_INT_FLOAT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_FLOAT_INT(operand1, operand2); } #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_FLOAT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyFloat_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyFloat_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'long' and 'float'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'int' and 'float'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_LONG_FLOAT(operand1, operand2); } /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_add; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types { // No sequence repeat slot sq_concat available for this type. assert(type1->tp_as_sequence == NULL || type1->tp_as_sequence->sq_concat == NULL); } #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'long'"); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: 'float' and 'int'"); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_FLOAT_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; } PyObject *BINARY_OPERATION_ADD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_STR_UNICODE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: return obj_result; } PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_UNICODE_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_STR_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = &PyUnicode_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyString_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } } nuitka_bool BINARY_OPERATION_ADD_NBOOL_STR_UNICODE(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_STR_UNICODE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_UNICODE_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = &PyString_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif assert(type2 == NULL || type2->tp_as_number == NULL || type2->tp_as_number->nb_add == NULL || type1->tp_as_number->nb_add == type2->tp_as_number->nb_add); // Statically recognized that coercion is not possible with these types { PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(operand1, operand2); obj_result = o; goto exit_binary_result_object; } NUITKA_CANNOT_GET_HERE("missing error exit annotation"); exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } } nuitka_bool BINARY_OPERATION_ADD_NBOOL_UNICODE_STR(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_UNICODE_STR(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_ADD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); if (likely(no_overflow)) { clong_result = x; goto exit_result_ok_clong; } { PyObject *operand1_object = operand1; PyObject *operand2_object = operand2; PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object); assert(r != Py_NotImplemented); obj_result = r; goto exit_result_object; } exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_ADD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long x = (long)((unsigned long)a + b); bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0); bool t = !no_overflow || x != 0; cbool_result = t; goto exit_result_ok_cbool; exit_result_ok_cbool: result = cbool_result ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_add; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif { // Special case for "+" and "*", also works as sequence concat/repeat. binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL; if (sq_slot != NULL) { PyObject *result = sq_slot(operand1, operand2); obj_result = result; goto exit_binary_result_object; } } PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_ADD_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersRaising.c0000600000372100037210000003445614166627112030116 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This helpers is used to work with lists. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif static void FORMAT_TYPE_ERROR1(PyObject **exception_type, PyObject **exception_value, char const *format, char const *arg) { *exception_type = PyExc_TypeError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat(format, arg); CHECK_OBJECT(*exception_value); } #if PYTHON_VERSION >= 0x270 static void FORMAT_TYPE_ERROR2(PyObject **exception_type, PyObject **exception_value, char const *format, char const *arg1, char const *arg2) { *exception_type = PyExc_TypeError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat(format, arg1, arg2); CHECK_OBJECT(*exception_value); } #endif #if PYTHON_VERSION < 0x266 #define WRONG_EXCEPTION_TYPE_ERROR_MESSAGE "exceptions must be classes or instances, not %s" #elif PYTHON_VERSION < 0x300 #define WRONG_EXCEPTION_TYPE_ERROR_MESSAGE "exceptions must be old-style classes or derived from BaseException, not %s" #else #define WRONG_EXCEPTION_TYPE_ERROR_MESSAGE "exceptions must derive from BaseException" #endif void RAISE_EXCEPTION_WITH_TYPE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { *exception_value = NULL; *exception_tb = NULL; #if PYTHON_VERSION < 0x300 // Next, repeatedly, replace a tuple exception with its first item while (PyTuple_Check(*exception_type) && PyTuple_GET_SIZE(*exception_type) > 0) { PyObject *tmp = *exception_type; *exception_type = PyTuple_GET_ITEM(*exception_type, 0); Py_INCREF(*exception_type); Py_DECREF(tmp); } #endif if (PyExceptionClass_Check(*exception_type)) { NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); #if PYTHON_VERSION >= 0x270 if (unlikely(!PyExceptionInstance_Check(*exception_value))) { PyObject *old_exception_type = *exception_type; PyObject *old_exception_value = *exception_value; FORMAT_TYPE_ERROR2(exception_type, exception_value, "calling %s() should have returned an instance of BaseException, not '%s'", Py_TYPE(*exception_type)->tp_name, Py_TYPE(*exception_value)->tp_name); Py_DECREF(old_exception_type); Py_DECREF(old_exception_value); return; } #endif #if PYTHON_VERSION >= 0x300 CHAIN_EXCEPTION(*exception_value); #endif return; } else if (PyExceptionInstance_Check(*exception_type)) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); #if PYTHON_VERSION >= 0x300 CHAIN_EXCEPTION(*exception_value); // Note: Cannot be assigned here. assert(*exception_tb == NULL); *exception_tb = (PyTracebackObject *)PyException_GetTraceback(*exception_value); #endif return; } else { PyObject *old_exception_type = *exception_type; FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); return; } } #if PYTHON_VERSION >= 0x300 void RAISE_EXCEPTION_WITH_CAUSE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb, PyObject *exception_cause) { CHECK_OBJECT(*exception_type); CHECK_OBJECT(exception_cause); *exception_tb = NULL; // None is not a cause. if (exception_cause == Py_None) { Py_DECREF(exception_cause); exception_cause = NULL; } else if (PyExceptionClass_Check(exception_cause)) { PyObject *old_exception_cause = exception_cause; exception_cause = PyObject_CallObject(exception_cause, NULL); Py_DECREF(old_exception_cause); if (unlikely(exception_cause == NULL)) { Py_DECREF(*exception_type); Py_XDECREF(*exception_tb); FETCH_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return; } } if (unlikely(exception_cause != NULL && !PyExceptionInstance_Check(exception_cause))) { Py_DECREF(*exception_type); Py_XDECREF(*exception_tb); PyObject *old_exception_cause = exception_cause; #ifdef _NUITKA_FULL_COMPAT SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "exception causes must derive from BaseException"); FETCH_ERROR_OCCURRED(exception_type, exception_value, exception_tb); #else FORMAT_TYPE_ERROR1(exception_type, exception_value, "exception causes must derive from BaseException (%s does not)", Py_TYPE(exception_cause)->tp_name); #endif Py_XDECREF(old_exception_cause); return; } if (PyExceptionClass_Check(*exception_type)) { NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); if (unlikely(!PyExceptionInstance_Check(*exception_value))) { Py_DECREF(*exception_tb); Py_XDECREF(exception_cause); PyObject *old_exception_type = *exception_type; PyObject *old_exception_value = *exception_value; FORMAT_TYPE_ERROR2(exception_type, exception_value, "calling %s() should have returned an instance of BaseException, not '%s'", Py_TYPE(*exception_type)->tp_name, Py_TYPE(*exception_value)->tp_name); Py_DECREF(old_exception_type); Py_XDECREF(old_exception_value); return; } PyException_SetCause(*exception_value, exception_cause); CHAIN_EXCEPTION(*exception_value); return; } else if (PyExceptionInstance_Check(*exception_type)) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); PyException_SetCause(*exception_value, exception_cause); CHAIN_EXCEPTION(*exception_value); return; } else { Py_XDECREF(exception_cause); PyObject *old_exception_type = *exception_type; FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); return; } } #endif void RAISE_EXCEPTION_WITH_VALUE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { CHECK_OBJECT(*exception_type); CHECK_OBJECT(*exception_value); *exception_tb = NULL; // Non-empty tuple exceptions are the first element. while (unlikely(PyTuple_Check(*exception_type) && PyTuple_GET_SIZE(*exception_type) > 0)) { *exception_type = PyTuple_GET_ITEM(*exception_type, 0); } if (PyExceptionClass_Check(*exception_type)) { NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); #if PYTHON_VERSION >= 0x270 if (unlikely(!PyExceptionInstance_Check(*exception_value))) { PyObject *old_exception_type = *exception_type; PyObject *old_exception_value = *exception_type; FORMAT_TYPE_ERROR2(exception_type, exception_value, "calling %s() should have returned an instance of BaseException, not '%s'", Py_TYPE(*exception_type)->tp_name, Py_TYPE(*exception_value)->tp_name); Py_DECREF(old_exception_type); Py_DECREF(old_exception_value); } #endif return; } else if (PyExceptionInstance_Check(*exception_type)) { if (unlikely(*exception_value != NULL && *exception_value != Py_None)) { Py_DECREF(*exception_type); Py_DECREF(*exception_value); *exception_type = PyExc_TypeError; Py_INCREF(PyExc_TypeError); *exception_value = Nuitka_String_FromString("instance exception may not have a separate value"); return; } // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); return; } else { PyObject *old_exception_type = *exception_type; FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); return; } } void RAISE_EXCEPTION_IMPLICIT(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { CHECK_OBJECT(*exception_type); CHECK_OBJECT(*exception_value); *exception_tb = NULL; // Non-empty tuple exceptions are the first element. while (unlikely(PyTuple_Check(*exception_type) && PyTuple_GET_SIZE(*exception_type) > 0)) { *exception_type = PyTuple_GET_ITEM(*exception_type, 0); } if (PyExceptionClass_Check(*exception_type)) { #if PYTHON_VERSION >= 0x340 NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); CHAIN_EXCEPTION(*exception_value); #endif return; } else if (PyExceptionInstance_Check(*exception_type)) { #if PYTHON_VERSION >= 0x340 CHAIN_EXCEPTION(*exception_value); #endif // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); return; } else { PyObject *old_exception_type = *exception_type; Py_DECREF(*exception_value); FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); #if PYTHON_VERSION >= 0x340 CHAIN_EXCEPTION(*exception_value); #endif return; } } void RAISE_EXCEPTION_WITH_TRACEBACK(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { CHECK_OBJECT(*exception_type); CHECK_OBJECT(*exception_value); if (*exception_tb == (PyTracebackObject *)Py_None) { Py_DECREF(*exception_tb); *exception_tb = NULL; } // Non-empty tuple exceptions are the first element. while (unlikely(PyTuple_Check(*exception_type) && PyTuple_GET_SIZE(*exception_type) > 0)) { *exception_type = PyTuple_GET_ITEM(*exception_type, 0); } if (PyExceptionClass_Check(*exception_type)) { NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); #if PYTHON_VERSION >= 0x270 if (unlikely(!PyExceptionInstance_Check(*exception_value))) { PyObject *old_exception_type = *exception_type; PyObject *old_exception_value = *exception_value; FORMAT_TYPE_ERROR2(exception_type, exception_value, "calling %s() should have returned an instance of BaseException, not '%s'", Py_TYPE(*exception_type)->tp_name, Py_TYPE(*exception_value)->tp_name); Py_DECREF(old_exception_type); Py_DECREF(old_exception_value); } #endif return; } else if (PyExceptionInstance_Check(*exception_type)) { if (unlikely(*exception_value != NULL && *exception_value != Py_None)) { Py_DECREF(*exception_type); Py_XDECREF(*exception_value); Py_XDECREF(*exception_tb); *exception_type = PyExc_TypeError; Py_INCREF(PyExc_TypeError); *exception_value = Nuitka_String_FromString("instance exception may not have a separate value"); return; } // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); return; } else { PyObject *old_exception_type = *exception_type; FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); return; } } bool RERAISE_EXCEPTION(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { PyThreadState *tstate = PyThreadState_GET(); assert(tstate); *exception_type = EXC_TYPE(tstate) != NULL ? EXC_TYPE(tstate) : Py_None; Py_INCREF(*exception_type); *exception_value = EXC_VALUE(tstate); Py_XINCREF(*exception_value); *exception_tb = (PyTracebackObject *)EXC_TRACEBACK(tstate); Py_XINCREF(*exception_tb); CHECK_OBJECT(*exception_type); if (*exception_type == Py_None) { #if PYTHON_VERSION >= 0x300 Py_DECREF(*exception_type); Py_INCREF(PyExc_RuntimeError); *exception_type = PyExc_RuntimeError; *exception_value = PyUnicode_FromString("No active exception to reraise"); *exception_tb = NULL; #else PyObject *old_exception_type = *exception_type; FORMAT_TYPE_ERROR1(exception_type, exception_value, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE(*exception_type)->tp_name); Py_DECREF(old_exception_type); #endif return false; } return true; } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledGeneratorType.c0000600000372100037210000016356214166627112031445 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Compiled Generators. * * Unlike in CPython, we have one type for just generators, this doesn't do coroutines * nor asyncgen. * * It strives to be full replacement for normal generators, while providing also an * interface for quick iteration from compiled code. * */ #include "nuitka/prelude.h" #include "nuitka/freelists.h" // In a separate file, code to interact with uncompiled generators, that does // all the quirks necessary to get those working. #include "CompiledGeneratorTypeUncompiledIntegration.c" // Debugging output tools #if _DEBUG_GENERATOR NUITKA_MAY_BE_UNUSED static void _PRINT_GENERATOR_STATUS(char const *descriptor, char const *context, struct Nuitka_GeneratorObject *generator) { char const *status; switch (generator->m_status) { case status_Finished: status = "(finished)"; break; case status_Running: status = "(running)"; break; case status_Unused: status = "(unused)"; break; default: status = "(ILLEGAL)"; break; } PRINT_STRING(descriptor); PRINT_STRING(" : "); PRINT_STRING(context); PRINT_STRING(" "); PRINT_ITEM((PyObject *)generator); PRINT_STRING(" "); PRINT_STRING(status); PRINT_STRING(" "); PRINT_REFCOUNT((PyObject *)generator); PRINT_NEW_LINE(); } #define PRINT_GENERATOR_STATUS(context, generator) _PRINT_GENERATOR_STATUS(__FUNCTION__, context, generator) #endif #if _DEBUG_GENERATOR || _DEBUG_COROUTINE || _DEBUG_ASYNCGEN NUITKA_MAY_BE_UNUSED static void PRINT_COROUTINE_VALUE(char const *name, PyObject *value) { PRINT_STRING(name); PRINT_STRING("="); PRINT_ITEM(value); if (value) { PRINT_REFCOUNT(value); } PRINT_NEW_LINE(); } NUITKA_MAY_BE_UNUSED static void PRINT_COROUTINE_STRING(char const *name, char const *value) { PRINT_STRING(name); PRINT_STRING("="); PRINT_STRING(value); PRINT_NEW_LINE(); } #endif static PyObject *Nuitka_Generator_tp_repr(struct Nuitka_GeneratorObject *generator) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat("", Nuitka_String_AsString(generator->m_name), generator); #else return PyUnicode_FromFormat("", #if PYTHON_VERSION < 0x350 Nuitka_String_AsString(generator->m_name), #else Nuitka_String_AsString(generator->m_qualname), #endif generator); #endif } static long Nuitka_Generator_tp_traverse(struct Nuitka_GeneratorObject *generator, visitproc visit, void *arg) { CHECK_OBJECT(generator); // TODO: Identify the impact of not visiting owned objects like module. #if PYTHON_VERSION >= 0x300 Py_VISIT(generator->m_yieldfrom); #endif for (Py_ssize_t i = 0; i < generator->m_closure_given; i++) { Py_VISIT(generator->m_closure[i]); } Py_VISIT(generator->m_frame); return 0; } static void Nuitka_Generator_release_closure(struct Nuitka_GeneratorObject *generator) { for (Py_ssize_t i = 0; i < generator->m_closure_given; i++) { CHECK_OBJECT(generator->m_closure[i]); Py_DECREF(generator->m_closure[i]); } generator->m_closure_given = 0; } #if PYTHON_VERSION >= 0x300 // Note: Shared with coroutines and asyncgen code. static PyObject *ERROR_GET_STOP_ITERATION_VALUE() { assert(PyErr_ExceptionMatches(PyExc_StopIteration)); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); Py_DECREF(exception_type); Py_XDECREF(exception_tb); PyObject *value = NULL; if (exception_value) { if (EXCEPTION_MATCH_BOOL_SINGLE(exception_value, PyExc_StopIteration)) { value = ((PyStopIterationObject *)exception_value)->value; Py_XINCREF(value); Py_DECREF(exception_value); } else { value = exception_value; } } if (value == NULL) { Py_INCREF(Py_None); value = Py_None; } return value; } static PyObject *_Nuitka_Generator_throw2(struct Nuitka_GeneratorObject *generator, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb); #if PYTHON_VERSION >= 0x350 static PyObject *_Nuitka_Coroutine_throw2(struct Nuitka_CoroutineObject *coroutine, bool closing, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb); #endif static PyObject *_Nuitka_YieldFromPassExceptionTo(PyObject *value, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { // The yielding generator is being closed, but we also are tasked to // immediately close the currently running sub-generator. if (EXCEPTION_MATCH_BOOL_SINGLE(exception_type, PyExc_GeneratorExit)) { PyObject *close_method = PyObject_GetAttr(value, const_str_plain_close); if (close_method) { PyObject *close_value = PyObject_Call(close_method, const_tuple_empty, NULL); Py_DECREF(close_method); if (unlikely(close_value == NULL)) { // Release exception, we are done with it, raising the one from close instead. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } Py_DECREF(close_value); } else { PyObject *error = GET_ERROR_OCCURRED(); if (error != NULL && !EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_AttributeError)) { PyErr_WriteUnraisable((PyObject *)value); } } // Transfer exception ownership to pusblished. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; } #if NUITKA_UNCOMPILED_THROW_INTEGRATION if (PyGen_CheckExact(value) #if PYTHON_VERSION >= 0x350 || PyCoro_CheckExact(value) #endif ) { PyGenObject *gen = (PyGenObject *)value; // Handing exception ownership over. PyObject *result = Nuitka_UncompiledGenerator_throw(gen, 1, exception_type, exception_value, exception_tb); return result; } #endif if (Nuitka_Generator_Check(value)) { struct Nuitka_GeneratorObject *gen = ((struct Nuitka_GeneratorObject *)value); return _Nuitka_Generator_throw2(gen, exception_type, exception_value, exception_tb); } #if PYTHON_VERSION >= 0x350 if (Nuitka_Coroutine_Check(value)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineObject *)value); // Handing exception ownership over. return _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); } if (Nuitka_CoroutineWrapper_Check(value)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineWrapperObject *)value)->m_coroutine; // Handing exception ownership over. return _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); } #endif PyObject *throw_method = PyObject_GetAttr(value, const_str_plain_throw); if (throw_method) { PyObject *result = PyObject_CallFunctionObjArgs(throw_method, exception_type, exception_value, exception_tb, NULL); Py_DECREF(throw_method); // Releasing exception we own. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return result; } else if (EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_AttributeError)) { // Restoring the exception we own, to be released when handling it. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; } else { assert(ERROR_OCCURRED()); // Releasing exception we own. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } } static PyObject *_Nuitka_YieldFromGeneratorCore(struct Nuitka_GeneratorObject *generator, PyObject *yieldfrom, PyObject *send_value) { // Send iteration value to the sub-generator, which may be a CPython // generator object, something with an iterator next, or a send method, // where the later is only required if values other than "None" need to // be passed in. CHECK_OBJECT(yieldfrom); assert(send_value != NULL || ERROR_OCCURRED()); PyObject *retval; #if 0 PRINT_STRING("YIELD CORE:"); PRINT_ITEM( value ); PRINT_ITEM( send_value ); PRINT_NEW_LINE(); #endif assert(send_value != NULL || ERROR_OCCURRED()); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); // Exception, was thrown into us, need to send that to sub-generator. if (exception_type != NULL) { // Passing ownership of exception fetch to it. retval = _Nuitka_YieldFromPassExceptionTo(yieldfrom, exception_type, exception_value, exception_tb); if (unlikely(send_value == NULL)) { PyObject *error = GET_ERROR_OCCURRED(); if (error != NULL && EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopIteration)) { generator->m_returned = ERROR_GET_STOP_ITERATION_VALUE(); assert(!ERROR_OCCURRED()); return NULL; } } } else if (PyGen_CheckExact(yieldfrom)) { retval = Nuitka_PyGen_Send((PyGenObject *)yieldfrom, Py_None); } #if PYTHON_VERSION >= 0x350 else if (PyCoro_CheckExact(yieldfrom)) { retval = Nuitka_PyGen_Send((PyGenObject *)yieldfrom, Py_None); } #endif else if (send_value == Py_None && Py_TYPE(yieldfrom)->tp_iternext != NULL) { retval = Py_TYPE(yieldfrom)->tp_iternext(yieldfrom); } else { // Bug compatibility here, before 3.3 tuples were unrolled in calls, which is what // PyObject_CallMethod does. #if PYTHON_VERSION >= 0x340 retval = PyObject_CallMethodObjArgs(yieldfrom, const_str_plain_send, send_value, NULL); #else retval = PyObject_CallMethod(yieldfrom, (char *)"send", (char *)"O", send_value); #endif } // Check the sub-generator result if (retval == NULL) { PyObject *error = GET_ERROR_OCCURRED(); if (error == NULL) { Py_INCREF(Py_None); generator->m_returned = Py_None; } else if (likely(EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_StopIteration))) { // The sub-generator has given an exception. In case of // StopIteration, we need to check the value, as it is going to be // the expression value of this "yield from", and we are done. All // other errors, we need to raise. generator->m_returned = ERROR_GET_STOP_ITERATION_VALUE(); assert(!ERROR_OCCURRED()); } return NULL; } else { return retval; } } static PyObject *Nuitka_YieldFromGeneratorCore(struct Nuitka_GeneratorObject *generator, PyObject *send_value) { CHECK_OBJECT(generator); CHECK_OBJECT_X(send_value); PyObject *yieldfrom = generator->m_yieldfrom; CHECK_OBJECT(yieldfrom); // Need to make it unaccessible while using it. generator->m_yieldfrom = NULL; PyObject *yielded = _Nuitka_YieldFromGeneratorCore(generator, yieldfrom, send_value); if (yielded == NULL) { Py_DECREF(yieldfrom); if (generator->m_returned != NULL) { PyObject *yield_from_result = generator->m_returned; generator->m_returned = NULL; yielded = ((generator_code)generator->m_code)(generator, yield_from_result); } else { assert(ERROR_OCCURRED()); yielded = ((generator_code)generator->m_code)(generator, NULL); } } else { generator->m_yieldfrom = yieldfrom; } return yielded; } static PyObject *Nuitka_YieldFromGeneratorNext(struct Nuitka_GeneratorObject *generator) { CHECK_OBJECT(generator); // Coroutines are already perfect for yielding from. #if PYTHON_VERSION >= 0x350 if (PyCoro_CheckExact(generator->m_yieldfrom) || Nuitka_Coroutine_Check(generator->m_yieldfrom)) { if (unlikely((generator->m_code_object->co_flags & CO_ITERABLE_COROUTINE) == 0)) { Py_DECREF(generator->m_yieldfrom); generator->m_yieldfrom = NULL; SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "cannot 'yield from' a coroutine object in a non-coroutine generator"); return NULL; } } else #endif { PyObject *old = generator->m_yieldfrom; generator->m_yieldfrom = MAKE_ITERATOR(generator->m_yieldfrom); Py_DECREF(old); if (unlikely(generator->m_yieldfrom == NULL)) { return NULL; } } return Nuitka_YieldFromGeneratorCore(generator, Py_None); } static PyObject *Nuitka_YieldFromGeneratorInitial(struct Nuitka_GeneratorObject *generator, PyObject *send_value) { PyObject *result = Nuitka_YieldFromGeneratorCore(generator, send_value); #if 0 PRINT_STRING("RES:"); PRINT_ITEM( result ); PRINT_NEW_LINE(); #endif return result; } #endif static PyObject *_Nuitka_Generator_send(struct Nuitka_GeneratorObject *generator, PyObject *value, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { CHECK_OBJECT(generator); assert(Nuitka_Generator_Check((PyObject *)generator)); CHECK_OBJECT_X(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); CHECK_OBJECT_X(value); #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Enter", generator); PRINT_COROUTINE_VALUE("value", value); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif if (value != NULL) { assert(exception_type == NULL); assert(exception_value == NULL); assert(exception_tb == NULL); } if (generator->m_status != status_Finished) { if (generator->m_running) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "generator already executing"); return NULL; } PyThreadState *thread_state = PyThreadState_GET(); #if PYTHON_VERSION < 0x300 PyObject *saved_exception_type = thread_state->exc_type; PyObject *saved_exception_value = NULL; PyTracebackObject *saved_exception_traceback = NULL; if (saved_exception_type != Py_None && saved_exception_type != NULL) { saved_exception_value = thread_state->exc_value; Py_INCREF(saved_exception_type); Py_XINCREF(saved_exception_value); saved_exception_traceback = (PyTracebackObject *)thread_state->exc_traceback; Py_XINCREF(saved_exception_traceback); } #endif // Put the generator back on the frame stack. // First take of running frame from the stack, owning a reference. PyFrameObject *return_frame = thread_state->frame; #ifndef __NUITKA_NO_ASSERT__ if (return_frame) { assertFrameObject((struct Nuitka_FrameObject *)return_frame); } #endif if (generator->m_frame) { // It would be nice if our frame were still alive. Nobody had the // right to release it. assertFrameObject(generator->m_frame); // It's not supposed to be on the top right now. assert(return_frame != &generator->m_frame->m_frame); Py_XINCREF(return_frame); generator->m_frame->m_frame.f_back = return_frame; thread_state->frame = &generator->m_frame->m_frame; } if (generator->m_status == status_Unused) { generator->m_status = status_Running; } // Continue the yielder function while preventing recursion. generator->m_running = true; // Check for thrown exception, publish it to the generator code. if (unlikely(exception_type)) { assert(value == NULL); // Transfer exception ownership to published. RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); } if (generator->m_frame) { Nuitka_Frame_MarkAsExecuting(generator->m_frame); } #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Switching to coroutine", generator); PRINT_COROUTINE_VALUE("value", value); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); // dumpFrameStack(); #endif PyObject *yielded; #if PYTHON_VERSION >= 0x300 if (generator->m_yieldfrom == NULL) { yielded = ((generator_code)generator->m_code)(generator, value); } else { yielded = Nuitka_YieldFromGeneratorInitial(generator, value); } #else yielded = ((generator_code)generator->m_code)(generator, value); #endif #if PYTHON_VERSION >= 0x300 // If the generator returns with m_yieldfrom set, it wants us to yield // from that value from now on. while (yielded == NULL && generator->m_yieldfrom != NULL) { yielded = Nuitka_YieldFromGeneratorNext(generator); } #endif if (generator->m_frame) { Nuitka_Frame_MarkAsNotExecuting(generator->m_frame); } generator->m_running = false; thread_state = PyThreadState_GET(); // Remove the generator from the frame stack. if (generator->m_frame) { // assert(thread_state->frame == &generator->m_frame->m_frame); assertFrameObject(generator->m_frame); Py_CLEAR(generator->m_frame->m_frame.f_back); } thread_state->frame = return_frame; #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Returned from coroutine", generator); // dumpFrameStack(); #endif if (yielded == NULL) { #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("finishing from yield", generator); PRINT_STRING("-> finishing generator sets status_Finished\n"); PRINT_COROUTINE_VALUE("return_value", generator->m_returned); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif generator->m_status = status_Finished; if (generator->m_frame != NULL) { #if PYTHON_VERSION >= 0x340 generator->m_frame->m_frame.f_gen = NULL; #endif Py_DECREF(generator->m_frame); generator->m_frame = NULL; } Nuitka_Generator_release_closure(generator); #if PYTHON_VERSION < 0x300 if (saved_exception_type != NULL && saved_exception_type != Py_None) { Py_DECREF(saved_exception_type); Py_XDECREF(saved_exception_value); Py_XDECREF(saved_exception_traceback); } #endif #if PYTHON_VERSION >= 0x350 if ( #if PYTHON_VERSION < 0x370 generator->m_code_object->co_flags & CO_FUTURE_GENERATOR_STOP && #endif GET_ERROR_OCCURRED() == PyExc_StopIteration) { PyObject *saved_exception_type, *saved_exception_value; PyTracebackObject *saved_exception_tb; FETCH_ERROR_OCCURRED(&saved_exception_type, &saved_exception_value, &saved_exception_tb); NORMALIZE_EXCEPTION(&saved_exception_type, &saved_exception_value, &saved_exception_tb); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "generator raised StopIteration"); FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); RAISE_EXCEPTION_WITH_CAUSE(&exception_type, &exception_value, &exception_tb, saved_exception_value); CHECK_OBJECT(exception_value); CHECK_OBJECT(saved_exception_value); Py_INCREF(saved_exception_value); PyException_SetContext(exception_value, saved_exception_value); Py_DECREF(saved_exception_type); Py_XDECREF(saved_exception_tb); RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; } #endif // Create StopIteration if necessary, i.e. return value that is not "None" was // given. TODO: Push this further down the user line, we might be able to avoid // it for some uses, e.g. quick iteration entirely. #if PYTHON_VERSION >= 0x300 if (generator->m_returned) { if (generator->m_returned != Py_None) { Nuitka_SetStopIterationValue(generator->m_returned); } Py_DECREF(generator->m_returned); generator->m_returned = NULL; #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Return value to exception set", generator); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } #endif return NULL; } else { #if _NUITKA_MAINTAIN_SYS_EXC_VARS PyObject *old_type = thread_state->exc_type; PyObject *old_value = thread_state->exc_value; PyTracebackObject *old_tb = (PyTracebackObject *)thread_state->exc_traceback; // Set sys attributes in the fastest possible way. PyObject *sys_dict = thread_state->interp->sysdict; CHECK_OBJECT(sys_dict); if (saved_exception_type != NULL && saved_exception_type != Py_None) { thread_state->exc_type = saved_exception_type; thread_state->exc_value = saved_exception_value; thread_state->exc_traceback = (PyObject *)saved_exception_traceback; Py_XDECREF(old_type); Py_XDECREF(old_value); Py_XDECREF(old_tb); if (old_type != saved_exception_type) { PyDict_SetItem(sys_dict, const_str_plain_exc_type, saved_exception_type); } if (saved_exception_value != old_value) { PyDict_SetItem(sys_dict, const_str_plain_exc_value, saved_exception_value ? saved_exception_value : Py_None); } if (saved_exception_traceback != old_tb) { PyDict_SetItem(sys_dict, const_str_plain_exc_traceback, saved_exception_traceback ? (PyObject *)saved_exception_traceback : Py_None); } } else { thread_state->exc_type = Py_None; thread_state->exc_value = Py_None; thread_state->exc_traceback = (PyObject *)Py_None; Py_INCREF(Py_None); Py_INCREF(Py_None); Py_INCREF(Py_None); Py_XDECREF(old_type); Py_XDECREF(old_value); Py_XDECREF(old_tb); if (old_type != Py_None) { PyDict_SetItem(sys_dict, const_str_plain_exc_type, Py_None); } if (old_value != Py_None) { PyDict_SetItem(sys_dict, const_str_plain_exc_value, Py_None); } if (old_tb != (PyTracebackObject *)Py_None) { PyDict_SetItem(sys_dict, const_str_plain_exc_traceback, Py_None); } } #endif return yielded; } } else { return NULL; } } static PyObject *Nuitka_Generator_send(struct Nuitka_GeneratorObject *generator, PyObject *value) { if (generator->m_status == status_Unused && value != NULL && value != Py_None) { // Newer Python refuses to allow later usage. #if PYTHON_VERSION >= 0x3a0 generator->m_status = status_Finished; #endif SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "can't send non-None value to a just-started generator"); return NULL; } PyObject *result = _Nuitka_Generator_send(generator, value, NULL, NULL, NULL); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } return result; } static PyObject *Nuitka_Generator_tp_iternext(struct Nuitka_GeneratorObject *generator) { return _Nuitka_Generator_send(generator, Py_None, NULL, NULL, NULL); } /* Our own qiter interface, which is for quicker simple loop style iteration, that does not send anything in. */ PyObject *Nuitka_Generator_qiter(struct Nuitka_GeneratorObject *generator, bool *finished) { PyObject *result = _Nuitka_Generator_send(generator, Py_None, NULL, NULL, NULL); if (result == NULL) { if (unlikely(!CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED())) { *finished = false; return NULL; } *finished = true; return NULL; } *finished = false; return result; } // Note: Used by compiled frames. static bool _Nuitka_Generator_close(struct Nuitka_GeneratorObject *generator) { #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Enter", generator); #endif CHECK_OBJECT(generator); if (generator->m_status == status_Running) { Py_INCREF(PyExc_GeneratorExit); PyObject *result = _Nuitka_Generator_send(generator, NULL, PyExc_GeneratorExit, NULL, NULL); if (unlikely(result)) { Py_DECREF(result); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "generator ignored GeneratorExit"); return false; } else { PyObject *error = GET_ERROR_OCCURRED(); // StopIteration as exception. if (error == NULL) { return true; } // Maybe another acceptable exception for generator exit. if (EXCEPTION_MATCH_GENERATOR(error)) { CLEAR_ERROR_OCCURRED(); return true; } return false; } } return true; } static PyObject *Nuitka_Generator_close(struct Nuitka_GeneratorObject *generator) { bool r = _Nuitka_Generator_close(generator); if (unlikely(r == false)) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } // Shared code for checking a thrown exception, coroutines, asyncgen, uncompiled ones do this too. static bool _Nuitka_Generator_check_throw2(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { CHECK_OBJECT(*exception_type); CHECK_OBJECT_X(*exception_value); CHECK_OBJECT_X(*exception_tb); if (*exception_tb == (PyTracebackObject *)Py_None) { Py_DECREF(*exception_tb); *exception_tb = NULL; } else if (*exception_tb != NULL && !PyTraceBack_Check(*exception_tb)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "throw() third argument must be a traceback object"); goto failed_throw; } if (PyExceptionClass_Check(*exception_type)) { // TODO: Must not normalize here. NORMALIZE_EXCEPTION(exception_type, exception_value, exception_tb); } else if (PyExceptionInstance_Check(*exception_type)) { if (*exception_value != NULL && *exception_value != Py_None) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } // Release old None value and replace it with the object, then set the exception type // from the class. Py_XDECREF(*exception_value); *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class(*exception_type); Py_INCREF(*exception_type); } else { #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(*exception_type)->tp_name); #else PyErr_Format(PyExc_TypeError, "exceptions must be classes or instances deriving from BaseException, not %s", Py_TYPE(*exception_type)->tp_name); #endif goto failed_throw; } return true; failed_throw: // Release exception, we are done with it now. Py_DECREF(*exception_type); Py_XDECREF(*exception_value); Py_XDECREF(*exception_tb); return false; } #if PYTHON_VERSION >= 0x300 static bool _Nuitka_Generator_close(struct Nuitka_GeneratorObject *generator); #if PYTHON_VERSION >= 0x350 static bool _Nuitka_Coroutine_close(struct Nuitka_CoroutineObject *coroutine); #if PYTHON_VERSION >= 0x360 static bool _Nuitka_Asyncgen_close(struct Nuitka_AsyncgenObject *asyncgen); #endif #endif // Note: This is also used for coroutines and asyncgen static bool Nuitka_gen_close_iter(PyObject *yieldfrom) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Enter\n"); #endif CHECK_OBJECT(yieldfrom); // TODO: Could specialize depending in yieldfrom type for performance. Many // times these will be our own ones, or known ones like uncompiled // generators. if (Nuitka_Generator_Check(yieldfrom)) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Defer to _Nuitka_Generator_close\n"); #endif return _Nuitka_Generator_close((struct Nuitka_GeneratorObject *)yieldfrom); } #if PYTHON_VERSION >= 0x350 if (Nuitka_Coroutine_Check(yieldfrom)) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Defer to _Nuitka_Coroutine_close\n"); #endif return _Nuitka_Coroutine_close((struct Nuitka_CoroutineObject *)yieldfrom); } #endif #if PYTHON_VERSION >= 0x360 if (Nuitka_Asyncgen_Check(yieldfrom)) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Defer to _Nuitka_Asyncgen_close\n"); #endif return _Nuitka_Asyncgen_close((struct Nuitka_AsyncgenObject *)yieldfrom); } #endif PyObject *meth = PyObject_GetAttr(yieldfrom, const_str_plain_close); if (unlikely(meth == NULL)) { if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Strange error while looking up close method.\n"); #endif PyErr_WriteUnraisable(yieldfrom); } CLEAR_ERROR_OCCURRED(); #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Leave, has no close method.\n"); #endif return true; } PyObject *retval = CALL_FUNCTION_NO_ARGS(meth); Py_DECREF(meth); if (unlikely(retval == NULL)) { #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Leave, exception from close.\n"); #endif return false; } CHECK_OBJECT(retval); Py_DECREF(retval); #if _DEBUG_GENERATOR PRINT_STRING("Nuitka_gen_close_iter: Leave, closed.\n"); #endif return true; } #endif #if PYTHON_VERSION >= 0x360 static bool Nuitka_AsyncgenAsend_Check(PyObject *object); struct Nuitka_AsyncgenAsendObject; static PyObject *_Nuitka_AsyncgenAsend_throw2(struct Nuitka_AsyncgenAsendObject *asyncgen_asend, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb); #endif static PyObject *_Nuitka_Generator_throw2(struct Nuitka_GeneratorObject *generator, PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Enter", generator); PRINT_COROUTINE_VALUE("yieldfrom", generator->m_yieldfrom); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_NEW_LINE(); #endif CHECK_OBJECT(generator); assert(Nuitka_Generator_Check((PyObject *)generator)); CHECK_OBJECT(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); #if PYTHON_VERSION >= 0x300 if (generator->m_yieldfrom != NULL) { if (EXCEPTION_MATCH_BOOL_SINGLE(exception_type, PyExc_GeneratorExit)) { // Generators need to close the yield_from. generator->m_running = 1; bool res = Nuitka_gen_close_iter(generator->m_yieldfrom); generator->m_running = 0; if (res == false) { // Release exception, we are done with it now and pick up the new one. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); FETCH_ERROR_OCCURRED(&exception_type, &exception_value, &exception_tb); } // Transferred exception ownership to "_Nuitka_Generator_send". return _Nuitka_Generator_send(generator, NULL, exception_type, exception_value, exception_tb); } PyObject *ret; #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Passing to yielded from", generator); PRINT_COROUTINE_VALUE("m_yieldfrom", generator->m_yieldfrom); PRINT_NEW_LINE(); #endif if (Nuitka_Generator_Check(generator->m_yieldfrom)) { struct Nuitka_GeneratorObject *gen = ((struct Nuitka_GeneratorObject *)generator->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Generator_throw2". generator->m_running = 1; ret = _Nuitka_Generator_throw2(gen, exception_type, exception_value, exception_tb); generator->m_running = 0; #if NUITKA_UNCOMPILED_THROW_INTEGRATION } else if (PyGen_CheckExact(generator->m_yieldfrom)) { PyGenObject *gen = (PyGenObject *)generator->m_yieldfrom; // Transferred exception ownership to "Nuitka_UncompiledGenerator_throw". generator->m_running = 1; ret = Nuitka_UncompiledGenerator_throw(gen, 1, exception_type, exception_value, exception_tb); generator->m_running = 0; #endif #if PYTHON_VERSION >= 0x350 } else if (Nuitka_Coroutine_Check(generator->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineObject *)generator->m_yieldfrom); // Transferred exception ownership to "_Nuitka_Coroutine_throw2". generator->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); generator->m_running = 0; } else if (Nuitka_CoroutineWrapper_Check(generator->m_yieldfrom)) { struct Nuitka_CoroutineObject *coro = ((struct Nuitka_CoroutineWrapperObject *)generator->m_yieldfrom)->m_coroutine; // Transferred exception ownership to "_Nuitka_Coroutine_throw2". generator->m_running = 1; ret = _Nuitka_Coroutine_throw2(coro, true, exception_type, exception_value, exception_tb); generator->m_running = 0; } else if (PyCoro_CheckExact(generator->m_yieldfrom)) { PyGenObject *gen = (PyGenObject *)generator->m_yieldfrom; // Transferred exception ownership to "Nuitka_UncompiledGenerator_throw". generator->m_running = 1; ret = Nuitka_UncompiledGenerator_throw(gen, 1, exception_type, exception_value, exception_tb); generator->m_running = 0; #if PYTHON_VERSION >= 0x360 } else if (Nuitka_AsyncgenAsend_Check(generator->m_yieldfrom)) { struct Nuitka_AsyncgenAsendObject *asyncgen_asend = ((struct Nuitka_AsyncgenAsendObject *)generator->m_yieldfrom); // Transferred exception ownership to "_Nuitka_AsyncgenAsend_throw2". generator->m_running = 1; ret = _Nuitka_AsyncgenAsend_throw2(asyncgen_asend, exception_type, exception_value, exception_tb); generator->m_running = 0; #endif #endif } else { PyObject *meth = PyObject_GetAttr(generator->m_yieldfrom, const_str_plain_throw); if (unlikely(meth == NULL)) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); return NULL; } CLEAR_ERROR_OCCURRED(); // Passing exception ownership to that code. goto throw_here; } CHECK_OBJECT(exception_type); #if 0 // TODO: Add slow mode traces. PRINT_ITEM(coroutine->m_yieldfrom); PRINT_NEW_LINE(); #endif generator->m_running = 1; ret = PyObject_CallFunctionObjArgs(meth, exception_type, exception_value, exception_tb, NULL); generator->m_running = 0; Py_DECREF(meth); // Release exception, we are done with it now. Py_DECREF(exception_type); Py_XDECREF(exception_value); Py_XDECREF(exception_tb); } if (unlikely(ret == NULL)) { // Return value or exception, not to continue with yielding from. if (generator->m_yieldfrom != NULL) { CHECK_OBJECT(generator->m_yieldfrom); #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Null return, yield from removal:", generator); PRINT_COROUTINE_VALUE("yieldfrom", generator->m_yieldfrom); #endif Py_DECREF(generator->m_yieldfrom); generator->m_yieldfrom = NULL; } PyObject *val; if (_PyGen_FetchStopIterationValue(&val) == 0) { CHECK_OBJECT(val); #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Sending return value into ourselves", generator); PRINT_COROUTINE_VALUE("value", val); PRINT_NEW_LINE(); #endif ret = _Nuitka_Generator_send(generator, val, NULL, NULL, NULL); } else { #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Sending exception value into ourselves", generator); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif ret = _Nuitka_Generator_send(generator, NULL, NULL, NULL, NULL); } #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Leave with value/exception from sending into ourselves:", generator); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } else { #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Leave with return value:", generator); PRINT_COROUTINE_VALUE("return_value", ret); PRINT_CURRENT_EXCEPTION(); PRINT_NEW_LINE(); #endif } return ret; } throw_here: #endif // We continue to have exception ownership here. if (unlikely(_Nuitka_Generator_check_throw2(&exception_type, &exception_value, &exception_tb) == false)) { // Exception was released by _Nuitka_Generator_check_throw2 already. return NULL; } if (generator->m_status == status_Running) { // Passing exception ownership to _Nuitka_Generator_send PyObject *result = _Nuitka_Generator_send(generator, NULL, exception_type, exception_value, exception_tb); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } return result; } else if (generator->m_status == status_Finished) { RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); return NULL; } else { if (exception_tb == NULL) { // TODO: Our compiled objects really need a way to store common // stuff in a "shared" part across all instances, and outside of // run time, so we could reuse this. struct Nuitka_FrameObject *frame = MAKE_FUNCTION_FRAME(generator->m_code_object, generator->m_module, 0); exception_tb = MAKE_TRACEBACK(frame, generator->m_code_object->co_firstlineno); Py_DECREF(frame); } RESTORE_ERROR_OCCURRED(exception_type, exception_value, exception_tb); generator->m_status = status_Finished; return NULL; } } static PyObject *Nuitka_Generator_throw(struct Nuitka_GeneratorObject *generator, PyObject *args) { PyObject *exception_type; PyObject *exception_value = NULL; PyTracebackObject *exception_tb = NULL; // This takes no references, that is for us to do. int res = PyArg_UnpackTuple(args, "throw", 1, 3, &exception_type, &exception_value, &exception_tb); if (unlikely(res == 0)) { return NULL; } // Handing ownership of exception over, we need not release it ourselves Py_INCREF(exception_type); Py_XINCREF(exception_value); Py_XINCREF(exception_tb); PyObject *result = _Nuitka_Generator_throw2(generator, exception_type, exception_value, exception_tb); if (result == NULL) { if (GET_ERROR_OCCURRED() == NULL) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } } #if _DEBUG_GENERATOR PRINT_GENERATOR_STATUS("Leave", generator); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); PRINT_COROUTINE_VALUE("return value", result); PRINT_CURRENT_EXCEPTION(); #endif return result; } #if PYTHON_VERSION >= 0x340 static void Nuitka_Generator_tp_finalizer(struct Nuitka_GeneratorObject *generator) { if (generator->m_status != status_Running) { return; } PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); bool close_result = _Nuitka_Generator_close(generator); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)generator); } /* Restore the saved exception if any. */ RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } #endif #define MAX_GENERATOR_FREE_LIST_COUNT 100 static struct Nuitka_GeneratorObject *free_list_generators = NULL; static int free_list_generators_count = 0; static void Nuitka_Generator_tp_dealloc(struct Nuitka_GeneratorObject *generator) { // Revive temporarily. assert(Py_REFCNT(generator) == 0); Py_REFCNT(generator) = 1; // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); if (generator->m_status == status_Running) { bool close_result = _Nuitka_Generator_close(generator); CHECK_OBJECT(generator); if (unlikely(close_result == false)) { PyErr_WriteUnraisable((PyObject *)generator); } } Nuitka_Generator_release_closure(generator); // Allow for above code to resurrect the generator. Py_REFCNT(generator) -= 1; if (Py_REFCNT(generator) >= 1) { return; } if (generator->m_frame != NULL) { #if PYTHON_VERSION >= 0x340 generator->m_frame->m_frame.f_gen = NULL; #endif Py_DECREF(generator->m_frame); generator->m_frame = NULL; } // Now it is safe to release references and memory for it. Nuitka_GC_UnTrack(generator); if (generator->m_weakrefs != NULL) { PyObject_ClearWeakRefs((PyObject *)generator); assert(!ERROR_OCCURRED()); } Py_DECREF(generator->m_name); #if PYTHON_VERSION >= 0x350 Py_DECREF(generator->m_qualname); #endif /* Put the object into freelist or release to GC */ releaseToFreeList(free_list_generators, generator, MAX_GENERATOR_FREE_LIST_COUNT); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); } static long Nuitka_Generator_tp_hash(struct Nuitka_GeneratorObject *generator) { return generator->m_counter; } static PyObject *Nuitka_Generator_get_name(struct Nuitka_GeneratorObject *generator) { PyObject *result = generator->m_name; Py_INCREF(result); return result; } #if PYTHON_VERSION >= 0x350 static int Nuitka_Generator_set_name(struct Nuitka_GeneratorObject *generator, PyObject *value) { // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } PyObject *tmp = generator->m_name; Py_INCREF(value); generator->m_name = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Generator_get_qualname(struct Nuitka_GeneratorObject *generator) { PyObject *result = generator->m_qualname; Py_INCREF(result); return result; } static int Nuitka_Generator_set_qualname(struct Nuitka_GeneratorObject *generator, PyObject *value) { // Cannot be deleted, not be non-unicode value. if (unlikely((value == NULL) || !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } PyObject *tmp = generator->m_qualname; Py_INCREF(value); generator->m_qualname = value; Py_DECREF(tmp); return 0; } static PyObject *Nuitka_Generator_get_yieldfrom(struct Nuitka_GeneratorObject *generator) { if (generator->m_yieldfrom) { Py_INCREF(generator->m_yieldfrom); return generator->m_yieldfrom; } else { Py_INCREF(Py_None); return Py_None; } } #endif static PyObject *Nuitka_Generator_get_code(struct Nuitka_GeneratorObject *generator) { PyObject *result = (PyObject *)generator->m_code_object; Py_INCREF(result); return result; } static int Nuitka_Generator_set_code(struct Nuitka_GeneratorObject *generator, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "gi_code is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Generator_get_frame(struct Nuitka_GeneratorObject *generator) { PyObject *result; if (generator->m_frame) { result = (PyObject *)generator->m_frame; } else { result = Py_None; } Py_INCREF(result); return result; } static int Nuitka_Generator_set_frame(struct Nuitka_GeneratorObject *generator, PyObject *value) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "gi_frame is not writable in Nuitka"); return -1; } static PyObject *Nuitka_Generator_get_running(struct Nuitka_GeneratorObject *generator) { PyObject *result; /* The type of "gi_running" changed in Python3. */ #if PYTHON_VERSION < 0x300 result = PyInt_FromLong(generator->m_running); #else result = BOOL_FROM(generator->m_running != 0); Py_INCREF(result); #endif return result; } static int Nuitka_Generator_set_running(struct Nuitka_GeneratorObject *generator, PyObject *value) { #if PYTHON_VERSION < 0x300 PyObject *exception_type = PyExc_TypeError; #else PyObject *exception_type = PyExc_AttributeError; #endif #if !defined(_NUITKA_FULL_COMPAT) || PYTHON_VERSION >= 0x3a0 SET_CURRENT_EXCEPTION_TYPE0_STR(exception_type, "attribute 'gi_running' of 'generator' objects is not writable"); #else SET_CURRENT_EXCEPTION_TYPE0_STR(exception_type, "readonly attribute"); #endif return -1; } static PyGetSetDef Nuitka_Generator_getsetlist[] = { #if PYTHON_VERSION < 0x350 {(char *)"__name__", (getter)Nuitka_Generator_get_name, NULL, NULL}, #else {(char *)"__name__", (getter)Nuitka_Generator_get_name, (setter)Nuitka_Generator_set_name, NULL}, {(char *)"__qualname__", (getter)Nuitka_Generator_get_qualname, (setter)Nuitka_Generator_set_qualname, NULL}, {(char *)"gi_yieldfrom", (getter)Nuitka_Generator_get_yieldfrom, NULL, NULL}, #endif {(char *)"gi_code", (getter)Nuitka_Generator_get_code, (setter)Nuitka_Generator_set_code, NULL}, {(char *)"gi_frame", (getter)Nuitka_Generator_get_frame, (setter)Nuitka_Generator_set_frame, NULL}, {(char *)"gi_running", (getter)Nuitka_Generator_get_running, (setter)Nuitka_Generator_set_running, NULL}, {NULL}}; static PyMethodDef Nuitka_Generator_methods[] = {{"send", (PyCFunction)Nuitka_Generator_send, METH_O, NULL}, {"throw", (PyCFunction)Nuitka_Generator_throw, METH_VARARGS, NULL}, {"close", (PyCFunction)Nuitka_Generator_close, METH_NOARGS, NULL}, {NULL}}; #include PyTypeObject Nuitka_Generator_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_generator", /* tp_name */ sizeof(struct Nuitka_GeneratorObject), /* tp_basicsize */ sizeof(struct Nuitka_CellObject *), /* tp_itemsize */ (destructor)Nuitka_Generator_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)Nuitka_Generator_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Nuitka_Generator_tp_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #if PYTHON_VERSION < 0x340 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, #endif /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Generator_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(struct Nuitka_GeneratorObject, m_weakrefs), /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)Nuitka_Generator_tp_iternext, /* tp_iternext */ Nuitka_Generator_methods, /* tp_methods */ NULL, /* tp_members */ Nuitka_Generator_getsetlist, /* tp_getset */ #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) &PyGen_Type, /* tp_base */ #else 0, /* tp_base */ #endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0 /* tp_version_tag */ #if PYTHON_VERSION >= 0x340 , (destructor)Nuitka_Generator_tp_finalizer /* tp_finalize */ #endif }; #if PYTHON_VERSION >= 0x350 static void _initCompiledCoroutineTypes(); #endif #if PYTHON_VERSION >= 0x360 static void _initCompiledAsyncgenTypes(); #endif void _initCompiledGeneratorType(void) { PyType_Ready(&Nuitka_Generator_Type); // Be a paranoid subtype of uncompiled function, we want nothing shared. assert(Nuitka_Generator_Type.tp_doc != PyGen_Type.tp_doc || PyGen_Type.tp_doc == NULL); assert(Nuitka_Generator_Type.tp_traverse != PyGen_Type.tp_traverse); assert(Nuitka_Generator_Type.tp_clear != PyGen_Type.tp_clear || PyGen_Type.tp_clear == NULL); assert(Nuitka_Generator_Type.tp_richcompare != PyGen_Type.tp_richcompare || PyGen_Type.tp_richcompare == NULL); assert(Nuitka_Generator_Type.tp_iter != PyGen_Type.tp_iter || PyGen_Type.tp_iter == PyObject_SelfIter); assert(Nuitka_Generator_Type.tp_iternext != PyGen_Type.tp_iternext || PyGen_Type.tp_iternext == NULL); assert(Nuitka_Generator_Type.tp_methods != PyGen_Type.tp_methods); assert(Nuitka_Generator_Type.tp_members != PyGen_Type.tp_members); assert(Nuitka_Generator_Type.tp_getset != PyGen_Type.tp_getset); #if defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) assert(Nuitka_Generator_Type.tp_base != PyGen_Type.tp_base); #endif assert(Nuitka_Generator_Type.tp_dict != PyGen_Type.tp_dict); assert(Nuitka_Generator_Type.tp_descr_get != PyGen_Type.tp_descr_get || PyGen_Type.tp_descr_get == NULL); assert(Nuitka_Generator_Type.tp_descr_set != PyGen_Type.tp_descr_set || PyGen_Type.tp_descr_set == NULL); assert(Nuitka_Generator_Type.tp_dictoffset != PyGen_Type.tp_dictoffset || PyGen_Type.tp_dictoffset == 0); // TODO: These get changed and into the same thing, not sure what to compare against, project something // assert(Nuitka_Generator_Type.tp_init != PyGen_Type.tp_init || PyGen_Type.tp_init == NULL); // assert(Nuitka_Generator_Type.tp_alloc != PyGen_Type.tp_alloc || PyGen_Type.tp_alloc == NULL); // assert(Nuitka_Generator_Type.tp_new != PyGen_Type.tp_new || PyGen_Type.tp_new == NULL); // assert(Nuitka_Generator_Type.tp_free != PyGen_Type.tp_free || PyGen_Type.tp_free == NULL); assert(Nuitka_Generator_Type.tp_bases != PyGen_Type.tp_bases); assert(Nuitka_Generator_Type.tp_mro != PyGen_Type.tp_mro); assert(Nuitka_Generator_Type.tp_cache != PyGen_Type.tp_cache || PyGen_Type.tp_cache == NULL); assert(Nuitka_Generator_Type.tp_subclasses != PyGen_Type.tp_subclasses || PyGen_Type.tp_cache == NULL); assert(Nuitka_Generator_Type.tp_weaklist != PyGen_Type.tp_weaklist); assert(Nuitka_Generator_Type.tp_del != PyGen_Type.tp_del || PyGen_Type.tp_del == NULL); #if PYTHON_VERSION >= 0x340 assert(Nuitka_Generator_Type.tp_finalize != PyGen_Type.tp_finalize || PyGen_Type.tp_finalize == NULL); #endif #if PYTHON_VERSION >= 0x350 // Also initialize coroutines if necessary _initCompiledCoroutineTypes(); #endif #if PYTHON_VERSION >= 0x360 // Also initialize asyncgen if necessary _initCompiledAsyncgenTypes(); #endif } PyObject *Nuitka_Generator_New(generator_code code, PyObject *module, PyObject *name, #if PYTHON_VERSION >= 0x350 PyObject *qualname, #endif PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size) { struct Nuitka_GeneratorObject *result; // TODO: Change the var part of the type to 1 maybe Py_ssize_t full_size = closure_given + (heap_storage_size + sizeof(void *) - 1) / sizeof(void *); // Macro to assign result memory from GC or free list. allocateFromFreeList(free_list_generators, struct Nuitka_GeneratorObject, Nuitka_Generator_Type, full_size); // For quicker access of generator heap. result->m_heap_storage = &result->m_closure[closure_given]; assert(result != NULL); CHECK_OBJECT(result); assert(Py_SIZE(result) >= closure_given); result->m_code = (void *)code; CHECK_OBJECT(module); result->m_module = module; CHECK_OBJECT(name); result->m_name = name; Py_INCREF(name); #if PYTHON_VERSION >= 0x350 // The "qualname" defaults to NULL for most compact C code. if (qualname == NULL) { qualname = name; } CHECK_OBJECT(qualname); result->m_qualname = qualname; Py_INCREF(qualname); #endif #if PYTHON_VERSION >= 0x300 result->m_yieldfrom = NULL; #endif memcpy(&result->m_closure[0], closure, closure_given * sizeof(struct Nuitka_CellObject *)); result->m_closure_given = closure_given; result->m_weakrefs = NULL; result->m_status = status_Unused; result->m_running = false; result->m_yield_return_index = 0; #if PYTHON_VERSION >= 0x300 result->m_returned = NULL; #endif result->m_frame = NULL; result->m_code_object = code_object; #if PYTHON_VERSION >= 0x370 result->m_exc_state.exc_type = NULL; result->m_exc_state.exc_value = NULL; result->m_exc_state.exc_traceback = NULL; #endif static long Nuitka_Generator_counter = 0; result->m_counter = Nuitka_Generator_counter++; Nuitka_GC_Track(result); return (PyObject *)result; } static PyObject *_EMPTY_GENERATOR_CONTEXT(struct Nuitka_GeneratorObject *generator, PyObject *yield_return_value) { return NULL; } PyObject *Nuitka_Generator_NewEmpty(PyObject *module, PyObject *name, #if PYTHON_VERSION >= 0x350 PyObject *qualname, #endif PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given) { return Nuitka_Generator_New(_EMPTY_GENERATOR_CONTEXT, module, name, #if PYTHON_VERSION >= 0x350 qualname, #endif code_object, closure, closure_given, 0); } // Chain coroutine code to generator code, as it uses same functions, and then we can // have some things static if both are in the same compilation unit. This also loads // the asyncgen for 3.6 and higher. #if PYTHON_VERSION >= 0x350 #include "CompiledCoroutineType.c" #endif // Chain frames to generator and asyncgen code, as they need to close them with access // to best functions. #include "CompiledFrameType.c"Nuitka-0.6.19.1/nuitka/build/static_src/HelpersBuiltin.c0000600000372100037210000006152514166627112030125 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For calling built-ins, calls it and uses keyword dictionary if necessary. * * This helper simplifies calling built-ins with optional arguments that can * be given as keyword arguments. We basically re-construct the minimal call * using keywords here. This obviously is for inefficient calls to the original * built-in and should be avoided. * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif static PyObject *CALL_BUILTIN_KW_ARGS(PyObject *callable, PyObject **args, char const **arg_names, int max_args) { int i = 0; while (i < max_args) { if (args[i] == NULL) break; CHECK_OBJECT(args[i]); i++; } int usable_args = i; PyObject *kw_dict = NULL; while (i < max_args) { if (args[i] != NULL) { CHECK_OBJECT(args[i]); if (kw_dict == NULL) { kw_dict = PyDict_New(); } int res = PyDict_SetItemString(kw_dict, arg_names[i], args[i]); assert(res == 0); } i++; } PyObject *args_tuple = PyTuple_New(usable_args); for (i = 0; i < usable_args; i++) { PyTuple_SET_ITEM(args_tuple, i, args[i]); Py_INCREF(args[i]); } PyObject *result = CALL_FUNCTION(callable, args_tuple, kw_dict); Py_XDECREF(kw_dict); Py_DECREF(args_tuple); return result; } /** The "compile" built-in. * */ NUITKA_DEFINE_BUILTIN(compile) #if PYTHON_VERSION < 0x300 PyObject *COMPILE_CODE(PyObject *source_code, PyObject *file_name, PyObject *mode, PyObject *flags, PyObject *dont_inherit) #else PyObject *COMPILE_CODE(PyObject *source_code, PyObject *file_name, PyObject *mode, PyObject *flags, PyObject *dont_inherit, PyObject *optimize) #endif { // May be a source, but also could already be a compiled object, in which // case this should just return it. if (PyCode_Check(source_code)) { Py_INCREF(source_code); return source_code; } PyObject *pos_args = PyTuple_New(3); PyTuple_SET_ITEM(pos_args, 0, source_code); Py_INCREF(source_code); PyTuple_SET_ITEM(pos_args, 1, file_name); Py_INCREF(file_name); PyTuple_SET_ITEM(pos_args, 2, mode); Py_INCREF(mode); PyObject *kw_args = NULL; if (flags != NULL) { if (kw_args == NULL) kw_args = PyDict_New(); PyDict_SetItemString(kw_args, "flags", flags); } if (dont_inherit != NULL) { if (kw_args == NULL) kw_args = PyDict_New(); PyDict_SetItemString(kw_args, "dont_inherit", dont_inherit); } #if PYTHON_VERSION >= 0x300 if (optimize != NULL) { if (kw_args == NULL) kw_args = PyDict_New(); PyDict_SetItemString(kw_args, "optimize", optimize); } #endif NUITKA_ASSIGN_BUILTIN(compile); PyObject *result = CALL_FUNCTION(NUITKA_ACCESS_BUILTIN(compile), pos_args, kw_args); Py_DECREF(pos_args); Py_XDECREF(kw_args); return result; } /** * Helper used to deal with exec statement */ #if PYTHON_VERSION < 0x300 bool EXEC_FILE_ARG_HANDLING(PyObject **prog, PyObject **name) { CHECK_OBJECT(*prog); CHECK_OBJECT(*name); if (PyFile_Check(*prog)) { PyObject *old = *name; *name = PyFile_Name(*prog); Py_INCREF(*name); Py_DECREF(old); if (unlikely(*name == NULL)) { return false; } old = *prog; *prog = CALL_METHOD_NO_ARGS(*prog, const_str_plain_read); Py_DECREF(old); if (unlikely(*prog == NULL)) { return false; } } return true; } #endif /** * The "eval" implementation, used for "exec" too. */ PyObject *EVAL_CODE(PyObject *code, PyObject *globals, PyObject *locals) { CHECK_OBJECT(code); CHECK_OBJECT(globals); CHECK_OBJECT(locals); if (PyDict_Check(globals) == 0) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "exec: arg 2 must be a dictionary or None"); return NULL; } // TODO: Our re-formulation prevents this externally, doesn't it. if (locals == Py_None) { locals = globals; } if (PyMapping_Check(locals) == 0) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "exec: arg 3 must be a mapping or None"); return NULL; } // Set the __builtins__ in globals, it is expected to be present. if (PyDict_Check(globals) && DICT_HAS_ITEM(globals, const_str_plain___builtins__) == 0) { if (PyDict_SetItem(globals, const_str_plain___builtins__, (PyObject *)builtin_module) != 0) { return NULL; } } #if PYTHON_VERSION < 0x300 PyObject *result = PyEval_EvalCode((PyCodeObject *)code, globals, locals); #else PyObject *result = PyEval_EvalCode(code, globals, locals); #endif if (unlikely(result == NULL)) { return NULL; } return result; } /** The "open" built-in. * * Different for Python2 and Python3, the later has more arguments and * both accept keyword arguments. * **/ NUITKA_DEFINE_BUILTIN(open); #if PYTHON_VERSION < 0x300 PyObject *BUILTIN_OPEN(PyObject *file_name, PyObject *mode, PyObject *buffering) { NUITKA_ASSIGN_BUILTIN(open); PyObject *args[] = {file_name, mode, buffering}; char const *arg_names[] = {"name", "mode", "buffering"}; return CALL_BUILTIN_KW_ARGS(NUITKA_ACCESS_BUILTIN(open), args, arg_names, 3); } #else PyObject *BUILTIN_OPEN(PyObject *file_name, PyObject *mode, PyObject *buffering, PyObject *encoding, PyObject *errors, PyObject *newline, PyObject *closefd, PyObject *opener) { NUITKA_ASSIGN_BUILTIN(open); PyObject *args[] = {file_name, mode, buffering, encoding, errors, newline, closefd, opener}; char const *arg_names[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener"}; return CALL_BUILTIN_KW_ARGS(NUITKA_ACCESS_BUILTIN(open), args, arg_names, 8); } #endif /** The "staticmethod" built-in. * **/ NUITKA_DEFINE_BUILTIN(staticmethod) PyObject *BUILTIN_STATICMETHOD(PyObject *value) { NUITKA_ASSIGN_BUILTIN(staticmethod); return CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(staticmethod), value); } /** The "classmethod" built-in. * **/ NUITKA_DEFINE_BUILTIN(classmethod) PyObject *BUILTIN_CLASSMETHOD(PyObject *value) { NUITKA_ASSIGN_BUILTIN(classmethod); return CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(classmethod), value); } #if PYTHON_VERSION >= 0x300 /** The "bytes" built-in. * * Only for Python3. There is not BYTES_BUILTIN1 yet, this only delegates to * the actual built-in which is wasteful. TODO: Have dedicated implementation * for this. * **/ NUITKA_DEFINE_BUILTIN(bytes); PyObject *BUILTIN_BYTES1(PyObject *value) { NUITKA_ASSIGN_BUILTIN(bytes); return CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(bytes), value); } PyObject *BUILTIN_BYTES3(PyObject *value, PyObject *encoding, PyObject *errors) { NUITKA_ASSIGN_BUILTIN(bytes); PyObject *args[] = {value, encoding, errors}; char const *arg_names[] = {"value", "encoding", "errors"}; return CALL_BUILTIN_KW_ARGS(NUITKA_ACCESS_BUILTIN(bytes), args, arg_names, 3); } #endif /** The "bin" built-in. * **/ PyObject *BUILTIN_BIN(PyObject *value) { // Note: I don't really know why "oct" and "hex" don't use this as well. PyObject *result = PyNumber_ToBase(value, 2); if (unlikely(result == NULL)) { return NULL; } return result; } /** The "oct" built-in. * **/ PyObject *BUILTIN_OCT(PyObject *value) { #if PYTHON_VERSION >= 0x300 PyObject *result = PyNumber_ToBase(value, 8); if (unlikely(result == NULL)) { return NULL; } return result; #else if (unlikely(value == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "oct() argument can't be converted to oct"); return NULL; } PyNumberMethods *nb = Py_TYPE(value)->tp_as_number; if (unlikely(nb == NULL || nb->nb_oct == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "oct() argument can't be converted to oct"); return NULL; } PyObject *result = (*nb->nb_oct)(value); if (result) { if (unlikely(!PyString_Check(result))) { PyErr_Format(PyExc_TypeError, "__oct__ returned non-string (type %s)", Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } } return result; #endif } /** The "hex" built-in. * **/ PyObject *BUILTIN_HEX(PyObject *value) { #if PYTHON_VERSION >= 0x300 PyObject *result = PyNumber_ToBase(value, 16); if (unlikely(result == NULL)) { return NULL; } return result; #else if (unlikely(value == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "hex() argument can't be converted to hex"); return NULL; } PyNumberMethods *nb = Py_TYPE(value)->tp_as_number; if (unlikely(nb == NULL || nb->nb_hex == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "hex() argument can't be converted to hex"); return NULL; } PyObject *result = (*nb->nb_hex)(value); if (likely(result)) { if (unlikely(!PyString_Check(result))) { PyErr_Format(PyExc_TypeError, "__hex__ returned non-string (type %s)", Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } } return result; #endif } /** The "hash" built-in. * **/ static void SET_HASH_NOT_IMPLEMENTED_ERROR(PyObject *value) { // TODO: Use our own formatting code. PyErr_Format(PyExc_TypeError, "unhashable type: '%s'", Py_TYPE(value)->tp_name); } #if PYTHON_VERSION < 0x300 // Helper to make hash from pointer value, compatible with CPython. static long Nuitka_HashFromPointer(void *p) { size_t y = (size_t)p; y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); long x = (long)y; if (unlikely(x == -1)) { x = -2; } return x; } #endif PyObject *BUILTIN_HASH(PyObject *value) { PyTypeObject *type = Py_TYPE(value); if (likely(type->tp_hash != NULL)) { Py_hash_t hash = (*type->tp_hash)(value); if (unlikely(hash == -1)) { return NULL; } #if PYTHON_VERSION < 0x300 return PyInt_FromLong(hash); #else return PyLong_FromSsize_t(hash); #endif } #if PYTHON_VERSION < 0x300 if (likely(type->tp_compare == NULL && RICHCOMPARE(type) == NULL)) { Py_hash_t hash = Nuitka_HashFromPointer(value); return PyInt_FromLong(hash); } #endif SET_HASH_NOT_IMPLEMENTED_ERROR(value); return NULL; } Py_hash_t HASH_VALUE_WITH_ERROR(PyObject *value) { PyTypeObject *type = Py_TYPE(value); if (likely(type->tp_hash != NULL)) { Py_hash_t hash = (*type->tp_hash)(value); return hash; } #if PYTHON_VERSION < 0x300 if (likely(type->tp_compare == NULL && RICHCOMPARE(type) == NULL)) { return Nuitka_HashFromPointer(value); } #endif SET_HASH_NOT_IMPLEMENTED_ERROR(value); return -1; } Py_hash_t HASH_VALUE_WITHOUT_ERROR(PyObject *value) { PyTypeObject *type = Py_TYPE(value); if (likely(type->tp_hash != NULL)) { Py_hash_t hash = (*type->tp_hash)(value); if (unlikely(hash == -1)) { CLEAR_ERROR_OCCURRED(); } return hash; } #if PYTHON_VERSION < 0x300 if (likely(type->tp_compare == NULL && RICHCOMPARE(type) == NULL)) { return Nuitka_HashFromPointer(value); } #endif CLEAR_ERROR_OCCURRED(); return -1; } /** The "bytearray" built-in. * * These should be more in-lined maybe, as a lot of checks are not necessary * and the error checking for the 3 arguments variant may even not be enough, * as it could be keyword arguments. * **/ PyObject *BUILTIN_BYTEARRAY1(PyObject *value) { PyObject *result = PyByteArray_FromObject(value); if (unlikely(result == NULL)) { return NULL; } return result; } NUITKA_DEFINE_BUILTIN(bytearray) PyObject *BUILTIN_BYTEARRAY3(PyObject *string, PyObject *encoding, PyObject *errors) { CHECK_OBJECT(string); CHECK_OBJECT(encoding); NUITKA_ASSIGN_BUILTIN(bytearray); if (errors == NULL) { PyObject *args[] = {string, encoding}; PyObject *result = CALL_FUNCTION_WITH_ARGS2(NUITKA_ACCESS_BUILTIN(bytearray), args); return result; } else { PyObject *args[] = {string, encoding, errors}; PyObject *result = CALL_FUNCTION_WITH_ARGS3(NUITKA_ACCESS_BUILTIN(bytearray), args); return result; } } /** The "iter" built-in. * * This comes in two flavors, with one or two arguments. The second one * creates a "calliterobject" that is private to CPython. We define it here * for ourselves. The one argument version is in headers for in-lining of * the code. * **/ // From CPython: typedef struct { /* Python object folklore: */ PyObject_HEAD PyObject *it_callable; PyObject *it_sentinel; } calliterobject; PyObject *BUILTIN_ITER2(PyObject *callable, PyObject *sentinel) { calliterobject *result = PyObject_GC_New(calliterobject, &PyCallIter_Type); if (unlikely(result == NULL)) { return NULL; } // Note: References were taken at call site already. result->it_callable = callable; Py_INCREF(callable); result->it_sentinel = sentinel; Py_INCREF(sentinel); Nuitka_GC_Track(result); return (PyObject *)result; } /** The "type" built-in. * * This comes in two flavors, one being the detection of a values type, * and 3 argument variant creates a new type. * **/ PyObject *BUILTIN_TYPE1(PyObject *arg) { PyObject *result = (PyObject *)Py_TYPE(arg); Py_INCREF(result); return result; } PyObject *BUILTIN_TYPE3(PyObject *module_name, PyObject *name, PyObject *bases, PyObject *dict) { PyObject *pos_args = PyTuple_New(3); PyTuple_SET_ITEM(pos_args, 0, name); Py_INCREF(name); PyTuple_SET_ITEM(pos_args, 1, bases); Py_INCREF(bases); PyTuple_SET_ITEM(pos_args, 2, dict); Py_INCREF(dict); PyObject *result = PyType_Type.tp_new(&PyType_Type, pos_args, NULL); if (unlikely(result == NULL)) { Py_DECREF(pos_args); return NULL; } PyTypeObject *type = Py_TYPE(result); if (likely(PyType_IsSubtype(type, &PyType_Type))) { if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { int res = type->tp_init(result, pos_args, NULL); if (unlikely(res < 0)) { Py_DECREF(pos_args); Py_DECREF(result); return NULL; } } } Py_DECREF(pos_args); int res = PyObject_SetAttr(result, const_str_plain___module__, module_name); if (res < 0) { return NULL; } return result; } /** The "super" built-in. * * This uses a private structure "superobject" that we declare here too. * **/ typedef struct { /* Python object folklore: */ PyObject_HEAD PyTypeObject *type; PyObject *obj; PyTypeObject *obj_type; } superobject; PyObject *BUILTIN_SUPER2(PyObject *type, PyObject *object) { CHECK_OBJECT(type); CHECK_OBJECT_X(object); if (unlikely(PyType_Check(type) == false)) { #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE("super() argument 1 must be type, not %s", type); #elif PYTHON_VERSION < 0x352 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE("must be type, not %s", type); #else SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE("super() argument 1 must be type, not %s", type); #endif return NULL; } if (object == Py_None) { object = NULL; } PyTypeObject *obj_type = NULL; #if 0 PRINT_STRING("SUPER:"); PRINT_ITEM(type); PRINT_ITEM(object); PRINT_NEW_LINE(); #endif if (object != NULL) { if (PyType_Check(object) && PyType_IsSubtype((PyTypeObject *)object, (PyTypeObject *)type)) { obj_type = (PyTypeObject *)object; } else if (object != NULL && PyType_IsSubtype(Py_TYPE(object), (PyTypeObject *)type)) { obj_type = Py_TYPE(object); } else { PyObject *class_attr = PyObject_GetAttr(object, const_str_plain___class__); if (likely(class_attr != NULL && PyType_Check(class_attr) && (PyTypeObject *)class_attr != Py_TYPE(object) && PyType_IsSubtype((PyTypeObject *)class_attr, (PyTypeObject *)type))) { obj_type = (PyTypeObject *)class_attr; Py_DECREF(class_attr); } else { Py_XDECREF(class_attr); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "super(type, obj): obj must be an instance or subtype of type"); return NULL; } } } superobject *result = PyObject_GC_New(superobject, &PySuper_Type); assert(result); result->type = (PyTypeObject *)type; Py_INCREF(type); result->obj = object; Py_XINCREF(object); result->obj_type = obj_type; Py_XINCREF(obj_type); Nuitka_GC_Track(result); CHECK_OBJECT(result); assert(Py_TYPE(result) == &PySuper_Type); return (PyObject *)result; } PyObject *BUILTIN_SUPER0(PyObject *type, PyObject *object) { CHECK_OBJECT(type); superobject *result = PyObject_GC_New(superobject, &PySuper_Type); assert(result); if (object == Py_None) { object = NULL; } if (unlikely(PyType_Check(type) == false)) { PyErr_Format(PyExc_RuntimeError, "super(): __class__ is not a type (%s)", Py_TYPE(type)->tp_name); return NULL; } result->type = (PyTypeObject *)type; Py_INCREF(type); if (object) { result->obj = object; Py_INCREF(object); if (PyType_Check(object) && PyType_IsSubtype((PyTypeObject *)object, (PyTypeObject *)type)) { result->obj_type = (PyTypeObject *)object; Py_INCREF(object); } else if (PyType_IsSubtype(Py_TYPE(object), (PyTypeObject *)type)) { result->obj_type = Py_TYPE(object); Py_INCREF(result->obj_type); } else { PyObject *class_attr = PyObject_GetAttr(object, const_str_plain___class__); if (likely(class_attr != NULL && PyType_Check(class_attr) && (PyTypeObject *)class_attr != Py_TYPE(object))) { result->obj_type = (PyTypeObject *)class_attr; } else { if (class_attr == NULL) { CLEAR_ERROR_OCCURRED(); } else { Py_DECREF(class_attr); } SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "super(type, obj): obj must be an instance or subtype of type"); return NULL; } } } else { result->obj = NULL; result->obj_type = NULL; } Nuitka_GC_Track(result); CHECK_OBJECT(result); assert(Py_TYPE(result) == &PySuper_Type); return (PyObject *)result; } /** The "callable" built-in. * **/ PyObject *BUILTIN_CALLABLE(PyObject *value) { int res = PyCallable_Check(value); PyObject *result = BOOL_FROM(res != 0); Py_INCREF(result); return result; } /* The "getattr" built-in with default value. * * We might want to split it off for a variant without default value. * **/ PyObject *BUILTIN_GETATTR(PyObject *object, PyObject *attribute, PyObject *default_value) { #if PYTHON_VERSION < 0x300 if (PyUnicode_Check(attribute)) { attribute = _PyUnicode_AsDefaultEncodedString(attribute, NULL); if (unlikely(attribute == NULL)) { return NULL; } } if (unlikely(!PyString_Check(attribute))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "getattr(): attribute name must be string"); return NULL; } #else if (!PyUnicode_Check(attribute)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "getattr(): attribute name must be string"); return NULL; } #endif PyObject *result = PyObject_GetAttr(object, attribute); if (result == NULL) { if (default_value != NULL && EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_AttributeError)) { CLEAR_ERROR_OCCURRED(); Py_INCREF(default_value); return default_value; } else { return NULL; } } else { return result; } } /** The "setattr" built-in. * **/ PyObject *BUILTIN_SETATTR(PyObject *object, PyObject *attribute, PyObject *value) { int res = PyObject_SetAttr(object, attribute, value); if (unlikely(res < 0)) { return NULL; } // No reference returned. return Py_None; } PyObject *BUILTIN_INT2(PyObject *value, PyObject *base) { #if PYTHON_VERSION < 0x340 long base_int = PyInt_AsLong(base); #else Py_ssize_t base_int = PyNumber_AsSsize_t(base, NULL); #endif if (unlikely(base_int == -1)) { PyObject *error = GET_ERROR_OCCURRED(); if (likely(error)) { #if PYTHON_VERSION >= 0x300 if (EXCEPTION_MATCH_BOOL_SINGLE(error, PyExc_OverflowError)) { PyErr_Format(PyExc_ValueError, #if PYTHON_VERSION < 0x324 "int() arg 2 must be >= 2 and <= 36" #elif PYTHON_VERSION < 0x364 "int() base must be >= 2 and <= 36" #else "int() base must be >= 2 and <= 36, or 0" #endif ); } #endif return NULL; } } #if PYTHON_VERSION >= 0x300 if (unlikely((base_int != 0 && base_int < 2) || base_int > 36)) { PyErr_Format(PyExc_ValueError, #if PYTHON_VERSION < 0x324 "int() arg 2 must be >= 2 and <= 36" #elif PYTHON_VERSION < 0x364 "int() base must be >= 2 and <= 36" #else "int() base must be >= 2 and <= 36, or 0" #endif ); return NULL; } #endif #if PYTHON_VERSION < 0x300 if (unlikely(!Nuitka_String_Check(value) && !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "int() can't convert non-string with explicit base"); return NULL; } char *value_str = Nuitka_String_AsString(value); if (unlikely(value_str == NULL)) { return NULL; } PyObject *result = PyInt_FromString(value_str, NULL, base_int); if (unlikely(result == NULL)) { return NULL; } return result; #else if (PyUnicode_Check(value)) { return PyLong_FromUnicodeObject(value, (int)base_int); } else if (PyBytes_Check(value) || PyByteArray_Check(value)) { // Check for "NUL" as PyLong_FromString has no length parameter, Py_ssize_t size = Py_SIZE(value); char const *value_str; if (PyByteArray_Check(value)) { value_str = PyByteArray_AS_STRING(value); } else { value_str = PyBytes_AS_STRING(value); } PyObject *result = NULL; if (size != 0 && strlen(value_str) == (size_t)size) { result = PyLong_FromString((char *)value_str, NULL, (int)base_int); } if (unlikely(result == NULL)) { PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", base_int, value); return NULL; } return result; } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "int() can't convert non-string with explicit base"); return NULL; } #endif } #if PYTHON_VERSION < 0x300 // Note: Python3 uses TO_INT2 function. PyObject *BUILTIN_LONG2(PyObject *value, PyObject *base) { long base_int = PyInt_AsLong(base); if (unlikely(base_int == -1)) { if (likely(ERROR_OCCURRED())) { return NULL; } } if (unlikely(!Nuitka_String_Check(value) && !PyUnicode_Check(value))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "long() can't convert non-string with explicit base"); return NULL; } char *value_str = Nuitka_String_AsString(value); if (unlikely(value_str == NULL)) { return NULL; } PyObject *result = PyLong_FromString(value_str, NULL, base_int); if (unlikely(result == NULL)) { return NULL; } return result; } #endif Nuitka-0.6.19.1/nuitka/build/static_src/MetaPathBasedLoader.c0000600000372100037210000015333514166627112030766 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This implements the loading of C compiled modules and shared library // extension modules bundled for standalone mode. // This is achieved mainly by registered a "sys.meta_path" loader, that then // gets asked for module names, and responds if knows about one. It's fed by // a table created at compile time. // The nature and use of these 2 loaded module kinds is very different, but // having them as distinct loaders would only require to duplicate the search // and registering of stuff. #include #ifdef _WIN32 #undef SEP #define SEP '\\' #endif #include "nuitka/prelude.h" #include "nuitka/unfreezing.h" #ifdef _WIN32 #include #endif extern PyTypeObject Nuitka_Loader_Type; struct Nuitka_LoaderObject { /* Python object folklore: */ PyObject_HEAD /* The loader entry, to know what was loaded exactly. */ struct Nuitka_MetaPathBasedLoaderEntry const *m_loader_entry; }; #ifdef _NUITKA_EXE static inline bool isVerbose(void) { return Py_VerboseFlag != 0; } #elif _NUITKA_SYSFLAG_VERBOSE static inline bool isVerbose(void) { return true; } #else static inline bool isVerbose(void) { return false; } #endif static struct Nuitka_MetaPathBasedLoaderEntry *loader_entries = NULL; static bool hasFrozenModule(char const *name) { for (struct _frozen const *p = PyImport_FrozenModules;; p++) { if (p->name == NULL) { return false; } if (strcmp(p->name, name) == 0) { break; } } return true; } static char *appendModulenameAsPath(char *buffer, char const *module_name, size_t buffer_size) { // Skip to the end while (*buffer != 0) { buffer++; } while (*module_name) { if (buffer_size < 1) { abort(); } if (*module_name == '.') { *buffer++ = SEP; module_name++; } else { *buffer++ = *module_name++; } buffer_size -= 1; } *buffer = 0; return buffer; } #if defined(_WIN32) && defined(_NUITKA_STANDALONE) static void appendModulenameAsPathW(wchar_t *buffer, char const *module_name, size_t buffer_size) { // Skip to the end while (*buffer != 0) { buffer++; } while (*module_name) { char c = *module_name++; if (c == '.') { c = SEP; } appendCharSafeW(buffer, c, buffer_size); } } #endif // TODO: This updates the wrong absolute path. We ought to change it to // the "module_path_name" at the time of writing it, then we save a few // bytes in the blob, and don't have to create that string here. #ifdef _NUITKA_STANDALONE static void patchCodeObjectPaths(PyCodeObject *code_object, PyObject *module_path) { code_object->co_filename = module_path; Py_INCREF(module_path); Py_ssize_t nconsts = PyTuple_GET_SIZE(code_object->co_consts); for (int i = 0; i < nconsts; i++) { PyObject *constant = PyTuple_GET_ITEM(code_object->co_consts, i); if (PyCode_Check(constant)) { patchCodeObjectPaths((PyCodeObject *)constant, module_path); } } } #endif NUITKA_MAY_BE_UNUSED static PyObject *MAKE_RELATIVE_PATH_FROM_NAME(char const *name, bool is_package) { char buffer[MAXPATHLEN + 1] = {0}; appendModulenameAsPath(buffer, name, sizeof(buffer)); if (is_package) { appendCharSafe(buffer, SEP, sizeof(buffer)); appendStringSafe(buffer, "__init__.py", sizeof(buffer)); } else { appendStringSafe(buffer, ".py", sizeof(buffer)); } PyObject *module_path_entry_base = Nuitka_String_FromString(buffer); PyObject *result = MAKE_RELATIVE_PATH(module_path_entry_base); Py_DECREF(module_path_entry_base); return result; } static PyObject *loadModuleFromCodeObject(PyObject *module, PyCodeObject *code_object, char const *name, bool is_package) { assert(code_object != NULL); // TODO: This should not actually trigger, but it does. // assert(PyDict_GetItemString(modules, name) == NULL); bool b_res = Nuitka_SetModuleString(name, module); assert(b_res != false); char buffer[MAXPATHLEN + 1] = {0}; PyObject *module_path_entry = NULL; if (is_package) { appendModulenameAsPath(buffer, name, sizeof(buffer)); PyObject *module_path_entry_base = Nuitka_String_FromString(buffer); module_path_entry = MAKE_RELATIVE_PATH(module_path_entry_base); Py_DECREF(module_path_entry_base); appendCharSafe(buffer, SEP, sizeof(buffer)); appendStringSafe(buffer, "__init__.py", sizeof(buffer)); } else { appendModulenameAsPath(buffer, name, sizeof(buffer)); appendStringSafe(buffer, ".py", sizeof(buffer)); } PyObject *module_path_name = Nuitka_String_FromString(buffer); PyObject *module_path = MAKE_RELATIVE_PATH(module_path_name); Py_DECREF(module_path_name); if (is_package) { /* Set __path__ properly, unlike frozen module importer does. */ PyObject *path_list = PyList_New(1); if (unlikely(path_list == NULL)) return NULL; int res = PyList_SetItem(path_list, 0, module_path_entry); if (unlikely(res != 0)) { return NULL; } Py_INCREF(module_path_entry); res = PyObject_SetAttr(module, const_str_plain___path__, path_list); if (unlikely(res != 0)) { return NULL; } Py_DECREF(path_list); PyObject *module_name = PyObject_GetAttr(module, const_str_plain___name__); CHECK_OBJECT(module_name); res = PyObject_SetAttr(module, const_str_plain___package__, module_name); if (unlikely(res != 0)) { return NULL; } } #ifdef _NUITKA_STANDALONE patchCodeObjectPaths(code_object, module_path); #endif PGO_onModuleEntered(name); module = PyImport_ExecCodeModuleEx((char *)name, (PyObject *)code_object, Nuitka_String_AsString(module_path)); PGO_onModuleExit(name, module == NULL); Py_DECREF(module_path); return module; } static struct Nuitka_MetaPathBasedLoaderEntry *findEntry(char const *name) { struct Nuitka_MetaPathBasedLoaderEntry *current = loader_entries; assert(current); while (current->name != NULL) { if ((current->flags & NUITKA_TRANSLATED_FLAG) != 0) { current->name = UNTRANSLATE(current->name); current->flags -= NUITKA_TRANSLATED_FLAG; } if (strcmp(name, current->name) == 0) { return current; } current++; } return NULL; } #ifndef _NUITKA_STANDALONE static struct Nuitka_MetaPathBasedLoaderEntry *findContainingPackageEntry(char const *name) { struct Nuitka_MetaPathBasedLoaderEntry *current = loader_entries; // Consider the package name of the searched entry. char const *package_name_end = strrchr(name, '.'); if (package_name_end == NULL) { return NULL; } size_t length = package_name_end - name; while (current->name != NULL) { if ((current->flags & NUITKA_TRANSLATED_FLAG) != 0) { current->name = UNTRANSLATE(current->name); current->flags -= NUITKA_TRANSLATED_FLAG; } if ((current->flags & NUITKA_PACKAGE_FLAG) != 0) { if (strlen(current->name) == length && strncmp(name, current->name, length) == 0) { return current; } } current++; } return NULL; } static PyObject *getFileList(PyObject *dirname) { static PyObject *listdir_func = NULL; if (listdir_func == NULL) { PyObject *os_module = PyImport_ImportModule("os"); listdir_func = PyObject_GetAttrString(os_module, "listdir"); } if (unlikely(listdir_func == NULL)) { return NULL; } return CALL_FUNCTION_WITH_SINGLE_ARG(listdir_func, dirname); } #if PYTHON_VERSION < 0x300 static PyObject *_getImportingSuffixesByPriority(int kind) { static PyObject *result = NULL; if (result == NULL) { result = PyList_New(0); PyObject *imp_module = PyImport_ImportModule("imp"); PyObject *get_suffixes_func = PyObject_GetAttrString(imp_module, "get_suffixes"); PyObject *suffix_list = CALL_FUNCTION_NO_ARGS(get_suffixes_func); for (int i = 0; i < PyList_GET_SIZE(suffix_list); i++) { PyObject *module_kind = PyTuple_GET_ITEM(PyList_GET_ITEM(suffix_list, i), 2); if (PyInt_AsLong(module_kind) == kind) { LIST_APPEND0(result, PyTuple_GET_ITEM(PyList_GET_ITEM(suffix_list, i), 0)); } } Py_DECREF(suffix_list); } return result; } #endif static PyObject *getExtensionModuleSuffixesByPriority() { static PyObject *result = NULL; if (result == NULL) { #if PYTHON_VERSION < 0x300 result = _getImportingSuffixesByPriority(3); #else static PyObject *machinery_module = NULL; if (machinery_module == NULL) { machinery_module = PyImport_ImportModule("importlib.machinery"); } result = PyObject_GetAttrString(machinery_module, "EXTENSION_SUFFIXES"); #endif } CHECK_OBJECT(result); return result; } static PyObject *installed_extension_modules = NULL; static bool scanModuleInPackagePath(PyObject *module_name, char const *parent_module_name) { PyObject *sys_modules = PyImport_GetModuleDict(); PyObject *parent_module = PyDict_GetItemString(sys_modules, parent_module_name); CHECK_OBJECT(parent_module); PyObject *parent_path = PyObject_GetAttr(parent_module, const_str_plain___path__); // Accept that it might be deleted. if (parent_path == NULL || !PyList_Check(parent_path)) { return false; } PyObject *candidates = PyList_New(0); // Search only relative to the parent name of course. char const *module_relname_str = Nuitka_String_AsString(module_name) + strlen(parent_module_name) + 1; Py_ssize_t parent_path_size = PyList_GET_SIZE(parent_path); for (Py_ssize_t i = 0; i < parent_path_size; i += 1) { PyObject *path_element = PyList_GET_ITEM(parent_path, i); PyObject *filenames_list = getFileList(path_element); if (filenames_list == NULL) { DROP_ERROR_OCCURRED(); continue; } Py_ssize_t filenames_list_size = PyList_GET_SIZE(filenames_list); for (Py_ssize_t j = 0; j < filenames_list_size; j += 1) { PyObject *filename = PyList_GET_ITEM(filenames_list, j); if (Nuitka_String_CheckExact(filename)) { char const *filename_str = Nuitka_String_AsString(filename); if (strncmp(filename_str, module_relname_str, strlen(module_relname_str)) == 0 && filename_str[strlen(module_relname_str)] == '.') { LIST_APPEND1(candidates, PyTuple_Pack(2, path_element, filename)); } } } } #if 0 PRINT_STRING("CANDIDATES:"); PRINT_STRING(Nuitka_String_AsString(module_name)); PRINT_STRING(module_relname_str); PRINT_ITEM(candidates); PRINT_NEW_LINE(); #endif // Look up C-extension suffixes, these are used with highest priority. PyObject *suffix_list = getExtensionModuleSuffixesByPriority(); bool result = false; for (Py_ssize_t i = 0; i < PyList_GET_SIZE(suffix_list); i += 1) { PyObject *suffix = PyList_GET_ITEM(suffix_list, i); char const *suffix_str = Nuitka_String_AsString(suffix); for (Py_ssize_t j = 0; j < PyList_GET_SIZE(candidates); j += 1) { PyObject *entry = PyList_GET_ITEM(candidates, j); PyObject *directory = PyTuple_GET_ITEM(entry, 0); PyObject *candidate = PyTuple_GET_ITEM(entry, 1); char const *candidate_str = Nuitka_String_AsString(candidate); if (strcmp(suffix_str, candidate_str + strlen(module_relname_str)) == 0) { PyObject *fullpath = JOIN_PATH2(directory, candidate); if (installed_extension_modules == NULL) { installed_extension_modules = PyDict_New(); } // Force path to unicode, to have easier consumption, as we need a wchar_t or char * // from it later, and we don't want to test there. #if PYTHON_VERSION < 0x300 && defined(_WIN32) PyObject *tmp = PyUnicode_FromObject(fullpath); Py_DECREF(fullpath); fullpath = tmp; #endif DICT_SET_ITEM(installed_extension_modules, module_name, fullpath); result = true; break; } } } Py_DECREF(candidates); return result; } #ifdef _WIN32 static PyObject *callIntoShlibModule(char const *full_name, const wchar_t *filename); #else static PyObject *callIntoShlibModule(char const *full_name, const char *filename); #endif static PyObject *callIntoInstalledShlibModule(PyObject *module_name, PyObject *extension_module_filename) { #if _WIN32 // We can rely on unicode object to be there in case of Windows, to have an easier time to // create the string needed. assert(PyUnicode_CheckExact(extension_module_filename)); #if PYTHON_VERSION < 0x300 wchar_t const *extension_module_filename_str = PyUnicode_AS_UNICODE(extension_module_filename); #else wchar_t const *extension_module_filename_str = PyUnicode_AsWideCharString(extension_module_filename, NULL); #endif #else char const *extension_module_filename_str = Nuitka_String_AsString(extension_module_filename); #endif return callIntoShlibModule(Nuitka_String_AsString(module_name), extension_module_filename_str); } #endif static char *_kwlist[] = {(char *)"fullname", (char *)"unused", NULL}; static PyObject *_path_unfreezer_find_module(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module_name; PyObject *unused; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O|O:find_module", (char **)_kwlist, &module_name, &unused); if (unlikely(res == 0)) { return NULL; } char const *name = Nuitka_String_AsString(module_name); if (isVerbose()) { PySys_WriteStderr("import %s # considering responsibility (find_module)\n", name); } struct Nuitka_MetaPathBasedLoaderEntry *entry = findEntry(name); if (entry) { if (isVerbose()) { PySys_WriteStderr("import %s # claimed responsibility (compiled)\n", name); } PyObject *metapath_based_loader = (PyObject *)&Nuitka_Loader_Type; Py_INCREF(metapath_based_loader); return metapath_based_loader; } if (hasFrozenModule(name)) { if (isVerbose()) { PySys_WriteStderr("import %s # claimed responsibility (frozen)\n", name); } PyObject *metapath_based_loader = (PyObject *)&Nuitka_Loader_Type; Py_INCREF(metapath_based_loader); return metapath_based_loader; } #ifndef _NUITKA_STANDALONE entry = findContainingPackageEntry(name); if (entry != NULL) { bool result = scanModuleInPackagePath(module_name, entry->name); if (result) { PyObject *metapath_based_loader = (PyObject *)&Nuitka_Loader_Type; Py_INCREF(metapath_based_loader); return metapath_based_loader; } } #endif if (isVerbose()) { PySys_WriteStderr("import %s # denied responsibility\n", name); } Py_INCREF(Py_None); return Py_None; } static char const *_kwlist_get_data[] = {"filename", NULL}; static PyObject *_path_unfreezer_get_data(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *filename; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:get_data", (char **)_kwlist_get_data, &filename); if (unlikely(res == 0)) { return NULL; } #if PYTHON_VERSION < 0x300 PyObject *data_file = BUILTIN_OPEN(filename, const_str_plain_rb, NULL); #else PyObject *data_file = BUILTIN_OPEN(filename, const_str_plain_rb, NULL, NULL, NULL, NULL, NULL, NULL); #endif if (unlikely(data_file == NULL)) { // TODO: Issue a runtime warning maybe. return NULL; } PyObject *read_method = PyObject_GetAttr(data_file, const_str_plain_read); Py_DECREF(data_file); if (unlikely(read_method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_NO_ARGS(read_method); Py_DECREF(read_method); return result; } #if PYTHON_VERSION < 0x300 typedef void (*entrypoint_t)(void); #else typedef PyObject *(*entrypoint_t)(void); #endif #ifndef _WIN32 // Shared libraries loading. #include #endif #if PYTHON_VERSION >= 0x350 static PyObject *createModuleSpec(PyObject *module_name, bool is_package); #endif #ifdef _WIN32 static PyObject *callIntoShlibModule(char const *full_name, const wchar_t *filename) { #else static PyObject *callIntoShlibModule(char const *full_name, const char *filename) { #endif // Determine the package name and basename of the module to load. char const *dot = strrchr(full_name, '.'); char const *name; char const *package; if (dot == NULL) { package = NULL; name = full_name; } else { // The extension modules do expect it to be full name in context. package = (char *)full_name; name = dot + 1; } char entry_function_name[1024]; snprintf(entry_function_name, sizeof(entry_function_name), #if PYTHON_VERSION < 0x300 "init%s", #else "PyInit_%s", #endif name); #ifdef _WIN32 if (isVerbose()) { PySys_WriteStderr("import %s # LoadLibraryExW(\"%S\");\n", full_name, filename); } #ifndef _NUITKA_EXPERIMENTAL_DEBUG_STANDALONE unsigned int old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif HINSTANCE hDLL = LoadLibraryExW(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); #ifndef _NUITKA_EXPERIMENTAL_DEBUG_STANDALONE SetErrorMode(old_mode); #endif if (unlikely(hDLL == NULL)) { char buffer[1024]; char error_message[1024]; int size; unsigned int error_code = GetLastError(); size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error_code, 0, (LPTSTR)error_message, sizeof(error_message), NULL); // Report either way even if failed to get error message. if (size == 0) { PyOS_snprintf(buffer, sizeof(buffer), "LoadLibraryExW '%S' failed with error code %d", filename, error_code); } else { // Strip trailing newline. if (size >= 2 && error_message[size - 2] == '\r' && error_message[size - 1] == '\n') { size -= 2; error_message[size] = '\0'; } PyOS_snprintf(buffer, sizeof(buffer), "LoadLibraryExW '%S' failed: %s", filename, error_message); } SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ImportError, buffer); return NULL; } entrypoint_t entrypoint = (entrypoint_t)GetProcAddress(hDLL, entry_function_name); #else // This code would work for all versions, we are avoiding access to interpreter // structure internals of 3.8 or higher. static PyObject *dlopenflags_object = NULL; if (dlopenflags_object == NULL) { dlopenflags_object = CALL_FUNCTION_NO_ARGS(Nuitka_SysGetObject("getdlopenflags")); } int dlopenflags = PyInt_AsLong(dlopenflags_object); if (isVerbose()) { PySys_WriteStderr("import %s # dlopen(\"%s\", %x);\n", full_name, filename, dlopenflags); } void *handle = dlopen(filename, dlopenflags); if (unlikely(handle == NULL)) { const char *error = dlerror(); if (unlikely(error == NULL)) { error = "unknown dlopen() error"; } SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ImportError, error); return NULL; } entrypoint_t entrypoint = (entrypoint_t)dlsym(handle, entry_function_name); #endif assert(entrypoint); #if PYTHON_VERSION < 0x370 char *old_context = _Py_PackageContext; #else char const *old_context = _Py_PackageContext; #endif _Py_PackageContext = (char *)package; // Finally call into the DLL. PGO_onModuleEntered(full_name); #if PYTHON_VERSION < 0x300 (*entrypoint)(); #else PyObject *module = (*entrypoint)(); #endif _Py_PackageContext = old_context; #if PYTHON_VERSION < 0x300 PyObject *module = Nuitka_GetModuleString(full_name); #endif PGO_onModuleExit(name, module == NULL); if (unlikely(module == NULL)) { if (unlikely(!ERROR_OCCURRED())) { PyErr_Format(PyExc_SystemError, "dynamic module '%s' not initialized properly", full_name); } return NULL; } #if PYTHON_VERSION >= 0x300 #if PYTHON_VERSION >= 0x350 PyModuleDef *def; if (Py_TYPE(module) == &PyModuleDef_Type) { def = (PyModuleDef *)module; PyObject *full_name_obj = Nuitka_String_FromString(full_name); PyObject *spec = createModuleSpec(full_name_obj, false); module = PyModule_FromDefAndSpec(def, spec); Py_DECREF(spec); if (unlikely(module == NULL)) { PyErr_Format(PyExc_SystemError, "dynamic module '%s' not initialized properly from def", full_name); return NULL; } Nuitka_SetModule(full_name_obj, module); Py_DECREF(full_name_obj); int res = PyModule_ExecDef(module, def); if (unlikely(res == -1)) { return NULL; } return module; } else { def = PyModule_GetDef(module); // Fixup __package__ after load. It seems some modules ignore _Py_PackageContext value. // so we patch it up here if it's None, but a package was specified. if (package != NULL) { PyObject *package_name = LOOKUP_ATTRIBUTE(module, const_str_plain___package__); if (package_name == Py_None) { char package2[1024]; copyStringSafeN(package2, full_name, dot - full_name, sizeof(package2)); PyObject *package_name_obj = Nuitka_String_FromString(package2); SET_ATTRIBUTE(module, const_str_plain___package__, package_name_obj); Py_DECREF(package_name_obj); } Py_DECREF(package_name); } } if (likely(def != NULL)) { def->m_base.m_init = entrypoint; } #else PyModuleDef *def = PyModule_GetDef(module); if (unlikely(def == NULL)) { PyErr_Format(PyExc_SystemError, "initialization of %s did not return an extension module", filename); return NULL; } def->m_base.m_init = entrypoint; #endif #endif // Set filename attribute if not already set, in some branches we don't // do it, esp. not for older Python. if (HAS_ATTR_BOOL(module, const_str_plain___file__) == false) { #ifdef _WIN32 int res = SET_ATTRIBUTE(module, const_str_plain___file__, NuitkaUnicode_FromWideChar(filename, -1)); #else int res = SET_ATTRIBUTE(module, const_str_plain___file__, PyUnicode_FromString(filename)); #endif if (unlikely(res < 0)) { // Might be refuted, which wouldn't be harmful. CLEAR_ERROR_OCCURRED(); } } // Call the standard import fix-ups for extension modules. Their interface // changed over releases. #if PYTHON_VERSION < 0x300 PyObject *res2 = _PyImport_FixupExtension((char *)full_name, (char *)filename); if (unlikely(res2 == NULL)) { return NULL; } #else PyObject *full_name_obj = PyUnicode_FromString(full_name); CHECK_OBJECT(full_name_obj); #ifdef _WIN32 PyObject *filename_obj = NuitkaUnicode_FromWideChar(filename, -1); #else PyObject *filename_obj = PyUnicode_FromString(filename); #endif CHECK_OBJECT(filename_obj); int res = _PyImport_FixupExtensionObject(module, full_name_obj, filename_obj #if PYTHON_VERSION >= 0x370 , PyImport_GetModuleDict() #endif ); Py_DECREF(full_name_obj); Py_DECREF(filename_obj); if (unlikely(res == -1)) { return NULL; } #endif return module; } static void loadTriggeredModule(char const *name, char const *trigger_name) { char trigger_module_name[2048]; copyStringSafe(trigger_module_name, name, sizeof(trigger_module_name)); appendStringSafe(trigger_module_name, trigger_name, sizeof(trigger_module_name)); struct Nuitka_MetaPathBasedLoaderEntry *entry = findEntry(trigger_module_name); if (entry != NULL) { if (isVerbose()) { PySys_WriteStderr("Loading %s\n", trigger_module_name); } IMPORT_EMBEDDED_MODULE(trigger_module_name); if (unlikely(ERROR_OCCURRED())) { if ((entry->flags & NUITKA_ABORT_MODULE_FLAG) != 0) { printf("Critical error loading %s.\n", trigger_module_name); abort(); } else { PyObject *trigger_module_name_str = Nuitka_String_FromString(trigger_module_name); PyErr_WriteUnraisable(trigger_module_name_str); Py_DECREF(trigger_module_name_str); } } } } #if PYTHON_VERSION >= 0x340 static void _fixupSpecAttribute(PyObject *module) { PyObject *spec_value = LOOKUP_ATTRIBUTE(module, const_str_plain___spec__); if (spec_value && spec_value != Py_None) { if (HAS_ATTR_BOOL(spec_value, const_str_plain__initializing)) { SET_ATTRIBUTE(spec_value, const_str_plain__initializing, Py_False); } } } #endif // Pointers to bytecode data. static char **_bytecode_data = NULL; static PyObject *loadModule(PyObject *module, PyObject *module_name, struct Nuitka_MetaPathBasedLoaderEntry const *entry) { #ifdef _NUITKA_STANDALONE if ((entry->flags & NUITKA_SHLIB_FLAG) != 0) { // Append the the entry name from full path module name with dots, // and translate these into directory separators. #ifdef _WIN32 wchar_t filename[MAXPATHLEN + 1] = {0}; appendWStringSafeW(filename, getBinaryDirectoryWideChars(), sizeof(filename) / sizeof(wchar_t)); appendCharSafeW(filename, SEP, sizeof(filename) / sizeof(wchar_t)); appendModulenameAsPathW(filename, entry->name, sizeof(filename) / sizeof(wchar_t)); appendStringSafeW(filename, ".pyd", sizeof(filename) / sizeof(wchar_t)); #else char filename[MAXPATHLEN + 1] = {0}; appendStringSafe(filename, getBinaryDirectoryHostEncoded(), sizeof(filename)); appendCharSafe(filename, SEP, sizeof(filename)); appendModulenameAsPath(filename, entry->name, sizeof(filename)); appendStringSafe(filename, ".so", sizeof(filename)); #endif // Set filename attribute before execution, some modules expect it early. #ifdef _WIN32 SET_ATTRIBUTE(module, const_str_plain___file__, NuitkaUnicode_FromWideChar(filename, -1)); #else SET_ATTRIBUTE(module, const_str_plain___file__, PyUnicode_FromString(filename)); #endif // Not used unfortunately. TODO: Check if we can make it so. Py_DECREF(module); callIntoShlibModule(entry->name, filename); } else #endif if ((entry->flags & NUITKA_BYTECODE_FLAG) != 0) { // TODO: Do node use marshal, but our own stuff, once we // can do code objects too. PyCodeObject *code_object = (PyCodeObject *)PyMarshal_ReadObjectFromString(_bytecode_data[entry->bytecode_index], entry->bytecode_size); // TODO: Probably a bit harsh reaction. if (unlikely(code_object == NULL)) { PyErr_Print(); abort(); } return loadModuleFromCodeObject(module, code_object, entry->name, (entry->flags & NUITKA_PACKAGE_FLAG) != 0); } else { assert((entry->flags & NUITKA_SHLIB_FLAG) == 0); assert(entry->python_initfunc); bool res = Nuitka_SetModule(module_name, module); assert(res != false); // Run the compiled module code, we get the module returned. PyObject *result = entry->python_initfunc(module, entry); CHECK_OBJECT_X(result); #if PYTHON_VERSION >= 0x340 if (result != NULL) { _fixupSpecAttribute(result); } #endif } if (unlikely(ERROR_OCCURRED())) { return NULL; } if (isVerbose()) { PySys_WriteStderr("Loaded %s\n", entry->name); } return Nuitka_GetModule(module_name); } static PyObject *_EXECUTE_EMBEDDED_MODULE(PyObject *module, PyObject *module_name, char const *name) { CHECK_OBJECT(module); CHECK_OBJECT(module_name); struct Nuitka_MetaPathBasedLoaderEntry *entry = findEntry(name); bool frozen_import = entry == NULL && hasFrozenModule(name); if (entry != NULL || frozen_import) { // Execute the "preLoad" code produced for the module potentially. This // is from plugins typically, that want to modify things for the the // module before loading, to e.g. set a plug-in path, or do some monkey // patching in order to make things compatible. loadTriggeredModule(name, "-preLoad"); } PyObject *result = NULL; if (entry != NULL) { result = loadModule(module, module_name, entry); if (unlikely(result == NULL)) { return NULL; } } if (frozen_import) { PGO_onModuleEntered(name); int res = PyImport_ImportFrozenModule((char *)name); PGO_onModuleExit(name, res == -1); if (unlikely(res == -1)) { return NULL; } if (res == 1) { result = Nuitka_GetModule(module_name); } } if (result != NULL) { // Execute the "postLoad" code produced for the module potentially. This // is from plugins typically, that want to modify the module immediately // after loading, to e.g. set a plug-in path, or do some monkey patching // in order to make things compatible. loadTriggeredModule(name, "-postLoad"); return result; } Py_INCREF(Py_None); return Py_None; } // Note: This may become an entry point for hard coded imports of compiled // stuff. PyObject *IMPORT_EMBEDDED_MODULE(char const *name) { PyObject *module_name = Nuitka_String_FromString(name); // Check if it's already loaded, and don't do it again otherwise. PyObject *module = Nuitka_GetModule(module_name); if (module != NULL) { Py_DECREF(module_name); return module; } #if PYTHON_VERSION < 0x300 module = PyModule_New(name); #else module = PyModule_NewObject(module_name); #endif PyObject *result = _EXECUTE_EMBEDDED_MODULE(module, module_name, name); #if PYTHON_VERSION < 0x350 if (unlikely(result == NULL)) { Nuitka_DelModule(module_name); } #endif Py_DECREF(module_name); return result; } PyObject *EXECUTE_EMBEDDED_MODULE(PyObject *module) { PyObject *module_name = LOOKUP_ATTRIBUTE(module, const_str_plain___name__); assert(module_name); char const *name = Nuitka_String_AsString(module_name); return _EXECUTE_EMBEDDED_MODULE(module, module_name, name); } static PyObject *_path_unfreezer_load_module(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module_name; PyObject *unused; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O|O:load_module", (char **)_kwlist, &module_name, &unused); if (unlikely(res == 0)) { return NULL; } assert(module_name); assert(Nuitka_String_Check(module_name)); char const *name = Nuitka_String_AsString(module_name); if (isVerbose()) { PySys_WriteStderr("Loading %s\n", name); } #ifndef _NUITKA_STANDALONE if (installed_extension_modules != NULL) { PyObject *extension_module_filename = DICT_GET_ITEM0(installed_extension_modules, module_name); if (extension_module_filename != NULL) { // TODO: Should we not set __file__ for the module here, but there is no object. return callIntoInstalledShlibModule(module_name, extension_module_filename); } } #endif return IMPORT_EMBEDDED_MODULE(name); } static char const *_kwlist_is_package[] = {"fullname", NULL}; static PyObject *_path_unfreezer_is_package(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module_name; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:is_package", (char **)_kwlist_is_package, &module_name); if (unlikely(res == 0)) { return NULL; } assert(module_name); assert(Nuitka_String_Check(module_name)); char const *name = Nuitka_String_AsString(module_name); struct Nuitka_MetaPathBasedLoaderEntry *entry = findEntry(name); PyObject *result; if (entry) { result = BOOL_FROM((entry->flags & NUITKA_PACKAGE_FLAG) != 0); } else { // TODO: Maybe needs to be an exception. result = Py_None; } Py_INCREF(result); return result; } static char const *_kwlist_iter_modules[] = {"package", NULL}; static PyObject *_path_unfreezer_iter_modules(struct Nuitka_LoaderObject *self, PyObject *args, PyObject *kwds) { PyObject *prefix; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:iter_modules", (char **)_kwlist_iter_modules, &prefix); if (unlikely(res == 0)) { return NULL; } PyObject *result = PyList_New(0); struct Nuitka_MetaPathBasedLoaderEntry *current = loader_entries; assert(current); char const *s = self->m_loader_entry->name; while (current->name != NULL) { if ((current->flags & NUITKA_TRANSLATED_FLAG) != 0) { current->name = UNTRANSLATE(current->name); current->flags -= NUITKA_TRANSLATED_FLAG; } int c = strncmp(s, current->name, strlen(s)); if (c != 0) { current++; continue; } if (current->name[strlen(s)] == 0) { current++; continue; } char const *sub = strchr(current->name + strlen(s) + 1, '.'); if (sub != NULL) { current++; continue; } PyObject *r = PyTuple_New(2); PyObject *name = Nuitka_String_FromString(current->name + strlen(s) + 1); if (CHECK_IF_TRUE(prefix)) { PyObject *old = name; name = PyUnicode_Concat(prefix, name); Py_DECREF(old); } PyTuple_SET_ITEM(r, 0, name); PyTuple_SET_ITEM0(r, 1, BOOL_FROM((current->flags & NUITKA_PACKAGE_FLAG) != 0)); LIST_APPEND1(result, r); current++; } return result; } #if PYTHON_VERSION >= 0x300 // Used in module template too, therefore exported. PyObject *getImportLibBootstrapModule() { static PyObject *importlib = NULL; if (importlib == NULL) { importlib = PyImport_ImportModule("importlib._bootstrap"); } return importlib; } #endif #if PYTHON_VERSION >= 0x340 static PyObject *_path_unfreezer_repr_module(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module; PyObject *unused; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O|O:module_repr", (char **)_kwlist, &module, &unused); if (unlikely(res == 0)) { return NULL; } return PyUnicode_FromFormat("", PyModule_GetName(module), Nuitka_GetFilenameObject(module)); } static PyObject *getModuleSpecClass(PyObject *importlib_module) { static PyObject *module_spec_class = NULL; if (module_spec_class == NULL) { module_spec_class = PyObject_GetAttrString(importlib_module, "ModuleSpec"); } return module_spec_class; } static PyObject *createModuleSpec(PyObject *module_name, bool is_package) { CHECK_OBJECT(module_name); assert(Nuitka_String_Check(module_name)); PyObject *importlib_module = getImportLibBootstrapModule(); if (unlikely(importlib_module == NULL)) { return NULL; } PyObject *module_spec_class = getModuleSpecClass(importlib_module); if (unlikely(module_spec_class == NULL)) { return NULL; } PyObject *args = PyTuple_New(2); PyTuple_SET_ITEM0(args, 0, module_name); PyTuple_SET_ITEM0(args, 1, (PyObject *)&Nuitka_Loader_Type); PyObject *kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "is_package", is_package ? Py_True : Py_False); PyObject *result = CALL_FUNCTION(module_spec_class, args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); return result; } #ifndef _NUITKA_STANDALONE // We might have to load stuff from installed modules in our package namespaces. static PyObject *createModuleSpecViaPathFinder(PyObject *module_name, char const *parent_module_name) { if (scanModuleInPackagePath(module_name, parent_module_name)) { return createModuleSpec(module_name, false); } else { // Without error this means we didn't make it. return NULL; } } #endif static char const *_kwlist_find_spec[] = {"fullname", "is_package", "path", NULL}; static PyObject *_path_unfreezer_find_spec(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module_name; PyObject *unused1; // We ignore "is_package" PyObject *unused2; // We ignore "path" int res = PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:find_spec", (char **)_kwlist_find_spec, &module_name, &unused1, &unused2); if (unlikely(res == 0)) { return NULL; } char const *full_name = Nuitka_String_AsString(module_name); if (isVerbose()) { PySys_WriteStderr("import %s # considering responsibility (find_spec)\n", full_name); } struct Nuitka_MetaPathBasedLoaderEntry const *entry = findEntry(full_name); #ifndef _NUITKA_STANDALONE // We need to deal with things located in compiled packages, that were not included, // e.g. extension modules, but also other files, that were asked to not be included // or added later. if (entry == NULL) { entry = findContainingPackageEntry(full_name); if (entry != NULL) { PyObject *result = createModuleSpecViaPathFinder(module_name, entry->name); if (result != NULL) { if (isVerbose()) { PySys_WriteStderr("import %s # claimed responsibility (contained in compiled package %s)\n", full_name, entry->name); } return result; } if (ERROR_OCCURRED()) { return NULL; } entry = NULL; } } #endif if (entry == NULL) { if (isVerbose()) { PySys_WriteStderr("import %s # denied responsibility\n", full_name); } Py_INCREF(Py_None); return Py_None; } if (isVerbose()) { PySys_WriteStderr("import %s # claimed responsibility (%s)\n", Nuitka_String_AsString(module_name), (entry->flags & NUITKA_BYTECODE_FLAG) != 0 ? "bytecode" : "compiled"); } return createModuleSpec(module_name, (entry->flags & NUITKA_PACKAGE_FLAG) != 0); } #if PYTHON_VERSION >= 0x350 static char const *_kwlist_create_module[] = {"spec", NULL}; static PyObject *_path_unfreezer_create_module(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *spec; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:create_module", (char **)_kwlist_create_module, &spec); if (unlikely(res == 0)) { return NULL; } PyObject *module_name = PyObject_GetAttr(spec, const_str_plain_name); if (isVerbose()) { PySys_WriteStderr("import %s # created module\n", Nuitka_String_AsString(module_name)); } // TODO: Should we clean it up here? return PyModule_NewObject(module_name); } static char const *_kwlist_exec_module[] = {"module", NULL}; static PyObject *_path_unfreezer_exec_module(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *module; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:exec_module", (char **)_kwlist_exec_module, &module); if (unlikely(res == 0)) { return NULL; } PyObject *module_name = PyObject_GetAttr(module, const_str_plain___name__); CHECK_OBJECT(module_name); if (isVerbose()) { PySys_WriteStderr("import %s # execute module\n", Nuitka_String_AsString(module_name)); } // During spec creation, we have populated the dictionary with a filename to load from // for extension modules that were found installed in the system and below our package. #ifndef _NUITKA_STANDALONE if (installed_extension_modules != NULL) { PyObject *extension_module_filename = DICT_GET_ITEM0(installed_extension_modules, module_name); if (extension_module_filename != NULL) { // Set filename attribute res = SET_ATTRIBUTE(module, const_str_plain___file__, extension_module_filename); if (unlikely(res < 0)) { // Might be refuted, which wouldn't be harmful. CLEAR_ERROR_OCCURRED(); } return callIntoInstalledShlibModule(module_name, extension_module_filename); } } #endif return EXECUTE_EMBEDDED_MODULE(module); } #endif #endif #if _NUITKA_EXPERIMENTAL_METADATA struct Nuitka_DistributionObject { /* Python object folklore: */ PyObject_HEAD /* The loader entry, to know this is about exactly. */ struct Nuitka_MetaPathBasedLoaderEntry const *m_loader_entry; }; static void Nuitka_Distribution_tp_dealloc(struct Nuitka_DistributionObject *distribution) { Nuitka_GC_UnTrack(distribution); PyObject_GC_Del(distribution); } static PyObject *Nuitka_Distribution_tp_repr(struct Nuitka_DistributionObject *loader) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif "", loader->m_loader_entry->name); } static PyObject *_nuitka_distribution_metainfo(struct Nuitka_DistributionObject *distribution) { CHECK_OBJECT(distribution); PyObject *result = Nuitka_String_FromString(""); return result; } static PyMethodDef Nuitka_Distribution_methods[] = { {"metainfo", (PyCFunction)_nuitka_distribution_metainfo, METH_NOARGS, NULL}, {NULL, NULL}}; static PyObject *Nuitka_Distribution_get_version(struct Nuitka_DistributionObject *distribution) { CHECK_OBJECT(distribution); // TODO: Don't lie, but this will allow some things to proceed. return Nuitka_String_FromString("0.0.0"); } static PyGetSetDef Nuitka_Distribution_getsetlist[] = { {(char *)"version", (getter)Nuitka_Distribution_get_version, (setter)NULL, NULL}, {NULL}}; static PyTypeObject Nuitka_Distribution_Type = { PyVarObject_HEAD_INIT(NULL, 0) "nuitka_distribution", sizeof(struct Nuitka_DistributionObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_Distribution_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)Nuitka_Distribution_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Distribution_methods, /* tp_methods */ 0, /* tp_members */ Nuitka_Distribution_getsetlist, /* tp_getset */ }; PyObject *Nuitka_Distribution_New(struct Nuitka_MetaPathBasedLoaderEntry const *entry) { struct Nuitka_DistributionObject *result; result = (struct Nuitka_DistributionObject *)PyObject_GC_New(struct Nuitka_DistributionObject, &Nuitka_Distribution_Type); Nuitka_GC_Track(result); result->m_loader_entry = entry; return (PyObject *)result; } static char const *_kwlist_find_distributions[] = {"context", NULL}; static PyObject *_path_unfreezer_find_distributions(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *context; int res = PyArg_ParseTupleAndKeywords(args, kwds, "O:find_distributions", (char **)_kwlist_find_distributions, &context); if (unlikely(res == 0)) { return NULL; } PyObject *name = PyObject_GetAttr(context, const_str_plain_name); if (unlikely(name == 0)) { return NULL; } struct Nuitka_MetaPathBasedLoaderEntry *entry = findEntry(Nuitka_String_AsString(name)); Py_DECREF(name); PyObject *temp; if (entry) { temp = PyTuple_New(1); // Create a distribution object for the entry PyObject *distribution = Nuitka_Distribution_New(entry); PyTuple_SET_ITEM(temp, 0, distribution); } else { temp = const_tuple_empty; Py_INCREF(const_tuple_empty); } // We are expected to return an iterator. PyObject *result = MAKE_ITERATOR(temp); Py_DECREF(temp); return result; } #endif static PyMethodDef Nuitka_Loader_methods[] = { {"iter_modules", (PyCFunction)_path_unfreezer_iter_modules, METH_VARARGS | METH_KEYWORDS, NULL}, {"get_data", (PyCFunction)_path_unfreezer_get_data, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, {"find_module", (PyCFunction)_path_unfreezer_find_module, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, {"load_module", (PyCFunction)_path_unfreezer_load_module, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, {"is_package", (PyCFunction)_path_unfreezer_is_package, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, #if PYTHON_VERSION >= 0x340 {"module_repr", (PyCFunction)_path_unfreezer_repr_module, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, {"find_spec", (PyCFunction)_path_unfreezer_find_spec, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, #endif #if PYTHON_VERSION >= 0x350 {"create_module", (PyCFunction)_path_unfreezer_create_module, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, {"exec_module", (PyCFunction)_path_unfreezer_exec_module, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, #endif #if _NUITKA_EXPERIMENTAL_METADATA {"find_distributions", (PyCFunction)_path_unfreezer_find_distributions, METH_STATIC | METH_VARARGS | METH_KEYWORDS, NULL}, #endif {NULL, NULL} }; static PyObject *Nuitka_Loader_tp_repr(struct Nuitka_LoaderObject *loader) { #if PYTHON_VERSION < 0x300 return PyString_FromFormat( #else return PyUnicode_FromFormat( #endif "", loader->m_loader_entry->name); } #include "nuitka/freelists.h" // TODO: A freelist is not the right thing for those, they are probably living forever, but it's // no big harm too, but make it small. #define MAX_LOADER_FREE_LIST_COUNT 10 static struct Nuitka_LoaderObject *free_list_loaders = NULL; static int free_list_loaders_count = 0; static void Nuitka_Loader_tp_dealloc(struct Nuitka_LoaderObject *loader) { Nuitka_GC_UnTrack(loader); releaseToFreeList(free_list_loaders, loader, MAX_LOADER_FREE_LIST_COUNT); } static int Nuitka_Loader_tp_traverse(struct Nuitka_LoaderObject *loader, visitproc visit, void *arg) { return 0; } PyTypeObject Nuitka_Loader_Type = { PyVarObject_HEAD_INIT(NULL, 0) "nuitka_module_loader", sizeof(struct Nuitka_LoaderObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Nuitka_Loader_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)Nuitka_Loader_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)Nuitka_Loader_tp_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Nuitka_Loader_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ }; /* Used by modules to register child loaders for packages. */ PyObject *Nuitka_Loader_New(struct Nuitka_MetaPathBasedLoaderEntry const *entry) { struct Nuitka_LoaderObject *result; allocateFromFreeListFixed(free_list_loaders, struct Nuitka_LoaderObject, Nuitka_Loader_Type); Nuitka_GC_Track(result); result->m_loader_entry = entry; return (PyObject *)result; } void registerMetaPathBasedUnfreezer(struct Nuitka_MetaPathBasedLoaderEntry *_loader_entries, unsigned char **bytecode_data) { // Do it only once. if (loader_entries) { assert(_loader_entries == loader_entries); return; } _bytecode_data = (char **)bytecode_data; if (isVerbose()) { PySys_WriteStderr("Setup nuitka compiled module/bytecode/shlib importer.\n"); } #ifdef _NUITKA_MODULE if (_Py_PackageContext != NULL) { char const *last_dot = strrchr(_Py_PackageContext, '.'); if (last_dot != NULL) { struct Nuitka_MetaPathBasedLoaderEntry *current = _loader_entries; assert(current); while (current->name != NULL) { if ((current->flags & NUITKA_TRANSLATED_FLAG) != 0) { current->name = UNTRANSLATE(current->name); current->flags -= NUITKA_TRANSLATED_FLAG; } char name[2048]; if (strcmp(last_dot + 1, current->name) == 0) { copyStringSafeN(name, _Py_PackageContext, last_dot - _Py_PackageContext + 1, sizeof(name)); appendStringSafe(name, current->name, sizeof(name)); current->name = strdup(name); } else if (strncmp(last_dot + 1, current->name, strlen(last_dot + 1)) == 0 && current->name[strlen(last_dot + 1)] == '.') { copyStringSafeN(name, _Py_PackageContext, last_dot - _Py_PackageContext + 1, sizeof(name)); appendStringSafe(name, current->name, sizeof(name)); current->name = strdup(name); } current++; } } } #endif loader_entries = _loader_entries; PyType_Ready(&Nuitka_Loader_Type); #if _NUITKA_EXPERIMENTAL_METADATA PyType_Ready(&Nuitka_Distribution_Type); #endif // Register it as a meta path loader. int res = PyList_Insert(Nuitka_SysGetObject("meta_path"), #if PYTHON_VERSION < 0x300 0, #else 2, #endif (PyObject *)&Nuitka_Loader_Type); assert(res == 0); } #if defined(_NUITKA_STANDALONE) // This is called for the technical module imported early on during interpreter // into, to still get compatible "__file__" attributes. void setEarlyFrozenModulesFileAttribute(void) { #if PYTHON_VERSION >= 0x300 // Make sure the importlib fully bootstraps before doing this. PyObject *importlib_module = getImportLibBootstrapModule(); CHECK_OBJECT(importlib_module); #endif PyObject *sys_modules = PyImport_GetModuleDict(); Py_ssize_t ppos = 0; PyObject *key, *value; while (PyDict_Next(sys_modules, &ppos, &key, &value)) { if (key != NULL && value != NULL && PyModule_Check(value)) { if (HAS_ATTR_BOOL(value, const_str_plain___file__)) { bool is_package = HAS_ATTR_BOOL(value, const_str_plain___path__); PyObject *file_value = MAKE_RELATIVE_PATH_FROM_NAME(Nuitka_String_AsString(key), is_package); PyObject_SetAttr(value, const_str_plain___file__, file_value); Py_DECREF(file_value); } } } assert(!ERROR_OCCURRED()); } #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersCalling2.c0000600000372100037210000154421014166627112030150 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template CodeTemplateCallsPositional.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif PyObject *CALL_FUNCTION_NO_ARGS(PyObject *called) { CHECK_OBJECT(called); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 0 == function->m_args_positional_count) { result = function->m_c_code(function, NULL); } else if (function->m_args_simple && 0 + function->m_defaults_given == function->m_args_positional_count) { PyObject **python_pars = &PyTuple_GET_ITEM(function->m_defaults, 0); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionNoArgs(function); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyErr_Format( PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class)); return NULL; } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 0 + 1 == function->m_args_positional_count) { PyObject *python_pars[0 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 0 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1 + 0, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionNoArgs(function, method->m_object); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (likely(flags & METH_NOARGS)) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result = (*method)(self, NULL); #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (0 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = const_tuple_empty; if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = const_tuple_empty; result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, NULL, 0, NULL); #else PyObject *pos_args = const_tuple_empty; result = (*(_PyCFunctionFast)method)(self, &pos_args, 0); #endif } else { PyObject *pos_args = const_tuple_empty; result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return _fast_function_noargs(called); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = const_tuple_empty; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)init_method, obj); } else { result = CALL_FUNCTION_NO_ARGS(init_method); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if ((init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } return obj; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)init_method, obj); } else { result = CALL_FUNCTION_NO_ARGS(init_method); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, NULL, 0, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, const_tuple_empty, NULL); return result; } PyObject *CALL_FUNCTION_WITH_SINGLE_ARG(PyObject *called, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. CHECK_OBJECT(called); CHECK_OBJECTS(args, 1); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 1 == function->m_args_positional_count) { Py_INCREF(args[0]); result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 1 * sizeof(PyObject *)); memcpy(python_pars + 1, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 1); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 1); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 1 + 1 == function->m_args_positional_count) { PyObject *python_pars[1 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); python_pars[1] = args[0]; Py_INCREF(args[0]); result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 1 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 1 * sizeof(PyObject *)); memcpy(python_pars + 1 + 1, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 1); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (1 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if ((flags & METH_O)) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result = (*method)(self, args[0]); #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 1); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 1); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 1, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 1); result = (*(_PyCFunctionFast)method)(self, &pos_args, 1); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 1); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 1); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called == (PyObject *)&PyType_Type)) { PyObject *result = (PyObject *)Py_TYPE(args[0]); Py_INCREF(result); return result; } if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 1); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 1); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 1, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 1); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS1(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 1); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 1); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 1 == function->m_args_positional_count) { Py_INCREF(args[0]); result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 1 * sizeof(PyObject *)); memcpy(python_pars + 1, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 1); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 1); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 1 + 1 == function->m_args_positional_count) { PyObject *python_pars[1 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); python_pars[1] = args[0]; Py_INCREF(args[0]); result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 1 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 1 * sizeof(PyObject *)); memcpy(python_pars + 1 + 1, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 1); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (1 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if ((flags & METH_O)) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result = (*method)(self, args[0]); #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 1, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 1); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 1); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called == (PyObject *)&PyType_Type)) { PyObject *result = (PyObject *)Py_TYPE(args[0]); Py_INCREF(result); return result; } if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 1); } else { result = CALL_FUNCTION_WITH_SINGLE_ARG(init_method, args[0]); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 1, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS2(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 2); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 2 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 2; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 2 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 2 * sizeof(PyObject *)); memcpy(python_pars + 2, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 2); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 2); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 2 + 1 == function->m_args_positional_count) { PyObject *python_pars[2 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 2; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 2 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 2 * sizeof(PyObject *)); memcpy(python_pars + 1 + 2, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 2); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (2 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (2 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 2); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 2); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 2, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 2); result = (*(_PyCFunctionFast)method)(self, &pos_args, 2); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 2); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 2); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 2); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 2); } else { result = CALL_FUNCTION_WITH_ARGS2(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 2); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 2); } else { result = CALL_FUNCTION_WITH_ARGS2(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 2, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 2); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS2(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 2); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 2); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 2 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 2; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 2 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 2 * sizeof(PyObject *)); memcpy(python_pars + 2, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 2); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 2); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 2 + 1 == function->m_args_positional_count) { PyObject *python_pars[2 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 2; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 2 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 2 * sizeof(PyObject *)); memcpy(python_pars + 1 + 2, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 2); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (2 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (2 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 2, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 2); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 2); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 2); } else { result = CALL_FUNCTION_WITH_POSARGS2(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 2); } else { result = CALL_FUNCTION_WITH_POSARGS2(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 2, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS3(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 3); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 3 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 3; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 3 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 3 * sizeof(PyObject *)); memcpy(python_pars + 3, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 3); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 3); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 3 + 1 == function->m_args_positional_count) { PyObject *python_pars[3 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 3; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 3 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 3 * sizeof(PyObject *)); memcpy(python_pars + 1 + 3, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 3); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (3 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (3 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 3); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 3); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 3, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 3); result = (*(_PyCFunctionFast)method)(self, &pos_args, 3); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 3); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 3); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 3); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 3); } else { result = CALL_FUNCTION_WITH_ARGS3(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 3); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 3); } else { result = CALL_FUNCTION_WITH_ARGS3(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 3, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 3); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS3(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 3); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 3); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 3 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 3; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 3 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 3 * sizeof(PyObject *)); memcpy(python_pars + 3, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 3); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 3); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 3 + 1 == function->m_args_positional_count) { PyObject *python_pars[3 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 3; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 3 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 3 * sizeof(PyObject *)); memcpy(python_pars + 1 + 3, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 3); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (3 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (3 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 3, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 3); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 3); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 3); } else { result = CALL_FUNCTION_WITH_POSARGS3(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 3); } else { result = CALL_FUNCTION_WITH_POSARGS3(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 3, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS4(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 4); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 4 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 4; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 4 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 4 * sizeof(PyObject *)); memcpy(python_pars + 4, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 4); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 4); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 4 + 1 == function->m_args_positional_count) { PyObject *python_pars[4 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 4; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 4 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 4 * sizeof(PyObject *)); memcpy(python_pars + 1 + 4, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 4); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (4 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (4 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 4); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 4); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 4, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 4); result = (*(_PyCFunctionFast)method)(self, &pos_args, 4); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 4); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 4); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 4); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 4); } else { result = CALL_FUNCTION_WITH_ARGS4(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 4); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 4); } else { result = CALL_FUNCTION_WITH_ARGS4(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 4, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 4); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS4(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 4); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 4); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 4 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 4; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 4 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 4 * sizeof(PyObject *)); memcpy(python_pars + 4, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 4); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 4); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 4 + 1 == function->m_args_positional_count) { PyObject *python_pars[4 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 4; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 4 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 4 * sizeof(PyObject *)); memcpy(python_pars + 1 + 4, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 4); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (4 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (4 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 4, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 4); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 4); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 4); } else { result = CALL_FUNCTION_WITH_POSARGS4(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 4); } else { result = CALL_FUNCTION_WITH_POSARGS4(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 4, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS5(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 5); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 5 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 5; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 5 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 5 * sizeof(PyObject *)); memcpy(python_pars + 5, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 5); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 5); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 5 + 1 == function->m_args_positional_count) { PyObject *python_pars[5 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 5; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 5 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 5 * sizeof(PyObject *)); memcpy(python_pars + 1 + 5, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 5); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (5 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (5 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 5); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 5); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 5, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 5); result = (*(_PyCFunctionFast)method)(self, &pos_args, 5); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 5); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 5); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 5); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 5); } else { result = CALL_FUNCTION_WITH_ARGS5(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 5); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 5); } else { result = CALL_FUNCTION_WITH_ARGS5(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 5, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 5); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS5(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 5); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 5); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 5 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 5; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 5 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 5 * sizeof(PyObject *)); memcpy(python_pars + 5, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 5); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 5); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 5 + 1 == function->m_args_positional_count) { PyObject *python_pars[5 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 5; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 5 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 5 * sizeof(PyObject *)); memcpy(python_pars + 1 + 5, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 5); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (5 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (5 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 5, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 5); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 5); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 5); } else { result = CALL_FUNCTION_WITH_POSARGS5(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 5); } else { result = CALL_FUNCTION_WITH_POSARGS5(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 5, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS6(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 6); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 6 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 6; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 6 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 6 * sizeof(PyObject *)); memcpy(python_pars + 6, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 6); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 6); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 6 + 1 == function->m_args_positional_count) { PyObject *python_pars[6 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 6; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 6 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 6 * sizeof(PyObject *)); memcpy(python_pars + 1 + 6, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 6); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (6 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (6 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 6); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 6); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 6, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 6); result = (*(_PyCFunctionFast)method)(self, &pos_args, 6); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 6); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 6); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 6); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 6); } else { result = CALL_FUNCTION_WITH_ARGS6(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 6); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 6); } else { result = CALL_FUNCTION_WITH_ARGS6(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 6, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 6); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS6(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 6); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 6); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 6 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 6; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 6 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 6 * sizeof(PyObject *)); memcpy(python_pars + 6, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 6); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 6); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 6 + 1 == function->m_args_positional_count) { PyObject *python_pars[6 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 6; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 6 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 6 * sizeof(PyObject *)); memcpy(python_pars + 1 + 6, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 6); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (6 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (6 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 6, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 6); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 6); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 6); } else { result = CALL_FUNCTION_WITH_POSARGS6(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 6); } else { result = CALL_FUNCTION_WITH_POSARGS6(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 6, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS7(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 7); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 7 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 7; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 7 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 7 * sizeof(PyObject *)); memcpy(python_pars + 7, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 7); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 7); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 7 + 1 == function->m_args_positional_count) { PyObject *python_pars[7 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 7; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 7 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 7 * sizeof(PyObject *)); memcpy(python_pars + 1 + 7, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 7); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (7 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (7 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 7); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 7); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 7, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 7); result = (*(_PyCFunctionFast)method)(self, &pos_args, 7); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 7); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 7); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 7); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 7); } else { result = CALL_FUNCTION_WITH_ARGS7(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 7); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 7); } else { result = CALL_FUNCTION_WITH_ARGS7(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 7, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 7); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS7(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 7); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 7); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 7 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 7; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 7 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 7 * sizeof(PyObject *)); memcpy(python_pars + 7, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 7); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 7); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 7 + 1 == function->m_args_positional_count) { PyObject *python_pars[7 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 7; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 7 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 7 * sizeof(PyObject *)); memcpy(python_pars + 1 + 7, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 7); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (7 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (7 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 7, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 7); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 7); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 7); } else { result = CALL_FUNCTION_WITH_POSARGS7(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 7); } else { result = CALL_FUNCTION_WITH_POSARGS7(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 7, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS8(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 8); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 8 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 8; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 8 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 8 * sizeof(PyObject *)); memcpy(python_pars + 8, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 8); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 8); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 8 + 1 == function->m_args_positional_count) { PyObject *python_pars[8 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 8; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 8 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 8 * sizeof(PyObject *)); memcpy(python_pars + 1 + 8, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 8); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (8 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (8 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 8); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 8); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 8, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 8); result = (*(_PyCFunctionFast)method)(self, &pos_args, 8); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 8); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 8); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 8); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 8); } else { result = CALL_FUNCTION_WITH_ARGS8(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 8); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 8); } else { result = CALL_FUNCTION_WITH_ARGS8(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 8, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 8); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS8(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 8); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 8); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 8 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 8; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 8 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 8 * sizeof(PyObject *)); memcpy(python_pars + 8, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 8); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 8); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 8 + 1 == function->m_args_positional_count) { PyObject *python_pars[8 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 8; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 8 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 8 * sizeof(PyObject *)); memcpy(python_pars + 1 + 8, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 8); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (8 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (8 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 8, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 8); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 8); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 8); } else { result = CALL_FUNCTION_WITH_POSARGS8(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 8); } else { result = CALL_FUNCTION_WITH_POSARGS8(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 8, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS9(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 9); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 9 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 9; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 9 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 9 * sizeof(PyObject *)); memcpy(python_pars + 9, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 9); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 9); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 9 + 1 == function->m_args_positional_count) { PyObject *python_pars[9 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 9; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 9 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 9 * sizeof(PyObject *)); memcpy(python_pars + 1 + 9, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 9); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (9 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (9 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 9); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 9); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 9, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 9); result = (*(_PyCFunctionFast)method)(self, &pos_args, 9); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 9); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 9); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 9); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 9); } else { result = CALL_FUNCTION_WITH_ARGS9(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 9); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 9); } else { result = CALL_FUNCTION_WITH_ARGS9(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 9, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 9); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS9(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 9); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 9); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 9 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 9; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 9 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 9 * sizeof(PyObject *)); memcpy(python_pars + 9, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 9); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 9); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 9 + 1 == function->m_args_positional_count) { PyObject *python_pars[9 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 9; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 9 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 9 * sizeof(PyObject *)); memcpy(python_pars + 1 + 9, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 9); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (9 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (9 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 9, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 9); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 9); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 9); } else { result = CALL_FUNCTION_WITH_POSARGS9(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 9); } else { result = CALL_FUNCTION_WITH_POSARGS9(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 9, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_ARGS10(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 10); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 10 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 10; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 10 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 10 * sizeof(PyObject *)); memcpy(python_pars + 10, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 10); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 10); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 10 + 1 == function->m_args_positional_count) { PyObject *python_pars[10 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 10; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 10 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 10 * sizeof(PyObject *)); memcpy(python_pars + 1 + 10, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 10); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (10 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (10 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args, 10); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args, 10); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 10, NULL); #else PyObject *pos_args = MAKE_TUPLE(args, 10); result = (*(_PyCFunctionFast)method)(self, &pos_args, 10); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args, 10); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 10); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *pos_args = NULL; PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { pos_args = MAKE_TUPLE(args, 10); obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { Py_DECREF(pos_args); return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { Py_XDECREF(pos_args); pos_args = NULL; PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 10); } else { result = CALL_FUNCTION_WITH_ARGS10(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (pos_args == NULL) { pos_args = MAKE_TUPLE(args, 10); } if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); Py_XDECREF(pos_args); return NULL; } } } } Py_XDECREF(pos_args); return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 10); } else { result = CALL_FUNCTION_WITH_ARGS10(init_method, args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 10, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 10); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; } PyObject *CALL_FUNCTION_WITH_POSARGS10(PyObject *called, PyObject *pos_args) { assert(PyTuple_CheckExact(pos_args)); assert(PyTuple_GET_SIZE(pos_args) == 10); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECT(called); CHECK_OBJECTS(args, 10); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result; if (function->m_args_simple && 10 == function->m_args_positional_count) { for (Py_ssize_t i = 0; i < 10; i++) { Py_INCREF(args[i]); } result = function->m_c_code(function, (PyObject **)args); } else if (function->m_args_simple && 10 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); memcpy(python_pars, args, 10 * sizeof(PyObject *)); memcpy(python_pars + 10, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 0; i < function->m_args_positional_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallFunctionPosArgs(function, args, 10); } Py_LeaveRecursiveCall(); return result; } else if (Nuitka_Method_Check(called)) { struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)called; if (method->m_object == NULL) { PyObject *self = args[0]; int res = PyObject_IsInstance(self, method->m_class); if (unlikely(res < 0)) { return NULL; } else if (unlikely(res == 0)) { PyErr_Format(PyExc_TypeError, "unbound compiled_method %s%s must be called with %s instance as first argument (got %s " "instance instead)", GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class), GET_INSTANCE_CLASS_NAME((PyObject *)self)); return NULL; } return Nuitka_CallFunctionPosArgs(method->m_function, args, 10); } else { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = method->m_function; PyObject *result; if (function->m_args_simple && 10 + 1 == function->m_args_positional_count) { PyObject *python_pars[10 + 1]; python_pars[0] = method->m_object; Py_INCREF(method->m_object); for (Py_ssize_t i = 0; i < 10; i++) { python_pars[i + 1] = args[i]; Py_INCREF(args[i]); } result = function->m_c_code(function, python_pars); } else if (function->m_args_simple && 10 + 1 + function->m_defaults_given == function->m_args_positional_count) { NUITKA_DYNAMIC_ARRAY_DECL(python_pars, PyObject *, function->m_args_positional_count); python_pars[0] = method->m_object; Py_INCREF(method->m_object); memcpy(python_pars + 1, args, 10 * sizeof(PyObject *)); memcpy(python_pars + 1 + 10, &PyTuple_GET_ITEM(function->m_defaults, 0), function->m_defaults_given * sizeof(PyObject *)); for (Py_ssize_t i = 1; i < function->m_args_overall_count; i++) { Py_INCREF(python_pars[i]); } result = function->m_c_code(function, python_pars); } else { result = Nuitka_CallMethodFunctionPosArgs(function, method->m_object, args, 10); } Py_LeaveRecursiveCall(); return result; } } else if (PyCFunction_Check(called)) { // Try to be fast about wrapping the arguments. int flags = PyCFunction_GET_FLAGS(called) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes no arguments (10 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (10 given)", ((PyCFunctionObject *)called)->m_ml->ml_name); return NULL; } else if (flags & METH_VARARGS) { // Recursion guard is not strictly necessary, as we already have // one on our way to here. #ifdef _NUITKA_FULL_COMPAT if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } #endif PyCFunction method = PyCFunction_GET_FUNCTION(called); PyObject *self = PyCFunction_GET_SELF(called); PyObject *result; #if PYTHON_VERSION < 0x360 if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args, 10, NULL); #else result = (*(_PyCFunctionFast)method)(self, &pos_args, 10); #endif } else { result = (*method)(self, pos_args); } #endif #ifdef _NUITKA_FULL_COMPAT Py_LeaveRecursiveCall(); #endif return Nuitka_CheckFunctionResult(result); } } else if (PyFunction_Check(called)) { return callPythonFunction(called, args, 10); } else if (PyType_Check(called)) { PyTypeObject *type = Py_TYPE(called); if (type->tp_call == PyType_Type.tp_call) { PyTypeObject *called_type = (PyTypeObject *)(called); if (unlikely(called_type->tp_new == NULL)) { PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", called_type->tp_name); return NULL; } PyObject *obj; if (called_type->tp_new == PyBaseObject_Type.tp_new) { if (unlikely(called_type->tp_flags & Py_TPFLAGS_IS_ABSTRACT)) { formatCannotInstantiateAbstractClass(called_type); return NULL; } obj = called_type->tp_alloc(called_type, 0); CHECK_OBJECT(obj); } else { obj = called_type->tp_new(called_type, pos_args, NULL); } if (likely(obj != NULL)) { if (!PyType_IsSubtype(obj->ob_type, called_type)) { return obj; } // Work on produced type. type = Py_TYPE(obj); if (NuitkaType_HasFeatureClass(type) && type->tp_init != NULL) { if (type->tp_init == default_tp_init_wrapper) { PyObject *init_method = Nuitka_TypeLookup(type, const_str_plain___init__); // Not really allowed, since we wouldn't have the default wrapper set. assert(init_method != NULL); bool is_compiled_function = false; if (likely(init_method != NULL)) { descrgetfunc func = Py_TYPE(init_method)->tp_descr_get; if (func == NULL) { Py_INCREF(init_method); } else if (func == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else { init_method = func(init_method, obj, (PyObject *)(type)); } } if (unlikely(init_method == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___init__); } return NULL; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 10); } else { result = CALL_FUNCTION_WITH_POSARGS10(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } } else { if (unlikely(type->tp_init(obj, pos_args, NULL) < 0)) { Py_DECREF(obj); return NULL; } } } } return obj; } #if PYTHON_VERSION < 0x300 } else if (PyClass_Check(called)) { PyObject *obj = PyInstance_NewRaw(called, NULL); PyObject *init_method = FIND_ATTRIBUTE_IN_CLASS((PyClassObject *)called, const_str_plain___init__); if (unlikely(init_method == NULL)) { if (unlikely(ERROR_OCCURRED())) { Py_DECREF(obj); return NULL; } Py_DECREF(obj); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "this constructor takes no arguments"); return NULL; } bool is_compiled_function = false; descrgetfunc descr_get = Py_TYPE(init_method)->tp_descr_get; if (descr_get == NULL) { Py_INCREF(init_method); } else if (descr_get == Nuitka_Function_Type.tp_descr_get) { is_compiled_function = true; } else if (descr_get != NULL) { PyObject *descr_method = descr_get(init_method, obj, called); if (unlikely(descr_method == NULL)) { return NULL; } init_method = descr_method; } PyObject *result; if (is_compiled_function) { result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)init_method, obj, args, 10); } else { result = CALL_FUNCTION_WITH_POSARGS10(init_method, pos_args); Py_DECREF(init_method); } if (unlikely(result == NULL)) { return NULL; } Py_DECREF(result); if (unlikely(result != Py_None)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("__init__() should return None, not '%s'", result); return NULL; } return obj; #endif #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 10, NULL); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *result = CALL_FUNCTION(called, pos_args, NULL); return result; } PyObject *CALL_FUNCTION_WITH_NO_ARGS_KWSPLIT(PyObject *called, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, NULL, 0, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, kw_values, 0, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = const_tuple_empty; PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS1_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 1); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[1], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 1, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 1, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 1); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[1 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 1); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS1_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 1); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 1, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 1 + nkwargs); memcpy(vectorcall_args, args, 1 * sizeof(PyObject *)); memcpy(&vectorcall_args[1], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 1, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 1); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 1); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS1_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 1); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 1, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 1 + nkwargs); memcpy(vectorcall_args, args, 1 * sizeof(PyObject *)); memcpy(&vectorcall_args[1], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 1, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 1); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS2_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 2); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[2], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 2, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 2, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 2); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[2 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 2); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS2_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 2); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 2, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 2 + nkwargs); memcpy(vectorcall_args, args, 2 * sizeof(PyObject *)); memcpy(&vectorcall_args[2], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 2, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 2); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 2); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS2_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 2); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 2, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 2 + nkwargs); memcpy(vectorcall_args, args, 2 * sizeof(PyObject *)); memcpy(&vectorcall_args[2], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 2, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 2); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS3_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 3); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[3], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 3, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 3, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 3); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[3 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 3); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS3_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 3); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 3, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 3 + nkwargs); memcpy(vectorcall_args, args, 3 * sizeof(PyObject *)); memcpy(&vectorcall_args[3], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 3, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 3); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 3); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS3_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 3); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 3, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 3 + nkwargs); memcpy(vectorcall_args, args, 3 * sizeof(PyObject *)); memcpy(&vectorcall_args[3], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 3, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 3); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS4_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 4); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[4], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 4, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 4, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 4); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[4 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 4); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS4_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 4); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 4, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 4 + nkwargs); memcpy(vectorcall_args, args, 4 * sizeof(PyObject *)); memcpy(&vectorcall_args[4], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 4, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 4); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 4); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS4_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 4); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 4, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 4 + nkwargs); memcpy(vectorcall_args, args, 4 * sizeof(PyObject *)); memcpy(&vectorcall_args[4], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 4, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 4); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS5_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 5); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[5], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 5, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 5, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 5); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[5 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 5); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS5_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 5); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 5, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 5 + nkwargs); memcpy(vectorcall_args, args, 5 * sizeof(PyObject *)); memcpy(&vectorcall_args[5], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 5, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 5); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 5); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS5_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 5); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 5, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 5 + nkwargs); memcpy(vectorcall_args, args, 5 * sizeof(PyObject *)); memcpy(&vectorcall_args[5], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 5, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 5); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS6_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 6); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[6], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 6, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 6, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 6); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[6 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 6); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS6_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 6); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 6, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 6 + nkwargs); memcpy(vectorcall_args, args, 6 * sizeof(PyObject *)); memcpy(&vectorcall_args[6], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 6, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 6); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 6); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS6_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 6); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 6, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 6 + nkwargs); memcpy(vectorcall_args, args, 6 * sizeof(PyObject *)); memcpy(&vectorcall_args[6], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 6, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 6); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS7_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 7); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[7], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 7, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 7, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 7); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[7 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 7); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS7_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 7); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 7, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 7 + nkwargs); memcpy(vectorcall_args, args, 7 * sizeof(PyObject *)); memcpy(&vectorcall_args[7], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 7, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 7); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 7); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS7_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 7); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 7, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 7 + nkwargs); memcpy(vectorcall_args, args, 7 * sizeof(PyObject *)); memcpy(&vectorcall_args[7], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 7, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 7); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS8_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 8); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[8], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 8, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 8, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 8); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[8 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 8); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS8_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 8); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 8, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 8 + nkwargs); memcpy(vectorcall_args, args, 8 * sizeof(PyObject *)); memcpy(&vectorcall_args[8], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 8, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 8); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 8); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS8_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 8); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 8, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 8 + nkwargs); memcpy(vectorcall_args, args, 8 * sizeof(PyObject *)); memcpy(&vectorcall_args[8], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 8, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 8); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS9_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 9); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[9], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 9, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 9, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 9); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[9 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 9); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS9_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 9); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 9, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 9 + nkwargs); memcpy(vectorcall_args, args, 9 * sizeof(PyObject *)); memcpy(&vectorcall_args[9], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 9, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 9); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 9); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS9_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 9); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 9, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 9 + nkwargs); memcpy(vectorcall_args, args, 9 * sizeof(PyObject *)); memcpy(&vectorcall_args[9], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 9, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 9); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS10_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names) { CHECK_OBJECTS(args, 10); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(&args[10], nkwargs); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionVectorcall(function, args, 10, &PyTuple_GET_ITEM(kw_names, 0), nkwargs); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { PyObject *result = func(called, args, 10, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 10); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = args[10 + i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 10); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_ARGS10_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names) { CHECK_OBJECTS(args, 10); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 10, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 10 + nkwargs); memcpy(vectorcall_args, args, 10 * sizeof(PyObject *)); memcpy(&vectorcall_args[10], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 10, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *pos_args = MAKE_TUPLE(args, 10); PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(pos_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 10); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_FUNCTION_WITH_POSARGS10_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names) { assert(PyTuple_CheckExact(pos_args)); PyObject *const *args = &PyTuple_GET_ITEM(pos_args, 0); CHECK_OBJECTS(args, 10); CHECK_OBJECT(kw_names); assert(PyTuple_CheckExact(kw_names)); Py_ssize_t nkwargs = PyTuple_GET_SIZE(kw_names); CHECK_OBJECTS(kw_values, PyTuple_GET_SIZE(kw_names)); if (Nuitka_Function_Check(called)) { if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } struct Nuitka_FunctionObject *function = (struct Nuitka_FunctionObject *)called; PyObject *result = Nuitka_CallFunctionPosArgsKwSplit(function, args, 10, kw_values, kw_names); Py_LeaveRecursiveCall(); return result; #if PYTHON_VERSION >= 0x380 } else if (PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)) { vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); if (likely(func != NULL)) { NUITKA_DYNAMIC_ARRAY_DECL(vectorcall_args, PyObject *, 10 + nkwargs); memcpy(vectorcall_args, args, 10 * sizeof(PyObject *)); memcpy(&vectorcall_args[10], kw_values, nkwargs * sizeof(PyObject *)); PyObject *result = func(called, vectorcall_args, 10, kw_names); return Nuitka_CheckFunctionResult(result); } #endif } #if 0 PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif ternaryfunc call_slot = Py_TYPE(called)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", called); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *named_args = _PyDict_NewPresized(nkwargs); for (Py_ssize_t i = 0; i < nkwargs; i++) { PyObject *key = PyTuple_GET_ITEM(kw_names, i); PyObject *value = kw_values[i]; CHECK_OBJECT(key); CHECK_OBJECT(value); PyDict_SetItem(named_args, key, value); } PyObject *result = (*call_slot)(called, pos_args, named_args); Py_DECREF(named_args); CHECK_OBJECTS(args, 10); CHECK_OBJECTS(kw_values, nkwargs); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } PyObject *CALL_METHODDESCR_WITH_SINGLE_ARG(PyObject *called, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. CHECK_OBJECT(called); CHECK_OBJECTS(args, 1); #if PYTHON_VERSION >= 0x380 assert(PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)); vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); assert(func != NULL); PyObject *result = func(called, args, 1, NULL); return Nuitka_CheckFunctionResult(result); #else PyMethodDescrObject *called_descr = (PyMethodDescrObject *)called; PyMethodDef *method_def = called_descr->d_method; // Try to be fast about wrapping the arguments. int flags = method_def->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (likely(flags & METH_NOARGS)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, NULL); return Nuitka_CheckFunctionResult(result); } else if ((flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (1 given)", method_def->ml_name); return NULL; } else if (flags & METH_VARARGS) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args + 1, 0); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args + 1, 0); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args + 1, 0, NULL); #else PyObject *pos_args = MAKE_TUPLE(args + 1, 0); result = (*(_PyCFunctionFast)method)(self, &pos_args, 1); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args + 1, 0); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif return Nuitka_CheckFunctionResult(result); } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 1); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; #endif } PyObject *CALL_METHODDESCR_WITH_ARGS2(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 2); #if PYTHON_VERSION >= 0x380 assert(PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)); vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); assert(func != NULL); PyObject *result = func(called, args, 2, NULL); return Nuitka_CheckFunctionResult(result); #else PyMethodDescrObject *called_descr = (PyMethodDescrObject *)called; PyMethodDef *method_def = called_descr->d_method; // Try to be fast about wrapping the arguments. int flags = method_def->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, NULL); return Nuitka_CheckFunctionResult(result); } else if (unlikely(flags & METH_O)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, args[1]); return Nuitka_CheckFunctionResult(result); } else if (flags & METH_VARARGS) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args + 1, 1); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args + 1, 1); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args + 1, 1, NULL); #else PyObject *pos_args = MAKE_TUPLE(args + 1, 1); result = (*(_PyCFunctionFast)method)(self, &pos_args, 2); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args + 1, 1); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif return Nuitka_CheckFunctionResult(result); } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 2); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; #endif } PyObject *CALL_METHODDESCR_WITH_ARGS3(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 3); #if PYTHON_VERSION >= 0x380 assert(PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)); vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); assert(func != NULL); PyObject *result = func(called, args, 3, NULL); return Nuitka_CheckFunctionResult(result); #else PyMethodDescrObject *called_descr = (PyMethodDescrObject *)called; PyMethodDef *method_def = called_descr->d_method; // Try to be fast about wrapping the arguments. int flags = method_def->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, NULL); return Nuitka_CheckFunctionResult(result); } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (3 given)", method_def->ml_name); return NULL; } else if (flags & METH_VARARGS) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args + 1, 2); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args + 1, 2); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args + 1, 2, NULL); #else PyObject *pos_args = MAKE_TUPLE(args + 1, 2); result = (*(_PyCFunctionFast)method)(self, &pos_args, 3); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args + 1, 2); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif return Nuitka_CheckFunctionResult(result); } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 3); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; #endif } PyObject *CALL_METHODDESCR_WITH_ARGS4(PyObject *called, PyObject *const *args) { CHECK_OBJECT(called); CHECK_OBJECTS(args, 4); #if PYTHON_VERSION >= 0x380 assert(PyType_HasFeature(Py_TYPE(called), _Py_TPFLAGS_HAVE_VECTORCALL)); vectorcallfunc func = *((vectorcallfunc *)(((char *)called) + Py_TYPE(called)->tp_vectorcall_offset)); assert(func != NULL); PyObject *result = func(called, args, 4, NULL); return Nuitka_CheckFunctionResult(result); #else PyMethodDescrObject *called_descr = (PyMethodDescrObject *)called; PyMethodDef *method_def = called_descr->d_method; // Try to be fast about wrapping the arguments. int flags = method_def->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (unlikely(flags & METH_NOARGS)) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result = (*method)(self, NULL); return Nuitka_CheckFunctionResult(result); } else if (unlikely(flags & METH_O)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, "%s() takes exactly one argument (4 given)", method_def->ml_name); return NULL; } else if (flags & METH_VARARGS) { PyCFunction method = method_def->ml_meth; PyObject *self = args[0]; PyObject *result; #if PYTHON_VERSION < 0x360 PyObject *pos_args = MAKE_TUPLE(args + 1, 3); if (flags & METH_KEYWORDS) { result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); } else { result = (*method)(self, pos_args); } Py_DECREF(pos_args); #else if (flags == (METH_VARARGS | METH_KEYWORDS)) { PyObject *pos_args = MAKE_TUPLE(args + 1, 3); result = (*(PyCFunctionWithKeywords)method)(self, pos_args, NULL); Py_DECREF(pos_args); } else if (flags == METH_FASTCALL) { #if PYTHON_VERSION < 0x370 result = (*(_PyCFunctionFast)method)(self, (PyObject **)args + 1, 3, NULL); #else PyObject *pos_args = MAKE_TUPLE(args + 1, 3); result = (*(_PyCFunctionFast)method)(self, &pos_args, 4); Py_DECREF(pos_args); #endif } else { PyObject *pos_args = MAKE_TUPLE(args + 1, 3); result = (*method)(self, pos_args); Py_DECREF(pos_args); } #endif return Nuitka_CheckFunctionResult(result); } #if 0 PRINT_NEW_LINE(); PRINT_STRING("FALLBACK"); PRINT_ITEM(called); PRINT_NEW_LINE(); #endif PyObject *pos_args = MAKE_TUPLE(args, 4); PyObject *result = CALL_FUNCTION(called, pos_args, NULL); Py_DECREF(pos_args); return result; #endif } PyObject *CALL_METHOD_NO_ARGS(PyObject *source, PyObject *attr_name) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)descr, source); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_NO_ARGS(descr); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_NO_ARGS(called_object); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionNoArgs((struct Nuitka_FunctionObject const *)called_object, source); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_NO_ARGS(method); Py_DECREF(method); return result; } else { return CALL_FUNCTION_NO_ARGS(called_object); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_NO_ARGS(descr); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_NO_ARGS(called_object); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_SINGLE_ARG(PyObject *source, PyObject *attr_name, PyObject *arg) { PyObject *const *args = &arg; // For easier code compatibility. CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 1); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 1); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(descr, args[0]); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 1); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(method, args[0]); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(descr, args[0]); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(called_object, args[0]); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS2(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 2); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 2); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS2(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS2(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 2); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS2(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS2(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS2(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS2(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS3(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 3); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 3); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS3(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS3(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 3); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS3(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS3(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS3(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS3(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS4(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 4); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 4); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS4(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS4(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 4); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS4(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS4(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS4(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS4(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS5(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 5); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 5); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS5(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS5(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 5); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS5(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS5(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS5(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS5(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS6(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 6); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 6); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS6(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS6(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 6); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS6(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS6(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS6(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS6(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS7(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 7); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 7); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS7(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS7(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 7); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS7(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS7(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS7(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS7(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS8(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 8); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 8); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS8(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS8(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 8); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS8(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS8(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS8(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS8(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS9(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 9); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 9); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS9(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS9(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 9); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS9(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS9(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS9(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS9(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } PyObject *CALL_METHOD_WITH_ARGS10(PyObject *source, PyObject *attr_name, PyObject *const *args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECTS(args, 10); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = Nuitka_TypeLookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } } } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) { tsize = -tsize; } size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *called_object = DICT_GET_ITEM1(dict, attr_name); if (called_object != NULL) { Py_XDECREF(descr); Py_DECREF(dict); PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } Py_DECREF(dict); } if (func != NULL) { if (func == Nuitka_Function_Type.tp_descr_get) { PyObject *result = Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)descr, source, args, 10); Py_DECREF(descr); return result; } else { PyObject *called_object = func(descr, source, (PyObject *)type); CHECK_OBJECT(called_object); Py_DECREF(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } } if (descr != NULL) { CHECK_OBJECT(descr); PyObject *result = CALL_FUNCTION_WITH_ARGS10(descr, args); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 0x300 SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 0x300 else if (type == &PyInstance_Type) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_ARGS10(called_object, args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, args, 10); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS10(method, args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_ARGS10(called_object, args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args2[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args2); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } } #endif else if (type->tp_getattro != NULL) { PyObject *descr = (*type->tp_getattro)(source, attr_name); if (unlikely(descr == NULL)) { return NULL; } descrgetfunc func = NULL; if (NuitkaType_HasFeatureClass(Py_TYPE(descr))) { func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *called_object = func(descr, source, (PyObject *)type); Py_DECREF(descr); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } } PyObject *result = CALL_FUNCTION_WITH_ARGS10(descr, args); Py_DECREF(descr); return result; } else if (type->tp_getattr != NULL) { PyObject *called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_ARGS10(called_object, args); Py_DECREF(called_object); return result; } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } } Nuitka-0.6.19.1/nuitka/build/static_src/MainProgram.c0000600000372100037210000010001414166627112027373 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* The main program for a compiled program. * * It needs to prepare the interpreter and then loads and executes * the "__main__" module. * */ #if defined(_WIN32) #include #endif #include "nuitka/prelude.h" #ifndef __IDE_ONLY__ // Generated during build with optional defines. #include "build_definitions.h" #else // For the IDE to know these exist. #define SYSFLAG_PY3K_WARNING 0 #define SYSFLAG_DIVISION_WARNING 0 #define SYSFLAG_UNICODE 0 #define SYSFLAG_OPTIMIZE 0 #define SYSFLAG_NO_SITE 0 #define SYSFLAG_VERBOSE 0 #define SYSFLAG_BYTES_WARNING 0 #define SYSFLAG_UTF8 0 #endif #ifndef NUITKA_MAIN_MODULE_NAME #define NUITKA_MAIN_MODULE_NAME "__main__" #endif #include #include extern PyCodeObject *codeobj_main; /* For later use in "Py_GetArgcArgv" we expose the needed value */ #if PYTHON_VERSION >= 0x300 static wchar_t **orig_argv; #else static char **orig_argv; #endif static int orig_argc; #ifdef _NUITKA_STANDALONE #if _NUITKA_FROZEN > 0 extern void copyFrozenModulesTo(struct _frozen *destination); // The original frozen modules list. #if PYTHON_VERSION < 0x340 static struct _frozen *old_frozen = NULL; #else static struct _frozen const *old_frozen = NULL; #endif #endif static void prepareStandaloneEnvironment() { // Tell the CPython library to use our pre-compiled modules as frozen // modules. This for those modules/packages like "encoding" that will be // loaded during "Py_Initialize" already, for the others they may be // compiled. #if _NUITKA_FROZEN > 0 // The CPython library has some pre-existing frozen modules, we only append // to that. struct _frozen const *search = PyImport_FrozenModules; while (search->name) { search++; } int pre_existing_count = (int)(search - PyImport_FrozenModules); /* Allocate new memory and merge the tables. Keeping the old ones has * the advantage that e.g. "import this" is going to work well. */ struct _frozen *merged = (struct _frozen *)malloc(sizeof(struct _frozen) * (_NUITKA_FROZEN + pre_existing_count + 1)); memcpy(merged, PyImport_FrozenModules, pre_existing_count * sizeof(struct _frozen)); copyFrozenModulesTo(merged + pre_existing_count); old_frozen = PyImport_FrozenModules; PyImport_FrozenModules = merged; #endif /* Setup environment variables to tell CPython that we would like it to use * the provided binary directory as the place to look for DLLs and for * extension modules. */ #if defined(_WIN32) SetDllDirectoryW(getBinaryDirectoryWideChars()); #endif #if PYTHON_VERSION < 0x300 char *binary_directory = (char *)getBinaryDirectoryHostEncoded(); NUITKA_PRINTF_TRACE("main(): Binary dir is %s\n", binary_directory); Py_SetPythonHome(binary_directory); #else wchar_t *binary_directory = (wchar_t *)getBinaryDirectoryWideChars(); NUITKA_PRINTF_TRACE("main(): Binary dir is %S\n", binary_directory); Py_SetPythonHome(binary_directory); #endif } static void restoreStandaloneEnvironment() { /* Make sure to use the optimal value for standalone mode only. */ #if PYTHON_VERSION < 0x300 PySys_SetPath((char *)getBinaryDirectoryHostEncoded()); // NUITKA_PRINTF_TRACE("Final PySys_GetPath is 's'.\n", PySys_GetPath()); #else PySys_SetPath(getBinaryDirectoryWideChars()); Py_SetPath(getBinaryDirectoryWideChars()); NUITKA_PRINTF_TRACE("Final Py_GetPath is '%ls'.\n", Py_GetPath()); #endif } #endif extern void _initCompiledCellType(); extern void _initCompiledGeneratorType(); extern void _initCompiledFunctionType(); extern void _initCompiledMethodType(); extern void _initCompiledFrameType(); #include #ifdef _WIN32 #define _NUITKA_NATIVE_WCHAR_ARGV 1 #else #define _NUITKA_NATIVE_WCHAR_ARGV 0 #endif // Types of command line arguments are different between Python2/3. #if PYTHON_VERSION >= 0x300 && _NUITKA_NATIVE_WCHAR_ARGV == 0 static wchar_t **convertCommandLineParameters(int argc, char **argv) { // Originally taken from CPython3: There seems to be no sane way to use static wchar_t **argv_copy; argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t *) * argc); // Temporarily disable locale for conversions to not use it. char *oldloc = strdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (int i = 0; i < argc; i++) { #if PYTHON_VERSION >= 0x350 argv_copy[i] = Py_DecodeLocale(argv[i], NULL); #elif defined(__APPLE__) && PYTHON_VERSION >= 0x320 argv_copy[i] = _Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i])); #else argv_copy[i] = _Py_char2wchar(argv[i], NULL); #endif assert(argv_copy[i]); } setlocale(LC_ALL, oldloc); free(oldloc); return argv_copy; } #endif #ifdef _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED extern void SvcInstall(); extern void SvcLaunchService(); // Callback from Windows Service logic. DWORD WINAPI SvcStartPython(LPVOID lpParam) { if (lpParam == NULL) { EXECUTE_MAIN_MODULE(NUITKA_MAIN_MODULE_NAME); // TODO: Log exception and call ReportSvcStatus if (ERROR_OCCURRED()) { return 1; } else { return 0; } } else { PyErr_SetInterrupt(); return 0; } } #endif // This is a multiprocessing fork static bool is_multiprocessing_fork = false; // This is a multiprocessing resource tracker. static PyObject *multiprocessing_resource_tracker_arg = NULL; // Platform compat #if !defined(_WIN32) && PYTHON_VERSION >= 0x300 static long _wtoi(const wchar_t *value) { return wcstol(value, 0, 10); } #endif // Parse the command line parameters and provide it to "sys" built-in module, // as well as decide if it's a multiprocessing usage. #if _NUITKA_NATIVE_WCHAR_ARGV == 0 static void setCommandLineParameters(int argc, char **argv, bool initial) { #else static void setCommandLineParameters(int argc, wchar_t **argv, bool initial) { #endif if (initial) { /* We might need to handle special parameters from plugins that are very deeply woven into command line handling. These are right now multiprocessing, which indicates that it's forking via extra command line argument. And Windows Service indicates need to install and exit here too. */ for (int i = 1; i < argc; i++) { #if _NUITKA_NATIVE_WCHAR_ARGV == 0 if ((strcmp(argv[i], "--multiprocessing-fork")) == 0 && (i + 1 < argc)) #else if ((wcscmp(argv[i], L"--multiprocessing-fork")) == 0 && (i + 1 < argc)) #endif { is_multiprocessing_fork = true; break; } #if _NUITKA_NATIVE_WCHAR_ARGV == 0 if ((strcmp(argv[i], "--multiprocessing-resource-tracker")) == 0 && (i + 1 < argc)) #else if ((wcscmp(argv[i], L"--multiprocessing-resource-tracker")) == 0 && (i + 1 < argc)) #endif { #if _NUITKA_NATIVE_WCHAR_ARGV == 0 multiprocessing_resource_tracker_arg = PyInt_FromLong(atoi(argv[i + 1])); #else multiprocessing_resource_tracker_arg = PyLong_FromLong(_wtoi(argv[i + 1])); #endif break; } #ifdef _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED if (i == 1) { #if PYTHON_VERSION < 0x300 if (strcmp(argv[i], "install") == 0) #else if (wcscmp(argv[i], L"install") == 0) #endif { NUITKA_PRINT_TRACE("main(): Calling plugin SvcInstall()."); SvcInstall(); NUITKA_CANNOT_GET_HERE("SvcInstall must not return"); } } #endif } } } #if defined(_WIN32) && PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1 static void setenv(char const *name, char const *value, int overwrite) { assert(overwrite); SetEnvironmentVariableA(name, value); } static void unsetenv(char const *name) { SetEnvironmentVariableA(name, NULL); } #endif #if _DEBUG_REFCOUNTS static void PRINT_REFCOUNTS() { PRINT_STRING("REFERENCE counts at program end:\n"); PRINT_STRING("active | allocated | released\n"); PRINT_FORMAT("Compiled Coroutines: %d | %d | %d\n", count_active_Nuitka_Coroutine_Type, count_allocated_Nuitka_Coroutine_Type, count_released_Nuitka_Coroutine_Type); PRINT_FORMAT("Compiled Coroutines Wrappers: %d | %d | %d\n", count_active_Nuitka_CoroutineWrapper_Type, count_allocated_Nuitka_CoroutineWrapper_Type, count_released_Nuitka_CoroutineWrapper_Type); PRINT_FORMAT("Compiled Coroutines AIter Wrappers: %d | %d | %d\n", count_active_Nuitka_AIterWrapper_Type, count_allocated_Nuitka_AIterWrapper_Type, count_released_Nuitka_AIterWrapper_Type); #if PYTHON_VERSION >= 0x360 PRINT_FORMAT("Compiled Asyncgen: %d | %d | %d\n", count_active_Nuitka_Asyncgen_Type, count_allocated_Nuitka_Asyncgen_Type, count_released_Nuitka_Asyncgen_Type); PRINT_FORMAT("Compiled Asyncgen Wrappers: %d | %d | %d\n", count_active_Nuitka_AsyncgenValueWrapper_Type, count_allocated_Nuitka_AsyncgenValueWrapper_Type, count_released_Nuitka_AsyncgenValueWrapper_Type); PRINT_FORMAT("Compiled Asyncgen Asend: %d | %d | %d\n", count_active_Nuitka_AsyncgenAsend_Type, count_allocated_Nuitka_AsyncgenAsend_Type, count_released_Nuitka_AsyncgenAsend_Type); PRINT_FORMAT("Compiled Asyncgen Athrow: %d | %d | %d\n", count_active_Nuitka_AsyncgenAthrow_Type, count_allocated_Nuitka_AsyncgenAthrow_Type, count_released_Nuitka_AsyncgenAthrow_Type); #endif PRINT_FORMAT("Compiled Frames: %d | %d | %d (cache usage may occur)\n", count_active_Nuitka_Frame_Type, count_allocated_Nuitka_Frame_Type, count_released_Nuitka_Frame_Type); PRINT_STRING("CACHED counts at program end:\n"); PRINT_STRING("active | allocated | released | hits\n"); PRINT_FORMAT("Cached Frames: %d | %d | %d | %d\n", count_active_frame_cache_instances, count_allocated_frame_cache_instances, count_released_frame_cache_instances, count_hit_frame_cache_instances); } #endif // Small helper to open files with few arguments. static PyObject *BUILTIN_OPEN_SIMPLE(PyObject *filename, char const *mode, PyObject *buffering) { #if PYTHON_VERSION < 0x300 return BUILTIN_OPEN(filename, Nuitka_String_FromString(mode), buffering); #else return BUILTIN_OPEN(filename, Nuitka_String_FromString(mode), buffering, NULL, NULL, NULL, NULL, NULL); #endif } #if defined(_NUITKA_ONEFILE) && defined(_WIN32) static long onefile_ppid; DWORD WINAPI doOnefileParentMonitoring(LPVOID lpParam) { for (;;) { Sleep(1000); HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, onefile_ppid); if (handle == NULL) { if (GetLastError() == ERROR_INVALID_PARAMETER) { break; } else { continue; } } else { DWORD ret = WaitForSingleObject(handle, 0); CloseHandle(handle); if (ret == WAIT_OBJECT_0) { break; } } } // puts("Onefile parent monitoring kicks in."); PyErr_SetInterrupt(); return 0; } #endif static int HANDLE_PROGRAM_EXIT() { int exit_code; if (ERROR_OCCURRED()) { #if PYTHON_VERSION >= 0x300 /* Remove the frozen importlib traceback part, which would not be compatible. */ PyThreadState *thread_state = PyThreadState_GET(); while (thread_state->curexc_traceback) { PyTracebackObject *tb = (PyTracebackObject *)thread_state->curexc_traceback; PyFrameObject *frame = tb->tb_frame; if (0 == strcmp(PyUnicode_AsUTF8(frame->f_code->co_filename), "")) { thread_state->curexc_traceback = (PyObject *)tb->tb_next; Py_INCREF(tb->tb_next); continue; } break; } #endif PyErr_PrintEx(0); exit_code = 1; } else { exit_code = 0; } return exit_code; } static PyObject *EXECUTE_MAIN_MODULE(char const *module_name) { NUITKA_INIT_PROGRAM_LATE(module_name); #if NUITKA_MAIN_PACKAGE_MODE { char const *w = module_name; for (;;) { char const *s = strchr(w, '.'); if (s == NULL) { break; } w = s + 1; char buffer[1024]; memset(buffer, 0, sizeof(buffer)); memcpy(buffer, module_name, s - module_name); PyObject *result = IMPORT_EMBEDDED_MODULE(buffer); if (ERROR_OCCURRED()) { return result; } } } #endif return IMPORT_EMBEDDED_MODULE(module_name); } #if defined(_WIN32) && PYTHON_VERSION < 0x300 static char **getCommandLineToArgvA(char *lpCmdline) { char *s = lpCmdline; int argc = 1; if (*s == '"') { s++; while (*s != 0) { if (*s++ == '"') { break; } } } else { while (*s != 0 && *s != ' ' && *s != '\t') { s++; } } while (*s == ' ' || *s == '\t') { s++; } if (*s != 0) { argc++; } int quote_count = 0; int slash_count = 0; while (*s != 0) { if ((*s == ' ' || *s == '\t') && quote_count == 0) { while (*s == ' ' || *s == '\t') { s++; } if (*s != 0) { argc++; } slash_count = 0; } else if (*s == '\\') { slash_count++; s++; } else if (*s == '"') { if ((slash_count & 1) == 0) { quote_count++; } slash_count = 0; s++; while (*s == '"') { quote_count++; s++; } quote_count = quote_count % 3; if (quote_count == 2) { quote_count = 0; } } else { slash_count = 0; s++; } } char **argv = (char **)malloc((argc + 1) * sizeof(char *) + (strlen(lpCmdline) + 1)); assert(argv); char *cmdline = (char *)(argv + argc + 1); strcpy(cmdline, lpCmdline); argv[0] = cmdline; argc = 1; char *d = cmdline; if (*d == '"') { s = d + 1; while (*s != 0) { if (*s == '"') { s++; break; } *d++ = *s++; } } else { while (*d && *d != ' ' && *d != '\t') { d++; } s = d; if (*s) { s++; } } *d++ = 0; while (*s == ' ' || *s == '\t') { s++; } if (*s == 0) { argv[argc] = NULL; return argv; } argv[argc++] = d; quote_count = 0; slash_count = 0; while (*s != 0) { if ((*s == ' ' || *s == '\t') && quote_count == 0) { *d++ = 0; slash_count = 0; do { s++; } while (*s == ' ' || *s == '\t'); if (*s) { argv[argc++] = d; } } else if (*s == '\\') { *d++ = *s++; slash_count++; } else if (*s == '"') { if ((slash_count & 1) == 0) { d -= slash_count / 2; quote_count++; } else { d = d - slash_count / 2 - 1; *d++ = '"'; } s++; slash_count = 0; while (*s == '"') { if (++quote_count == 3) { *d++ = '"'; quote_count = 0; } s++; } if (quote_count == 2) quote_count = 0; } else { *d++ = *s++; slash_count = 0; } } *d = '\0'; argv[argc] = NULL; return argv; } #endif #ifdef _NUITKA_WINMAIN_ENTRY_POINT int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpCmdLine, int nCmdShow) { /* MSVC, MINGW64 */ int argc = __argc; wchar_t **argv = __wargv; #else #if defined(_WIN32) int wmain(int argc, wchar_t **argv) { #else int main(int argc, char **argv) { #endif #endif NUITKA_PRINT_TIMING("main(): Entered."); NUITKA_INIT_PROGRAM_EARLY(argc, argv); #ifdef __FreeBSD__ /* 754 requires that FP exceptions run in "no stop" mode by default, and * * until C vendors implement C99's ways to control FP exceptions, Python * requires non-stop mode. Alas, some platforms enable FP exceptions by * default. Here we disable them. */ fp_except_t m; m = fpgetmask(); fpsetmask(m & ~FP_X_OFL); #endif #ifdef _NUITKA_STANDALONE NUITKA_PRINT_TIMING("main(): Prepare standalone environment."); prepareStandaloneEnvironment(); #else #if PYTHON_VERSION >= 0x350 && defined(DLL_EXTRA_PATH) NUITKA_PRINT_TIMING("main(): Prepare DLL extra path."); SetDllDirectory(DLL_EXTRA_PATH); #endif #endif /* Initialize CPython library environment. */ Py_DebugFlag = 0; #if PYTHON_VERSION < 0x300 Py_Py3kWarningFlag = SYSFLAG_PY3K_WARNING; Py_DivisionWarningFlag = SYSFLAG_DIVISION_WARNING; Py_UnicodeFlag = SYSFLAG_UNICODE; Py_TabcheckFlag = 0; #endif Py_InspectFlag = 0; Py_InteractiveFlag = 0; Py_OptimizeFlag = SYSFLAG_OPTIMIZE; Py_DontWriteBytecodeFlag = 0; Py_NoUserSiteDirectory = SYSFLAG_NO_SITE; Py_IgnoreEnvironmentFlag = 0; Py_VerboseFlag = SYSFLAG_VERBOSE; Py_BytesWarningFlag = SYSFLAG_BYTES_WARNING; #if SYSFLAG_NO_RANDOMIZATION == 1 Py_HashRandomizationFlag = 0; #if PYTHON_VERSION < 0x300 // For Python2 this is all it takes to have static hashes. _PyRandom_Init(); #endif #endif #if PYTHON_VERSION >= 0x370 Py_UTF8Mode = SYSFLAG_UTF8; if (Py_UTF8Mode) { if (Py_FileSystemDefaultEncoding == NULL) { Py_FileSystemDefaultEncoding = "utf-8"; Py_HasFileSystemDefaultEncoding = 1; } } #endif #ifdef NUITKA_PYTHON_STATIC Py_InitStaticModules(); #endif /* This suppresses warnings from getpath.c */ Py_FrozenFlag = 1; /* We want to import the site module, but only after we finished our own * setup. The site module import will be the first thing, the main module * does. */ Py_NoSiteFlag = 1; /* Initial command line handling only. */ #if PYTHON_VERSION >= 0x300 && _NUITKA_NATIVE_WCHAR_ARGV == 0 NUITKA_PRINT_TRACE("main(): Calling convertCommandLineParameters."); orig_argv = convertCommandLineParameters(argc, argv); #elif PYTHON_VERSION < 0x300 && _NUITKA_NATIVE_WCHAR_ARGV == 1 orig_argv = getCommandLineToArgvA(GetCommandLineA()); #else orig_argv = argv; #endif orig_argc = argc; NUITKA_PRINT_TRACE("main(): Calling initial setCommandLineParameters."); setCommandLineParameters(argc, argv, true); /* For Python installations that need the home set, we inject it back here. */ #if defined(PYTHON_HOME_PATH) #if PYTHON_VERSION < 0x300 NUITKA_PRINT_TRACE("main(): Prepare run environment '" PYTHON_HOME_PATH "'."); Py_SetPythonHome(PYTHON_HOME_PATH); #else NUITKA_PRINTF_TRACE("main(): Prepare run environment '%S'.\n", L"" PYTHON_HOME_PATH); Py_SetPythonHome(L"" PYTHON_HOME_PATH); // Make sure the above Py_SetPythonHome call has effect already. Py_GetPath(); #endif #endif #if PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1 char const *old_env = getenv("PYTHONHASHSEED"); setenv("PYTHONHASHSEED", "0", 1); #endif /* Disable CPython warnings if requested to. */ #if NO_PYTHON_WARNINGS { #if PYTHON_VERSION >= 0x300 wchar_t ignore[] = L"ignore"; #else char ignore[] = "ignore"; #endif PySys_ResetWarnOptions(); PySys_AddWarnOption(ignore); } #endif // Workaround older Python not handling stream setup on redirected files properly. #if PYTHON_VERSION >= 0x340 && PYTHON_VERSION < 0x380 { char const *encoding = NULL; if (SYSFLAG_UTF8) { encoding = "utf-8"; } else { encoding = getenv("PYTHONIOENCODING"); if (encoding == NULL) { encoding = "utf-8"; } } Py_SetStandardStreamEncoding(encoding, NULL); } #endif /* Initialize the embedded CPython interpreter. */ NUITKA_PRINT_TIMING("main(): Calling Py_Initialize to initialize interpreter."); Py_Initialize(); #if PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1 if (old_env) { setenv("PYTHONHASHSEED", old_env, 1); PyObject *env_value = PyUnicode_FromString(old_env); PyObject *hashseed_str = PyUnicode_FromString("PYTHONHASHSEED"); int res = PyObject_SetItem(PyObject_GetAttrString(PyImport_ImportModule("os"), "environ"), hashseed_str, env_value); assert(res == 0); Py_DECREF(env_value); Py_DECREF(hashseed_str); } else { unsetenv("PYTHONHASHSEED"); int res = PyObject_DelItemString(PyObject_GetAttrString(PyImport_ImportModule("os"), "environ"), "PYTHONHASHSEED"); assert(res == 0); } #endif #ifdef _NUITKA_STANDALONE NUITKA_PRINT_TRACE("main(): Restore standalone environment."); restoreStandaloneEnvironment(); #endif /* Lie about it, believe it or not, there are "site" files, that check * against later imports, see below. */ Py_NoSiteFlag = SYSFLAG_NO_SITE; /* Set the command line parameters for run time usage. */ NUITKA_PRINT_TRACE("main(): Calling setCommandLineParameters."); setCommandLineParameters(argc, argv, false); PySys_SetArgv(argc, orig_argv); /* Initialize the built-in module tricks used and builtin-type methods */ NUITKA_PRINT_TRACE("main(): Calling _initBuiltinModule()."); _initBuiltinModule(); /* Initialize the Python constant values used. This also sets * "sys.executable" while at it. */ NUITKA_PRINT_TIMING("main(): Calling createGlobalConstants()."); createGlobalConstants(); NUITKA_PRINT_TIMING("main(): Returned createGlobalConstants()."); /* Complex call helpers need "__main__" constants, even if we only * go into "__parents__main__" module as a start point. */ NUITKA_PRINT_TIMING("main(): Calling createMainModuleConstants()."); createMainModuleConstants(); NUITKA_PRINT_TIMING("main(): Returned createMainModuleConstants()."); NUITKA_PRINT_TRACE("main(): Calling _initBuiltinOriginalValues()."); _initBuiltinOriginalValues(); /* Revert the wrong "sys.flags" value, it's used by "site" on at least * Debian for Python 3.3, more uses may exist. */ #if SYSFLAG_NO_SITE == 0 #if PYTHON_VERSION < 0x300 PyStructSequence_SET_ITEM(Nuitka_SysGetObject("flags"), 9, const_int_0); #else PyStructSequence_SetItem(Nuitka_SysGetObject("flags"), 6, const_int_0); #endif #endif /* Initialize the compiled types of Nuitka. */ _initCompiledCellType(); _initCompiledGeneratorType(); _initCompiledFunctionType(); _initCompiledMethodType(); _initCompiledFrameType(); _initSlotCompare(); #if PYTHON_VERSION >= 0x270 _initSlotIternext(); #endif NUITKA_PRINT_TRACE("main(): Calling enhancePythonTypes()."); enhancePythonTypes(); NUITKA_PRINT_TRACE("main(): Calling patchBuiltinModule()."); patchBuiltinModule(); NUITKA_PRINT_TRACE("main(): Calling patchTypeComparison()."); patchTypeComparison(); NUITKA_PRINT_TRACE("main(): Calling patchTracebackDealloc()."); patchTracebackDealloc(); #ifndef NUITKA_USE_PYCORE_THREADSTATE /* Allow to override the ticker value, to remove checks for threads in * CPython core from impact on benchmarks. */ char const *ticker_value = getenv("NUITKA_TICKER"); if (ticker_value != NULL) { _Py_Ticker = atoi(ticker_value); assert(_Py_Ticker >= 20); } #endif /* At least on Windows, we support disabling the console via linker flag, but now need to provide the NUL standard file handles manually in this case. */ { PyObject *nul_filename = Nuitka_String_FromString("NUL:"); PyObject *sys_stdin = Nuitka_SysGetObject("stdin"); if (sys_stdin == NULL || sys_stdin == Py_None) { PyObject *stdin_file = BUILTIN_OPEN_SIMPLE(nul_filename, "r", NULL); CHECK_OBJECT(stdin_file); Nuitka_SysSetObject("stdin", stdin_file); } PyObject *sys_stdout = Nuitka_SysGetObject("stdout"); if (sys_stdout == NULL || sys_stdout == Py_None) { PyObject *stdout_file = BUILTIN_OPEN_SIMPLE(nul_filename, "w", NULL); CHECK_OBJECT(stdout_file); Nuitka_SysSetObject("stdout", stdout_file); } PyObject *sys_stderr = Nuitka_SysGetObject("stderr"); if (sys_stderr == NULL || sys_stderr == Py_None) { PyObject *stderr_file = BUILTIN_OPEN_SIMPLE(nul_filename, "w", NULL); CHECK_OBJECT(stderr_file); Nuitka_SysSetObject("stderr", stderr_file); } Py_DECREF(nul_filename); } #if defined(NUITKA_FORCED_STDOUT_PATH) { wchar_t filename_buffer[1024]; wchar_t const *pattern = L"" NUITKA_FORCED_STDOUT_PATH; bool res = expandTemplatePathW(filename_buffer, pattern, sizeof(filename_buffer) / sizeof(wchar_t)); if (res == false) { puts("Error, couldn't expand pattern:"); _putws(pattern); abort(); } PyObject *filename = NuitkaUnicode_FromWideChar(filename_buffer, -1); PyObject *stdout_file = BUILTIN_OPEN_SIMPLE(filename, "w", const_int_pos_1); if (unlikely(stdout_file == NULL)) { PyErr_PrintEx(1); Py_Exit(1); } Nuitka_SysSetObject("stdout", stdout_file); } #endif #if defined(NUITKA_FORCED_STDERR_PATH) { wchar_t filename_buffer[1024]; wchar_t const *pattern = L"" NUITKA_FORCED_STDERR_PATH; bool res = expandTemplatePathW(filename_buffer, pattern, sizeof(filename_buffer) / sizeof(wchar_t)); if (res == false) { puts("Error, couldn't expand pattern:"); _putws(pattern); abort(); } PyObject *filename = NuitkaUnicode_FromWideChar(filename_buffer, -1); PyObject *stderr_file = BUILTIN_OPEN_SIMPLE(filename, "w", const_int_pos_1); if (unlikely(stderr_file == NULL)) { PyErr_PrintEx(1); Py_Exit(1); } Nuitka_SysSetObject("stderr", stderr_file); } #endif #ifdef _NUITKA_STANDALONE NUITKA_PRINT_TRACE("main(): Calling setEarlyFrozenModulesFileAttribute()."); setEarlyFrozenModulesFileAttribute(); #endif #if _NUITKA_FROZEN > 0 NUITKA_PRINT_TRACE("main(): Removing early frozen module table again."); PyImport_FrozenModules = old_frozen; assert(old_frozen != NULL); #endif NUITKA_PRINT_TRACE("main(): Calling setupMetaPathBasedLoader()."); /* Enable meta path based loader. */ setupMetaPathBasedLoader(); /* Initialize warnings module. */ _PyWarnings_Init(); #if NO_PYTHON_WARNINGS && PYTHON_VERSION >= 0x342 && PYTHON_VERSION < 0x3a0 && defined(_NUITKA_FULL_COMPAT) // For full compatibility bump the warnings registry version, // otherwise modules "__warningsregistry__" will mismatch. PyObject *warnings_module = PyImport_ImportModule("warnings"); PyObject *meth = PyObject_GetAttrString(warnings_module, "_filters_mutated"); CALL_FUNCTION_NO_ARGS(meth); #if PYTHON_VERSION < 0x380 // Two times, so "__warningregistry__" version matches. CALL_FUNCTION_NO_ARGS(meth); #endif #endif #if PYTHON_VERSION >= 0x300 NUITKA_PRINT_TRACE("main(): Calling patchInspectModule()."); patchInspectModule(); #endif #if _NUITKA_PROFILE // Profiling with "vmprof" if enabled. startProfiling(); #endif #if _NUITKA_PGO_PYTHON // Profiling with our own Python PGO if enabled. PGO_Initialize(); #endif /* Execute the main module unless plugins want to do something else. In case of multiprocessing making a fork on Windows, we should execute "__parents_main__" instead. And for Windows Service we call the plugin C code to call us back to launch main code in a callback. */ #ifdef _NUITKA_PLUGIN_MULTIPROCESSING_ENABLED if (unlikely(is_multiprocessing_fork)) { NUITKA_PRINT_TRACE("main(): Calling __parents_main__."); EXECUTE_MAIN_MODULE("__parents_main__"); int exit_code = HANDLE_PROGRAM_EXIT(); NUITKA_PRINT_TRACE("main(): Calling __parents_main__ Py_Exit."); // TODO: Should maybe call Py_Exit here, but there were issues with that. exit(exit_code); } else if (unlikely(multiprocessing_resource_tracker_arg != NULL)) { NUITKA_PRINT_TRACE("main(): Calling resource_tracker."); PyObject *resource_tracker_module = EXECUTE_MAIN_MODULE("multiprocessing.resource_tracker"); PyObject *main_function = PyObject_GetAttrString(resource_tracker_module, "main"); CALL_FUNCTION_WITH_SINGLE_ARG(main_function, multiprocessing_resource_tracker_arg); int exit_code = HANDLE_PROGRAM_EXIT(); NUITKA_PRINT_TRACE("main(): Calling resource_tracker Py_Exit."); // TODO: Should maybe call Py_Exit here, but there were issues with that. exit(exit_code); } else { #endif #if defined(_NUITKA_ONEFILE) && defined(_WIN32) { char buffer[128] = {0}; DWORD size = GetEnvironmentVariableA("NUITKA_ONEFILE_PARENT", buffer, sizeof(buffer)); if (size > 0 && size < 127) { onefile_ppid = atol(buffer); CreateThread(NULL, 0, doOnefileParentMonitoring, NULL, 0, NULL); } } #endif PyDict_DelItemString(PyImport_GetModuleDict(), NUITKA_MAIN_MODULE_NAME); #if _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED NUITKA_PRINT_TRACE("main(): Calling plugin SvcLaunchService() entry point."); SvcLaunchService(); #else /* Execute the "__main__" module. */ NUITKA_PRINT_TIMING("main(): Calling " NUITKA_MAIN_MODULE_NAME "."); EXECUTE_MAIN_MODULE(NUITKA_MAIN_MODULE_NAME); NUITKA_PRINT_TIMING("main(): Exited from " NUITKA_MAIN_MODULE_NAME "."); #endif #ifdef _NUITKA_PLUGIN_MULTIPROCESSING_ENABLED } #endif #if _NUITKA_PROFILE stopProfiling(); #endif #if _NUITKA_PGO_PYTHON // Write out profiling with our own Python PGO if enabled. PGO_Finalize(); #endif #ifndef __NUITKA_NO_ASSERT__ checkGlobalConstants(); /* TODO: Walk over all loaded compiled modules, and make this kind of checks. */ #if !NUITKA_MAIN_PACKAGE_MODE checkModuleConstants___main__(); #endif #endif int exit_code = HANDLE_PROGRAM_EXIT(); #if _DEBUG_REFCOUNTS PRINT_REFCOUNTS(); #endif NUITKA_PRINT_TIMING("main(): Calling Py_Exit."); Py_Exit(exit_code); // The "Py_Exit()" calls is not supposed to return. NUITKA_CANNOT_GET_HERE("Py_Exit does not return"); } /* This is an unofficial API, not available on Windows, but on Linux and others * it is exported, and has been used by some code. */ #ifndef _WIN32 #ifdef __cplusplus extern "C" { #endif #if PYTHON_VERSION >= 0x300 #if defined(__GNUC__) __attribute__((weak)) __attribute__((visibility("default"))) #endif void Py_GetArgcArgv(int *argc, wchar_t ***argv) { *argc = orig_argc; *argv = orig_argv; } #else #if defined(__GNUC__) __attribute__((weak)) __attribute__((visibility("default"))) #endif void Py_GetArgcArgv(int *argc, char ***argv) { *argc = orig_argc; *argv = orig_argv; } #endif #ifdef __cplusplus } #endif #endif Nuitka-0.6.19.1/nuitka/build/static_src/HelpersCalling.c0000600000372100037210000003116314166627112030063 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif PyObject *callPythonFunction(PyObject *func, PyObject *const *args, int count) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); #if PYTHON_VERSION >= 0x300 PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); if (kwdefs == NULL && argdefs == NULL && co->co_argcount == count && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) #else if (argdefs == NULL && co->co_argcount == count && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) #endif { PyThreadState *tstate = PyThreadState_GET(); CHECK_OBJECT(globals); PyFrameObject *frame = PyFrame_New(tstate, co, globals, NULL); if (unlikely(frame == NULL)) { return NULL; }; for (int i = 0; i < count; i++) { frame->f_localsplus[i] = args[i]; Py_INCREF(frame->f_localsplus[i]); } #if PYTHON_VERSION < 0x390 PyObject *result = PyEval_EvalFrameEx(frame, 0); #else PyObject *result = _PyEval_EvalFrame(tstate, frame, 0); #endif // Frame release protects against recursion as it may lead to variable // destruction. ++tstate->recursion_depth; Py_DECREF(frame); --tstate->recursion_depth; return result; } PyObject **defaults = NULL; int num_defaults = 0; if (argdefs != NULL) { defaults = &PyTuple_GET_ITEM(argdefs, 0); num_defaults = (int)(Py_SIZE(argdefs)); } PyObject *result = PyEval_EvalCodeEx( #if PYTHON_VERSION >= 0x300 (PyObject *)co, #else co, // code object #endif globals, // globals NULL, // no locals (PyObject **)args, // args count, // argcount NULL, // kwds 0, // kwcount defaults, // defaults num_defaults, // defcount #if PYTHON_VERSION >= 0x300 kwdefs, #endif PyFunction_GET_CLOSURE(func)); return result; } static PyObject *_fast_function_noargs(PyObject *func) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); #if PYTHON_VERSION >= 0x300 PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); if (kwdefs == NULL && argdefs == NULL && co->co_argcount == 0 && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) #else if (argdefs == NULL && co->co_argcount == 0 && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) #endif { PyThreadState *tstate = PyThreadState_GET(); CHECK_OBJECT(globals); PyFrameObject *frame = PyFrame_New(tstate, co, globals, NULL); if (unlikely(frame == NULL)) { return NULL; }; PyObject *result = PyEval_EvalFrameEx(frame, 0); // Frame release protects against recursion as it may lead to variable // destruction. ++tstate->recursion_depth; Py_DECREF(frame); --tstate->recursion_depth; return result; } PyObject **defaults = NULL; int num_defaults = 0; if (argdefs != NULL) { defaults = &PyTuple_GET_ITEM(argdefs, 0); num_defaults = (int)(Py_SIZE(argdefs)); } PyObject *result = PyEval_EvalCodeEx( #if PYTHON_VERSION >= 0x300 (PyObject *)co, #else co, // code object #endif globals, // globals NULL, // no locals NULL, // args 0, // argcount NULL, // kwds 0, // kwcount defaults, // defaults num_defaults, // defcount #if PYTHON_VERSION >= 0x300 kwdefs, #endif PyFunction_GET_CLOSURE(func)); return result; } PyObject *CALL_METHOD_WITH_POSARGS(PyObject *source, PyObject *attr_name, PyObject *positional_args) { CHECK_OBJECT(source); CHECK_OBJECT(attr_name); CHECK_OBJECT(positional_args); #if PYTHON_VERSION < 0x300 if (PyInstance_Check(source)) { PyInstanceObject *source_instance = (PyInstanceObject *)source; // The special cases have their own variant on the code generation level // as we are called with constants only. assert(attr_name != const_str_plain___dict__); assert(attr_name != const_str_plain___class__); // Try the instance dict first. PyObject *called_object = GET_STRING_DICT_VALUE((PyDictObject *)source_instance->in_dict, (PyStringObject *)attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { return CALL_FUNCTION_WITH_POSARGS(called_object, positional_args); } // Then check the class dictionaries. called_object = FIND_ATTRIBUTE_IN_CLASS(source_instance->in_class, attr_name); // Note: The "called_object" was found without taking a reference, // so we need not release it in this branch. if (called_object != NULL) { descrgetfunc descr_get = Py_TYPE(called_object)->tp_descr_get; if (descr_get == Nuitka_Function_Type.tp_descr_get) { return Nuitka_CallMethodFunctionPosArgs((struct Nuitka_FunctionObject const *)called_object, source, &PyTuple_GET_ITEM(positional_args, 0), PyTuple_GET_SIZE(positional_args)); } else if (descr_get != NULL) { PyObject *method = descr_get(called_object, source, (PyObject *)source_instance->in_class); if (unlikely(method == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_POSARGS(method, positional_args); Py_DECREF(method); return result; } else { return CALL_FUNCTION_WITH_POSARGS(called_object, positional_args); } } else if (unlikely(source_instance->in_class->cl_getattr == NULL)) { PyErr_Format(PyExc_AttributeError, "%s instance has no attribute '%s'", PyString_AS_STRING(source_instance->in_class->cl_name), PyString_AS_STRING(attr_name)); return NULL; } else { // Finally allow the "__getattr__" override to provide it or else // it's an error. PyObject *args[] = {source, attr_name}; called_object = CALL_FUNCTION_WITH_ARGS2(source_instance->in_class->cl_getattr, args); if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_POSARGS(called_object, positional_args); Py_DECREF(called_object); return result; } } else #endif { PyObject *called_object; PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro != NULL) { called_object = (*type->tp_getattro)(source, attr_name); } else if (type->tp_getattr != NULL) { called_object = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); } else { SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } if (unlikely(called_object == NULL)) { return NULL; } PyObject *result = CALL_FUNCTION_WITH_POSARGS(called_object, positional_args); Py_DECREF(called_object); return result; } } char const *GET_CALLABLE_NAME(PyObject *object) { if (Nuitka_Function_Check(object)) { return Nuitka_String_AsString(Nuitka_Function_GetName(object)); } else if (Nuitka_Generator_Check(object)) { return Nuitka_String_AsString(Nuitka_Generator_GetName(object)); } else if (PyMethod_Check(object)) { return PyEval_GetFuncName(PyMethod_GET_FUNCTION(object)); } else if (PyFunction_Check(object)) { return Nuitka_String_AsString(((PyFunctionObject *)object)->func_name); } #if PYTHON_VERSION < 0x300 else if (PyInstance_Check(object)) { return Nuitka_String_AsString(((PyInstanceObject *)object)->in_class->cl_name); } else if (PyClass_Check(object)) { return Nuitka_String_AsString(((PyClassObject *)object)->cl_name); } #endif else if (PyCFunction_Check(object)) { return ((PyCFunctionObject *)object)->m_ml->ml_name; } else { return Py_TYPE(object)->tp_name; } } char const *GET_CALLABLE_DESC(PyObject *object) { if (Nuitka_Function_Check(object) || Nuitka_Generator_Check(object) || PyMethod_Check(object) || PyFunction_Check(object) || PyCFunction_Check(object)) { return "()"; } #if PYTHON_VERSION < 0x300 else if (PyClass_Check(object)) { return " constructor"; } else if (PyInstance_Check(object)) { return " instance"; } #endif else { return " object"; } } char const *GET_CLASS_NAME(PyObject *klass) { if (klass == NULL) { return "?"; } else { #if PYTHON_VERSION < 0x300 if (PyClass_Check(klass)) { return Nuitka_String_AsString(((PyClassObject *)klass)->cl_name); } #endif if (!PyType_Check(klass)) { klass = (PyObject *)Py_TYPE(klass); } return ((PyTypeObject *)klass)->tp_name; } } char const *GET_INSTANCE_CLASS_NAME(PyObject *instance) { PyObject *klass = PyObject_GetAttr(instance, const_str_plain___class__); // Fallback to type as this cannot fail. if (klass == NULL) { CLEAR_ERROR_OCCURRED(); klass = (PyObject *)Py_TYPE(instance); Py_INCREF(klass); } char const *result = GET_CLASS_NAME(klass); Py_DECREF(klass); return result; } static PyObject *getTypeAbstractMethods(PyTypeObject *type, void *context) { PyObject *result = DICT_GET_ITEM_WITH_ERROR(type->tp_dict, const_str_plain___abstractmethods__); if (unlikely(result == NULL)) { if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyExc_AttributeError, const_str_plain___abstractmethods__); } return NULL; } return result; } void formatCannotInstantiateAbstractClass(PyTypeObject *type) { PyObject *abstract_methods = getTypeAbstractMethods(type, NULL); if (unlikely(abstract_methods == NULL)) { return; } PyObject *sorted_methods = PySequence_List(abstract_methods); Py_DECREF(abstract_methods); if (unlikely(sorted_methods == NULL)) { return; } if (unlikely(PyList_Sort(sorted_methods))) { Py_DECREF(sorted_methods); return; } PyObject *comma = Nuitka_String_FromString(", "); CHECK_OBJECT(comma); #if PYTHON_VERSION < 0x300 PyObject *joined = CALL_METHOD_WITH_SINGLE_ARG(comma, const_str_plain_join, sorted_methods); char const *joined_str = Nuitka_String_AsString(joined); if (unlikely(joined_str == NULL)) { Py_DECREF(joined); return; } #else PyObject *joined = PyUnicode_Join(comma, sorted_methods); #endif Py_DECREF(sorted_methods); if (unlikely(joined == NULL)) { return; } Py_ssize_t method_count = PyList_GET_SIZE(sorted_methods); SET_CURRENT_EXCEPTION_TYPE0_FORMAT3(PyExc_TypeError, "Can't instantiate abstract class %s with abstract method%s %s", type->tp_name, method_count > 1 ? "s" : "", Nuitka_String_AsString(joined)); Py_DECREF(joined); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersConstantsBlob.c0000600000372100037210000010266514166627112031273 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** Providing access to the constants binary blob. * * There are multiple ways, the constants binary is accessed, and its * definition depends on how that is done. * * This deals with loading the resource from a DLL under Windows. * */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include #if _NUITKA_EXPERIMENTAL_WRITEABLE_CONSTANTS #define CONST_CONSTANT #else #define CONST_CONSTANT const #endif #if defined(_NUITKA_CONSTANTS_FROM_LINKER) // Symbol as provided by the linker, different for C++ and C11 mode. #ifdef __cplusplus extern "C" CONST_CONSTANT unsigned char constant_bin_data[]; #else extern CONST_CONSTANT unsigned char constant_bin_data[0]; #endif unsigned char const *constant_bin = &constant_bin_data[0]; #elif defined(_NUITKA_CONSTANTS_FROM_CODE) extern CONST_CONSTANT unsigned char constant_bin_data[]; unsigned char const *constant_bin = &constant_bin_data[0]; #else // Symbol to be assigned locally. unsigned char const *constant_bin = NULL; #endif #if defined(_NUITKA_CONSTANTS_FROM_INCBIN) extern unsigned const char *getConstantsBlobData(); #endif // No Python runtime yet, need to do this manually. static uint32_t calcCRC32(unsigned char const *message, uint32_t size) { uint32_t crc = 0xFFFFFFFF; for (uint32_t i = 0; i < size; i++) { unsigned int c = message[i]; crc = crc ^ c; for (int j = 7; j >= 0; j--) { uint32_t mask = ((crc & 1) != 0) ? 0xFFFFFFFF : 0; crc = (crc >> 1) ^ (0xEDB88320 & mask); } } return ~crc; } #if PYTHON_VERSION < 0x300 static PyObject *int_cache = NULL; #endif static PyObject *long_cache = NULL; static PyObject *float_cache = NULL; #if PYTHON_VERSION >= 0x300 static PyObject *bytes_cache = NULL; #endif #if PYTHON_VERSION < 0x300 static PyObject *unicode_cache = NULL; #endif static PyObject *tuple_cache = NULL; static PyObject *list_cache = NULL; static PyObject *dict_cache = NULL; static PyObject *set_cache = NULL; static PyObject *frozenset_cache = NULL; // Use our own non-random hash for some of the things to be fast. This is inspired // from the original Python2 hash func, but we are mostly using it on pointer values static Py_hash_t Nuitka_FastHashBytes(const void *value, Py_ssize_t size) { if (unlikely(size == 0)) { return 0; } unsigned char *w = (unsigned char *)value; long x = *w << 7; while (--size >= 0) { x = (1000003 * x) ^ *w++; } x ^= size; // The value -1 is reserved for errors. if (x == -1) { x = -2; } return x; } static Py_hash_t our_list_hash(PyListObject *list) { return Nuitka_FastHashBytes(&list->ob_item[0], Py_SIZE(list) * sizeof(PyObject *)); } static PyObject *our_list_richcompare(PyListObject *list1, PyListObject *list2, int op) { assert(op == Py_EQ); PyObject *result; if (list1 == list2) { result = Py_True; } else if (Py_SIZE(list1) != Py_SIZE(list2)) { result = Py_False; } else if (memcmp(&list1->ob_item[0], &list2->ob_item[0], Py_SIZE(list1) * sizeof(PyObject *)) == 0) { result = Py_True; } else { result = Py_False; } Py_INCREF(result); return result; } static Py_hash_t our_tuple_hash(PyTupleObject *tuple) { return Nuitka_FastHashBytes(&tuple->ob_item[0], Py_SIZE(tuple) * sizeof(PyObject *)); } static PyObject *our_tuple_richcompare(PyTupleObject *tuple1, PyTupleObject *tuple2, int op) { assert(op == Py_EQ); PyObject *result; if (tuple1 == tuple2) { result = Py_True; } else if (Py_SIZE(tuple1) != Py_SIZE(tuple2)) { result = Py_False; } else if (memcmp(&tuple1->ob_item[0], &tuple2->ob_item[0], Py_SIZE(tuple1) * sizeof(PyObject *)) == 0) { result = Py_True; } else { result = Py_False; } Py_INCREF(result); return result; } static Py_hash_t our_set_hash(PyObject *set) { Py_hash_t result = 0; PyObject *key; Py_ssize_t pos = 0; #if PYTHON_VERSION < 0x300 // Same sized set, simply check if values are identical. Other reductions should // make it identical, or else this won't have the effect intended. while (_PySet_Next(set, &pos, &key)) { result *= 1000003; result ^= Nuitka_FastHashBytes(key, sizeof(PyObject *)); } #else Py_hash_t unused; while (_PySet_NextEntry(set, &pos, &key, &unused)) { result *= 1000003; result ^= Nuitka_FastHashBytes(key, sizeof(PyObject *)); } #endif return result; } static PyObject *our_set_richcompare(PyObject *set1, PyObject *set2, int op) { assert(op == Py_EQ); Py_ssize_t pos1 = 0, pos2 = 0; PyObject *key1, *key2; #if PYTHON_VERSION < 0x300 // Same sized set, simply check if values are identical. Other reductions should // make it identical, or else this won't have the effect intended. while (_PySet_Next(set1, &pos1, &key1)) { int res = _PySet_Next(set2, &pos2, &key2); assert(res != 0); if (key1 != key2) { PyObject *result = Py_False; Py_INCREF(result); return result; } } #else Py_hash_t unused; // Same sized dictionary, simply check if values are identical. Other reductions should // make it identical, or else this won't have the effect intended. while (_PySet_NextEntry(set1, &pos1, &key1, &unused)) { int res = _PySet_NextEntry(set2, &pos2, &key2, &unused); assert(res != 0); if (key1 != key2) { PyObject *result = Py_False; Py_INCREF(result); return result; } } #endif PyObject *result = Py_True; Py_INCREF(result); return result; } static PyObject *our_float_richcompare(PyFloatObject *a, PyFloatObject *b, int op) { assert(op == Py_EQ); PyObject *result; // Avoid the C math when comparing, for it makes too many values equal or unequal. if (memcmp(&a->ob_fval, &b->ob_fval, sizeof(b->ob_fval)) == 0) { result = Py_True; } else { result = Py_False; } Py_INCREF(result); return result; } static Py_hash_t our_dict_hash(PyObject *dict) { Py_hash_t result = 0; Py_ssize_t ppos = 0; PyObject *key, *value; while (PyDict_Next(dict, &ppos, &key, &value)) { result *= 1000003; result ^= Nuitka_FastHashBytes(key, sizeof(PyObject *)); result *= 1000003; result ^= Nuitka_FastHashBytes(value, sizeof(PyObject *)); } return result; } static PyObject *our_dict_richcompare(PyObject *a, PyObject *b, int op) { PyObject *result; if (Py_SIZE(a) != Py_SIZE(b)) { result = Py_False; } else { result = Py_True; Py_ssize_t ppos1 = 0, ppos2 = 0; PyObject *key1, *value1; PyObject *key2, *value2; // Same sized dictionary, simply check if key and values are identical. // Other reductions should make it identical, or else this won't have the // effect intended. while (PyDict_Next(a, &ppos1, &key1, &value1)) { int res = PyDict_Next(b, &ppos2, &key2, &value2); assert(res != 0); if (key1 != key2 || value1 != value2) { result = Py_False; break; } } } Py_INCREF(result); return result; } #if PYTHON_VERSION >= 0x300 // For creation of small long singleton long values as required by Python3. PyObject *Nuitka_Long_SmallValues[NUITKA_STATIC_SMALLINT_VALUE_MAX - NUITKA_STATIC_SMALLINT_VALUE_MIN + 1]; #endif static void initCaches(void) { static bool init_done = false; if (init_done == true) { return; } #if PYTHON_VERSION < 0x300 int_cache = PyDict_New(); #endif long_cache = PyDict_New(); float_cache = PyDict_New(); #if PYTHON_VERSION >= 0x300 bytes_cache = PyDict_New(); #endif #if PYTHON_VERSION < 0x300 unicode_cache = PyDict_New(); #endif tuple_cache = PyDict_New(); list_cache = PyDict_New(); dict_cache = PyDict_New(); set_cache = PyDict_New(); frozenset_cache = PyDict_New(); for (long i = NUITKA_STATIC_SMALLINT_VALUE_MIN; i <= NUITKA_STATIC_SMALLINT_VALUE_MAX; i++) { #if PYTHON_VERSION >= 0x300 PyObject *value = PyLong_FromLong(i); Py_INCREF(value); Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(i)] = value; #endif } init_done = true; } static void insertToDictCache(PyObject *dict, PyObject **value) { PyObject *item = PyDict_GetItem(dict, *value); if (item != NULL) { *value = item; } else { PyDict_SetItem(dict, *value, *value); } } static void insertToDictCacheForcedHash(PyObject *dict, PyObject **value, hashfunc tp_hash, richcmpfunc tp_richcompare) { hashfunc old_hash = Py_TYPE(*value)->tp_hash; richcmpfunc old_richcmp = Py_TYPE(*value)->tp_richcompare; // Hash is optional, e.g. for floats we can spare us doing our own hash, // but we do equality if (tp_hash != NULL) { Py_TYPE(*value)->tp_hash = tp_hash; } Py_TYPE(*value)->tp_richcompare = tp_richcompare; insertToDictCache(dict, value); Py_TYPE(*value)->tp_hash = old_hash; Py_TYPE(*value)->tp_richcompare = old_richcmp; } static uint16_t unpackValueUint16(unsigned char const **data) { uint16_t value; memcpy(&value, *data, sizeof(value)); assert(sizeof(value) == 2); *data += sizeof(value); return value; } static uint32_t unpackValueUint32(unsigned char const **data) { uint32_t value; memcpy(&value, *data, sizeof(value)); assert(sizeof(value) == 4); *data += sizeof(value); return value; } static int unpackValueInt(unsigned char const **data) { int size; memcpy(&size, *data, sizeof(size)); *data += sizeof(size); return size; } static long unpackValueLong(unsigned char const **data) { long size; memcpy(&size, *data, sizeof(size)); *data += sizeof(size); return size; } static long long unpackValueLongLong(unsigned char const **data) { long long size; memcpy(&size, *data, sizeof(size)); *data += sizeof(size); return size; } static unsigned long long unpackValueUnsignedLongLong(unsigned char const **data) { unsigned long long size; memcpy(&size, *data, sizeof(size)); *data += sizeof(size); return size; } static double unpackValueFloat(unsigned char const **data) { double size; memcpy(&size, *data, sizeof(size)); *data += sizeof(size); return size; } static unsigned char const *_unpackValueCString(unsigned char const *data) { while (*(data++) != 0) { } return data; } static PyObject *_unpackAnonValue(unsigned char anon_index) { switch (anon_index) { case 0: return (PyObject *)Py_TYPE(Py_None); case 1: return (PyObject *)&PyEllipsis_Type; case 2: return (PyObject *)Py_TYPE(Py_NotImplemented); case 3: return (PyObject *)&PyFunction_Type; case 4: return (PyObject *)&PyGen_Type; case 5: return (PyObject *)&PyCFunction_Type; case 6: return (PyObject *)&PyCode_Type; #if PYTHON_VERSION < 0x300 case 7: return (PyObject *)&PyFile_Type; case 8: return (PyObject *)&PyClass_Type; case 9: return (PyObject *)&PyInstance_Type; case 10: return (PyObject *)&PyMethod_Type; #endif default: PRINT_FORMAT("Missing anon value for %d\n", (int)anon_index); NUITKA_CANNOT_GET_HERE("Corrupt constants blob"); } } PyObject *_unpackSpecialValue(unsigned char special_index) { switch (special_index) { case 0: return PyObject_GetAttrString((PyObject *)builtin_module, "Ellipsis"); case 1: return PyObject_GetAttrString((PyObject *)builtin_module, "NotImplemented"); case 2: return Py_SysVersionInfo; default: PRINT_FORMAT("Missing special value for %d\n", (int)special_index); NUITKA_CANNOT_GET_HERE("Corrupt constants blob"); } } static unsigned char const *_unpackBlobConstants(PyObject **output, unsigned char const *data, int count) { for (int _i = 0; _i < count; _i++) { // Make sure we discover failures to assign. *output = NULL; bool is_object; char c = *((char const *)data++); #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS unsigned char const *data_old = data; PRINT_FORMAT("Type %c for %d of %d:\n", c, _i, count); #endif switch (c) { case 'p': { assert(_i > 0); *output = *(output - 1); is_object = true; break; } case 'T': { // TODO: Use fixed sizes // uint32_t size = unpackSizeUint32(&data); int size = unpackValueInt(&data); PyObject *t = PyTuple_New(size); if (size > 0) { data = _unpackBlobConstants(&PyTuple_GET_ITEM(t, 0), data, size); } insertToDictCacheForcedHash(tuple_cache, &t, (hashfunc)our_tuple_hash, (richcmpfunc)our_tuple_richcompare); *output = t; is_object = true; break; } case 'L': { // TODO: Use fixed sizes // uint32_t size = unpackSizeUint32(&data); int size = unpackValueInt(&data); PyObject *l = PyList_New(size); if (size > 0) { data = _unpackBlobConstants(&PyList_GET_ITEM(l, 0), data, size); } insertToDictCacheForcedHash(list_cache, &l, (hashfunc)our_list_hash, (richcmpfunc)our_list_richcompare); *output = l; is_object = true; break; } case 'D': { // TODO: Use flexible sizes with bias towards small values. // uint32_t size = unpackSizeUint32(&data); int size = unpackValueInt(&data); PyObject *d = _PyDict_NewPresized(size); if (size > 0) { NUITKA_DYNAMIC_ARRAY_DECL(keys, PyObject *, size); NUITKA_DYNAMIC_ARRAY_DECL(values, PyObject *, size); data = _unpackBlobConstants(&keys[0], data, size); data = _unpackBlobConstants(&values[0], data, size); for (int i = 0; i < size; i++) { PyDict_SetItem(d, keys[i], values[i]); } } insertToDictCacheForcedHash(dict_cache, &d, (hashfunc)our_dict_hash, (richcmpfunc)our_dict_richcompare); *output = d; is_object = true; break; } case 'P': case 'S': { // TODO: Use fixed sizes // uint32_t size = unpackSizeUint32(&data); int size = unpackValueInt(&data); PyObject *s; if (c == 'S') { s = PySet_New(NULL); } else { if (size == 0) { // Get at the frozenset singleton of CPython and use it too. Some things // rely on it being a singleton across the board. static PyObject *empty_frozenset = NULL; if (empty_frozenset == NULL) { empty_frozenset = CALL_FUNCTION_WITH_SINGLE_ARG((PyObject *)&PyFrozenSet_Type, PyBytes_FromString("")); } s = empty_frozenset; } else { s = PyFrozenSet_New(NULL); } } if (size > 0) { NUITKA_DYNAMIC_ARRAY_DECL(values, PyObject *, size); data = _unpackBlobConstants(&values[0], data, size); for (int i = 0; i < size; i++) { PySet_Add(s, values[i]); } } // sets are cached globally too. if (c == 'S') { insertToDictCacheForcedHash(set_cache, &s, (hashfunc)our_set_hash, (richcmpfunc)our_set_richcompare); } else { insertToDictCacheForcedHash(frozenset_cache, &s, (hashfunc)our_set_hash, (richcmpfunc)our_set_richcompare); } *output = s; is_object = true; break; } #if PYTHON_VERSION < 0x300 case 'i': { // TODO: Use fixed sizes for small values, e.g. byte sized. long value = unpackValueLong(&data); PyObject *i = PyInt_FromLong(value); insertToDictCache(int_cache, &i); *output = i; is_object = true; break; } #endif case 'l': { // TODO: Use fixed sizes for small values, e.g. byte sized. long value = unpackValueLong(&data); PyObject *l = PyLong_FromLong(value); insertToDictCache(long_cache, &l); *output = l; is_object = true; break; } case 'q': { long long value = unpackValueLongLong(&data); PyObject *l = PyLong_FromLongLong(value); insertToDictCache(long_cache, &l); *output = l; is_object = true; break; } case 'g': { PyObject *result = PyLong_FromLong(0); unsigned char sign = *data++; int size = unpackValueInt(&data); PyObject *shift = PyLong_FromLong(8 * sizeof(unsigned long long)); for (int i = 0; i < size; i++) { result = PyNumber_InPlaceLshift(result, shift); unsigned long long value = unpackValueUnsignedLongLong(&data); PyObject *part = PyLong_FromUnsignedLongLong(value); result = PyNumber_InPlaceAdd(result, part); Py_DECREF(part); } Py_DECREF(shift); if (sign == '-') { // TODO: There is a negate function PyObject *neg = PyLong_FromLong(-1); result = PyNumber_InPlaceMultiply(result, neg); Py_DECREF(neg); } insertToDictCache(long_cache, &result); *output = result; is_object = true; break; } case 'f': { double value = unpackValueFloat(&data); PyObject *f = PyFloat_FromDouble(value); // Floats are cached globally too. insertToDictCacheForcedHash(float_cache, &f, NULL, (richcmpfunc)our_float_richcompare); *output = f; is_object = true; break; } case 'j': { double real = unpackValueFloat(&data); double imag = unpackValueFloat(&data); *output = PyComplex_FromDoubles(real, imag); is_object = true; break; } case 'J': { PyObject *parts[2]; // Complex via float is done for ones that are 0, nan, float. data = _unpackBlobConstants(&parts[0], data, 2); *output = BUILTIN_COMPLEX2(parts[0], parts[1]); is_object = true; break; } #if PYTHON_VERSION < 0x300 case 'a': #endif case 'c': { // Python2 str, potentially attributes, or Python3 bytes, zero terminated. size_t size = strlen((const char *)data); // TODO: Make this zero copy for non-interned with fake objects? PyObject *b = PyBytes_FromStringAndSize((const char *)data, size); CHECK_OBJECT(b); data += size + 1; #if PYTHON_VERSION < 0x300 if (c == 'a') { PyString_InternInPlace(&b); } #else insertToDictCache(bytes_cache, &b); #endif *output = b; is_object = true; break; } case 'd': { // Python2 str length 1 str, potentially attribute, or Python3 single byte PyObject *b = PyBytes_FromStringAndSize((const char *)data, 1); data += 1; #if PYTHON_VERSION < 0x300 PyString_InternInPlace(&b); #else insertToDictCache(bytes_cache, &b); #endif *output = b; is_object = true; break; } case 'w': { // Python2 unicode, Python3 str length 1, potentially attribute in Python3 PyObject *u = PyUnicode_FromStringAndSize((const char *)data, 1); data += 1; #if PYTHON_VERSION >= 0x300 PyUnicode_InternInPlace(&u); #else insertToDictCache(unicode_cache, &u); #endif *output = u; is_object = true; break; } case 'b': { // Python2 str or Python3 bytes, length indicated. // Python2 str, potentially attributes, or Python3 bytes, zero terminated. // TODO: Use fixed sizes for small, e.g. character values, and length vs. 0 // termination. int size = unpackValueInt(&data); // TODO: Make this zero copy for non-interned with fake objects? PyObject *b = PyBytes_FromStringAndSize((const char *)data, size); data += size; #if PYTHON_VERSION >= 0x300 insertToDictCache(bytes_cache, &b); #endif *output = b; is_object = true; break; } case 'B': { // TODO: Use fixed sizes for small, e.g. character values, and length vs. 0 // termination. int size = unpackValueInt(&data); // TODO: Make this zero copy for non-interned with fake objects? PyObject *b = PyByteArray_FromStringAndSize((const char *)data, size); data += size; *output = b; is_object = true; break; } #if PYTHON_VERSION >= 0x300 case 'a': // Python3 attributes #endif case 'u': { // Python2 unicode, Python3 str, zero terminated. size_t size = strlen((const char *)data); #if PYTHON_VERSION < 0x300 PyObject *u = PyUnicode_FromStringAndSize((const char *)data, size); #else PyObject *u = PyUnicode_DecodeUTF8((const char *)data, size, "surrogatepass"); #endif data += size + 1; #if PYTHON_VERSION >= 0x300 if (c == 'a') { PyUnicode_InternInPlace(&u); } #else insertToDictCache(unicode_cache, &u); #endif *output = u; is_object = true; break; } case 'v': { int size = unpackValueInt(&data); #if PYTHON_VERSION < 0x300 PyObject *u = PyUnicode_FromStringAndSize((const char *)data, size); #else PyObject *u = PyUnicode_DecodeUTF8((const char *)data, size, "surrogatepass"); #endif data += size; #if PYTHON_VERSION < 0x300 insertToDictCache(unicode_cache, &u); #endif *output = u; is_object = true; break; } case 'n': { *output = Py_None; is_object = true; break; } case 't': { *output = Py_True; is_object = true; break; } case 'F': { *output = Py_False; is_object = true; break; } case ':': { // Slice object PyObject *items[3]; data = _unpackBlobConstants(&items[0], data, 3); PyObject *s = MAKE_SLICEOBJ3(items[0], items[1], items[2]); *output = s; is_object = true; break; } case ';': { // (x)range objects #if PYTHON_VERSION < 0x300 int start = unpackValueInt(&data); int stop = unpackValueInt(&data); int step = unpackValueInt(&data); PyObject *s = MAKE_XRANGE(start, stop, step); #else PyObject *items[3]; data = _unpackBlobConstants(&items[0], data, 3); PyObject *s = BUILTIN_XRANGE3(items[0], items[1], items[2]); #endif *output = s; is_object = true; break; } case 'M': { // Anonymous builtin by table index value. unsigned char anon_index = *data++; *output = _unpackAnonValue(anon_index); is_object = true; break; } case 'Q': { // Anonymous builtin by table index value. unsigned char special_index = *data++; *output = _unpackSpecialValue(special_index); is_object = true; break; } case 'O': { // Builtin by name. TODO: Define number table shared by C and Python // serialization to avoid using strings here. char const *builtin_name = (char const *)data; data = _unpackValueCString(data); *output = PyObject_GetAttrString((PyObject *)builtin_module, builtin_name); is_object = true; break; } case 'E': { // Builtin exception by name. TODO: Define number table shared by C and Python // serialization to avoid using strings here. char const *builtin_exception_name = (char const *)data; data = _unpackValueCString(data); *output = PyObject_GetAttrString((PyObject *)builtin_module, builtin_exception_name); is_object = true; break; } case 'Z': { unsigned char v = *data++; PyObject *z = NULL; switch (v) { case 0: { static PyObject *_const_float_0_0 = NULL; if (_const_float_0_0 == NULL) { _const_float_0_0 = PyFloat_FromDouble(0.0); } z = _const_float_0_0; break; } case 1: { static PyObject *_const_float_minus_0_0 = NULL; if (_const_float_minus_0_0 == NULL) { _const_float_minus_0_0 = PyFloat_FromDouble(0.0); // Older Python3 has variable signs from C, so be explicit about it. PyFloat_AS_DOUBLE(_const_float_minus_0_0) = copysign(PyFloat_AS_DOUBLE(_const_float_minus_0_0), -1.0); } z = _const_float_minus_0_0; break; } case 2: { static PyObject *_const_float_plus_nan = NULL; if (_const_float_plus_nan == NULL) { _const_float_plus_nan = PyFloat_FromDouble(Py_NAN); // Older Python3 has variable signs for NaN from C, so be explicit about it. PyFloat_AS_DOUBLE(_const_float_plus_nan) = copysign(PyFloat_AS_DOUBLE(_const_float_plus_nan), 1.0); } z = _const_float_plus_nan; break; } case 3: { static PyObject *_const_float_minus_nan = NULL; if (_const_float_minus_nan == NULL) { _const_float_minus_nan = PyFloat_FromDouble(Py_NAN); // Older Python3 has variable signs for NaN from C, so be explicit about it. PyFloat_AS_DOUBLE(_const_float_minus_nan) = copysign(PyFloat_AS_DOUBLE(_const_float_minus_nan), -1.0); } z = _const_float_minus_nan; break; } case 4: { static PyObject *_const_float_plus_inf = NULL; if (_const_float_plus_inf == NULL) { _const_float_plus_inf = PyFloat_FromDouble(Py_HUGE_VAL); // Older Python3 has variable signs from C, so be explicit about it. PyFloat_AS_DOUBLE(_const_float_plus_inf) = copysign(PyFloat_AS_DOUBLE(_const_float_plus_inf), 1.0); } z = _const_float_plus_inf; break; } case 5: { static PyObject *_const_float_minus_inf = NULL; if (_const_float_minus_inf == NULL) { _const_float_minus_inf = PyFloat_FromDouble(Py_HUGE_VAL); // Older Python3 has variable signs from C, so be explicit about it. PyFloat_AS_DOUBLE(_const_float_minus_inf) = copysign(PyFloat_AS_DOUBLE(_const_float_minus_inf), -1.0); } z = _const_float_minus_inf; break; } default: { PRINT_FORMAT("Missing decoding for %d\n", (int)c); NUITKA_CANNOT_GET_HERE("Corrupt constants blob"); } } // Floats are cached globally too. insertToDictCacheForcedHash(float_cache, &z, NULL, (richcmpfunc)our_float_richcompare); *output = z; is_object = true; break; } case 'X': { // Blob data pointer, user knowns size. int size = unpackValueInt(&data); *output = (PyObject *)data; is_object = false; data += size; break; } #if PYTHON_VERSION >= 0x390 case 'G': { // GenericAlias object PyObject *items[2]; data = _unpackBlobConstants(&items[0], data, 2); PyObject *g = Py_GenericAlias(items[0], items[1]); // TODO: Maybe deduplicate. *output = g; is_object = true; break; } #endif #if PYTHON_VERSION >= 0x3a0 case 'H': { // UnionType object PyObject *args; data = _unpackBlobConstants(&args, data, 1); PyObject *union_type = MAKE_UNION_TYPE(args); // TODO: Maybe deduplicate. *output = union_type; is_object = true; break; } #endif case '.': { PRINT_FORMAT("Missing values %d\n", count - _i); NUITKA_CANNOT_GET_HERE("Corrupt constants blob"); } default: PRINT_FORMAT("Missing decoding for %d\n", (int)c); NUITKA_CANNOT_GET_HERE("Corrupt constants blob"); } #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS printf("Size for %c was %d\n", c, data - data_old); #endif // Discourage in-place operations from modifying these. These // might be put into containers, therefore take 2 refs to be // accounting for the container too. if (is_object == true) { CHECK_OBJECT(*output); Py_INCREF(*output); Py_INCREF(*output); } // PRINT_ITEM(*output); // PRINT_NEW_LINE(); output += 1; } return data; } static void unpackBlobConstants(PyObject **output, unsigned char const *data) { int count = (int)unpackValueUint16(&data); _unpackBlobConstants(output, data, count); } void loadConstantsBlob(PyObject **output, char const *name) { static bool init_done = false; if (init_done == false) { #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS PRINT_FORMAT("loadConstantsBlob '%s' one time init\n", name); #endif #if defined(_NUITKA_CONSTANTS_FROM_INCBIN) constant_bin = getConstantsBlobData(); #elif defined(_NUITKA_CONSTANTS_FROM_RESOURCE) #ifdef _NUITKA_EXE // Using NULL as this indicates running program. HMODULE handle = NULL; #else HMODULE handle = getDllModuleHandle(); #endif constant_bin = (const unsigned char *)LockResource( LoadResource(handle, FindResource(handle, MAKEINTRESOURCE(3), RT_RCDATA))); assert(constant_bin); #endif DECODE(constant_bin); uint32_t hash = unpackValueUint32(&constant_bin); uint32_t size = unpackValueUint32(&constant_bin); if (calcCRC32(constant_bin, size) != hash) { puts("Error, corrupted constants object"); abort(); } #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS PRINT_FORMAT("Checked CRC32 to match hash %u size %u\n", hash, size); #endif init_done = true; } #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS PRINT_FORMAT("Loading blob named '%s' with %d values\n", name, count); #endif // Python 3.9 or higher cannot create dictionary before calling init so avoid it. if (strcmp(name, ".bytecode") != 0) { initCaches(); } unsigned char const *w = constant_bin; for (;;) { int match = strcmp(name, (char const *)w); w += strlen((char const *)w) + 1; #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS PRINT_FORMAT("offset of blob size %d\n", w - constant_bin); #endif uint32_t size = unpackValueUint32(&w); if (match == 0) { #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CONSTANTS PRINT_FORMAT("Loading blob named '%s' with %d values and size %d\n", name, count, size); #endif break; } // Skip other module data. w += size; } unpackBlobConstants(output, w); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryBitor.c0000600000372100037210000023513514166627112032624 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "|" (BITOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITOR_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITOR_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_or; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_LONG_INT(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_SET_SET(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_or; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and 'set'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PySet_Type.tp_as_number->nb_or; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: 'set' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITOR_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_or(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_BITOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_BITOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a | b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_or : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_or : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_or; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITOR_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/OnefileSplashScreen.cpp0000600000372100037210000001715014166627112031423 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Creates a stream object initialized with the data from an executable resource. #ifdef __IDE_ONLY__ #include "HelpersSafeStrings.c" #include #endif #include #include #ifdef __MINGW32__ #error "No support for splash screens with MinGW64 yet, only works with MSVC. Somebody please make it portable." #endif IStream *createImageStream() { // Load the resource with image data HRSRC res_handle = FindResource(NULL, MAKEINTRESOURCE(27), RT_RCDATA); if (res_handle == NULL) { return NULL; } DWORD resource_size = SizeofResource(NULL, res_handle); HGLOBAL image_handle = LoadResource(NULL, res_handle); if (image_handle == NULL) { return NULL; } LPVOID resource_data = LockResource(image_handle); if (resource_data == NULL) { return NULL; } HGLOBAL temp_data_handle = GlobalAlloc(GMEM_MOVEABLE, resource_size); if (temp_data_handle == NULL) { return NULL; } LPVOID temp_data = GlobalLock(temp_data_handle); if (temp_data == NULL) { return NULL; } // Copy the data from the resource to the new memory block CopyMemory(temp_data, resource_data, resource_size); GlobalUnlock(temp_data_handle); // Create stream on the HGLOBAL containing the data IStream *result = NULL; if (SUCCEEDED(CreateStreamOnHGlobal(temp_data_handle, TRUE, &result))) { return result; } GlobalFree(temp_data_handle); return NULL; } IWICBitmapSource *getBitmapFromImageStream(IStream *image_stream) { // Load the PNG IWICBitmapDecoder *ipDecoder = NULL; if (FAILED(CoCreateInstance(CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, __uuidof(ipDecoder), (void **)(&ipDecoder)))) { return NULL; } if (FAILED(ipDecoder->Initialize(image_stream, WICDecodeMetadataCacheOnLoad))) { return NULL; } UINT frame_count = 0; if (FAILED(ipDecoder->GetFrameCount(&frame_count)) || frame_count != 1) { return NULL; } IWICBitmapFrameDecode *ipFrame = NULL; if (FAILED(ipDecoder->GetFrame(0, &ipFrame))) { return NULL; } // Convert the image to 32bpp BGRA with alpha channel IWICBitmapSource *ipBitmap = NULL; WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, ipFrame, &ipBitmap); ipFrame->Release(); ipDecoder->Release(); return ipBitmap; } HBITMAP CreateHBITMAP(IWICBitmapSource *ipBitmap) { // Get image dimenstions. UINT width = 0; UINT height = 0; if (FAILED(ipBitmap->GetSize(&width, &height)) || width == 0 || height == 0) { return NULL; } // Prepare structure for bitmap information BITMAPINFO bitmap_info; memset(&bitmap_info, 0, sizeof(bitmap_info)); bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitmap_info.bmiHeader.biWidth = width; bitmap_info.bmiHeader.biHeight = -((LONG)height); // top-down DIB mode bitmap_info.bmiHeader.biPlanes = 1; bitmap_info.bmiHeader.biBitCount = 32; bitmap_info.bmiHeader.biCompression = BI_RGB; // Create the DIB section for the image HDC handle_screen = GetDC(NULL); void *image_data = NULL; HBITMAP handle_bmp = CreateDIBSection(handle_screen, &bitmap_info, DIB_RGB_COLORS, &image_data, NULL, 0); ReleaseDC(NULL, handle_screen); if (handle_bmp == NULL) { return NULL; } // Copy the image into the HBITMAP const UINT stride = width * 4; const UINT size = stride * height; if (FAILED(ipBitmap->CopyPixels(NULL, stride, size, (BYTE *)(image_data)))) { return NULL; } return handle_bmp; } HWND createSplashWindow(HBITMAP splash_bitmap) { WNDCLASSA wc = {0}; wc.lpfnWndProc = DefWindowProc; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = "Splash"; RegisterClassA(&wc); HWND splash_window = CreateWindowExA(WS_EX_LAYERED, wc.lpszClassName, NULL, WS_POPUP | WS_VISIBLE | WS_EX_TOOLWINDOW, 0, 0, 0, 0, 0, NULL, 0, NULL); // get the size of the bitmap BITMAP bitmap; GetObject(splash_bitmap, sizeof(bitmap), &bitmap); SIZE sizeSplash = {bitmap.bmWidth, bitmap.bmHeight}; POINT zero = {0}; HMONITOR handle_monitor = MonitorFromPoint(zero, MONITOR_DEFAULTTOPRIMARY); MONITORINFO monitorinfo = {0}; monitorinfo.cbSize = sizeof(monitorinfo); GetMonitorInfo(handle_monitor, &monitorinfo); // Centered splash screen in the middle of main monitor. POINT ptOrigin; ptOrigin.x = monitorinfo.rcWork.left + (monitorinfo.rcWork.right - monitorinfo.rcWork.left - sizeSplash.cx) / 2; ptOrigin.y = monitorinfo.rcWork.top + (monitorinfo.rcWork.bottom - monitorinfo.rcWork.top - sizeSplash.cy) / 2; // Create a DC with splash bitmap HDC handle_screen = GetDC(NULL); HDC handle_memory = CreateCompatibleDC(handle_screen); HBITMAP handle_old_bitmap = (HBITMAP)SelectObject(handle_memory, splash_bitmap); // Set image alpha channel for blending. BLENDFUNCTION blend = {0}; blend.BlendOp = AC_SRC_OVER; blend.SourceConstantAlpha = 255; blend.AlphaFormat = AC_SRC_ALPHA; // Set window for display. UpdateLayeredWindow(splash_window, handle_screen, &ptOrigin, &sizeSplash, handle_memory, &zero, RGB(0, 0, 0), &blend, ULW_ALPHA); SelectObject(handle_memory, handle_old_bitmap); DeleteDC(handle_memory); ReleaseDC(NULL, handle_screen); return splash_window; } HWND splash_window = 0; static wchar_t splash_indicator_path[4096] = {0}; bool splash_active = false; static void initSplashScreen() { CoInitialize(NULL); IStream *image_stream = createImageStream(); if (image_stream == NULL) { return; } IWICBitmapSource *image_source = getBitmapFromImageStream(image_stream); image_stream->Release(); if (image_source == NULL) { return; } HBITMAP splash_bitmap = CreateHBITMAP(image_source); image_source->Release(); if (splash_bitmap == NULL) { return; } splash_window = createSplashWindow(splash_bitmap); wchar_t const *pattern = L"%TEMP%\\onefile_%PID%_splash_feedback.tmp"; BOOL bool_res = expandTemplatePathW(splash_indicator_path, pattern, sizeof(splash_indicator_path) / sizeof(wchar_t)); if (bool_res == false) { return; } HANDLE handle_splash_file = CreateFileW(splash_indicator_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); CloseHandle(handle_splash_file); splash_active = true; } static void closeSplashScreen() { if (splash_window) { DestroyWindow(splash_window); splash_window = 0; } } static bool checkSplashScreen() { if (splash_active) { if (!PathFileExistsW(splash_indicator_path)) { closeSplashScreen(); splash_active = false; } } return splash_active == false; }Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryBitxor.c0000600000372100037210000023540414166627112033013 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "^" (BITXOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); #endif goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NUITKA_BOOL_EXCEPTION; } return __BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'int'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITXOR_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE nuitka_bool __BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); nuitka_bool result; // return _BINARY_OPERATION_BITXOR_NBOOL_INT_INT(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } return __BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(operand1, operand2); } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_LONG_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyInt_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'int' and 'long'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_INT_LONG(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PyLong_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_xor; } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'long' and 'int'"); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_LONG_INT(operand1, operand2); } #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyObject *result; // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_SET_SET(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PySet_Type.tp_as_number->nb_xor; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and 'set'", type1->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); assert(PySet_CheckExact(operand2)); PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PySet_Type; if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(operand1, operand2); } /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = PySet_Type.tp_as_number->nb_xor; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: 'set' and '%s'", type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PySet_CheckExact(operand1)); CHECK_OBJECT(operand2); PyTypeObject *type1 = &PySet_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); PyObject *result; // return _BINARY_OPERATION_BITXOR_OBJECT_SET_SET(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PySet_Type.tp_as_number->nb_xor(operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } result = obj_result; goto exit_result_ok; exit_result_ok: return result; exit_result_exception: return NULL; } return __BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(operand1, operand2); } PyObject *BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static PyObject *_BINARY_OPERATION_BITXOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { PyObject *result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: return obj_result; exit_binary_exception: return NULL; } PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_OBJECT_OBJECT_OBJECT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static nuitka_bool _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { nuitka_bool result; // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); const long r = a ^ b; clong_result = r; goto exit_result_ok_clong; exit_result_ok_clong: result = clong_result != 0 ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; goto exit_result_ok; exit_result_ok: return result; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_xor : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_xor : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_binary_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_binary_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_xor; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_binary_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_binary_exception; exit_binary_result_object: if (unlikely(obj_result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(obj_result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(obj_result); return r; } exit_binary_exception: return NUITKA_BOOL_EXCEPTION; } nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { return _BINARY_OPERATION_BITXOR_NBOOL_OBJECT_OBJECT(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationBinaryAddUtils.c0000600000372100037210000004110314166627112033244 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* These slots are still manually coded and are used by the generated code. * * The plan should be to generate these as well, so e.g. we can have a slot * SLOT_nb_add_LONG_INT that is optimal too. */ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif static PyObject *LIST_CONCAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); Py_ssize_t size = Py_SIZE(operand1) + Py_SIZE(operand2); PyListObject *result = (PyListObject *)PyList_New(size); if (unlikely(result == NULL)) { return NULL; } PyObject **src = ((PyListObject *)operand1)->ob_item; PyObject **dest = result->ob_item; for (Py_ssize_t i = 0; i < Py_SIZE(operand1); i++) { PyObject *v = src[i]; Py_INCREF(v); dest[i] = v; } src = ((PyListObject *)operand2)->ob_item; dest = result->ob_item + Py_SIZE(operand1); for (Py_ssize_t i = 0; i < Py_SIZE(operand2); i++) { PyObject *v = src[i]; Py_INCREF(v); dest[i] = v; } return (PyObject *)result; } #if PYTHON_VERSION < 0x300 #include #if PYTHON_VERSION < 0x270 // Renamed from Python2.6 #define sdigit wdigit #endif #endif // Convert single digit to sdigit (int32_t) #define MEDIUM_VALUE(x) \ (Py_SIZE(x) < 0 ? -(sdigit)((PyLongObject *)(x))->ob_digit[0] \ : (Py_SIZE(x) == 0 ? (sdigit)0 : (sdigit)((PyLongObject *)(x))->ob_digit[0])) // Needed for offsetof #include #define MAX_LONG_DIGITS ((PY_SSIZE_T_MAX - offsetof(PyLongObject, ob_digit)) / sizeof(digit)) #define Nuitka_LongGetDigitPointer(value) (&(((PyLongObject *)value)->ob_digit[0])) #define Nuitka_LongGetDigitSize(value) (Py_ABS(Py_SIZE(value))) // Our version of _PyLong_New(size); static PyLongObject *Nuitka_LongNew(Py_ssize_t size) { assert(size < (Py_ssize_t)MAX_LONG_DIGITS); #if PYTHON_VERSION >= 0x300 PyLongObject *result; result = (PyLongObject *)PyObject_MALLOC(offsetof(PyLongObject, ob_digit) + size * sizeof(digit)); return (PyLongObject *)PyObject_INIT_VAR(result, &PyLong_Type, size); #else return (PyLongObject *)PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size); #endif } static PyObject *Nuitka_LongRealloc(PyObject *value, Py_ssize_t size) { PyLongObject *result = Nuitka_LongNew(size); Py_SIZE(result) = size; Py_DECREF(value); return (PyObject *)result; } static PyObject *Nuitka_LongFromCLong(long ival) { #if PYTHON_VERSION < 0x300 if (ival == 0) { PyLongObject *result = Nuitka_LongNew(0); return (PyObject *)result; } #else if (ival >= NUITKA_STATIC_SMALLINT_VALUE_MIN && ival <= NUITKA_STATIC_SMALLINT_VALUE_MAX) { PyObject *result = Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(ival)]; Py_INCREF(result); return result; } #endif // We go via unsigned long to avoid overflows when shifting and we need // the sign separate in the end anyway. unsigned long abs_ival; bool negative; if (ival < 0) { abs_ival = 0U - (unsigned long)ival; negative = true; } else { abs_ival = (unsigned long)ival; negative = false; } // Fast path for single digit values if (!(abs_ival >> PyLong_SHIFT)) { PyLongObject *result = Nuitka_LongNew(1); assert(result != NULL); if (negative) { Py_SIZE(result) = -1; } result->ob_digit[0] = (digit)abs_ival; return (PyObject *)result; } // Fast path for two digit values on suitable platforms. #if PyLong_SHIFT == 15 if (!(abs_ival >> 2 * PyLong_SHIFT)) { PyLongObject *result = Nuitka_LongNew(2); assert(result != NULL); if (negative) { Py_SIZE(result) = -2; } result->ob_digit[0] = (digit)(abs_ival & PyLong_MASK); result->ob_digit[1] = (digit)(abs_ival >> PyLong_SHIFT); return (PyObject *)result; } #endif // Slow path for the rest. unsigned long t = abs_ival; Py_ssize_t ndigits = 0; // First determine the number of digits needed. while (t != 0) { ++ndigits; t >>= PyLong_SHIFT; } PyLongObject *result = _PyLong_New(ndigits); assert(result != NULL); Py_SIZE(result) = negative ? -ndigits : ndigits; digit *d = result->ob_digit; // Now copy the digits t = abs_ival; while (t != 0) { *d++ = (digit)(t & PyLong_MASK); t >>= PyLong_SHIFT; } return (PyObject *)result; } static void Nuitka_LongUpdateFromCLong(PyObject **value, long ival) { assert(Py_REFCNT(*value) == 1); #if PYTHON_VERSION < 0x300 if (ival == 0) { if (Py_SIZE(*value) == 0) { return; } Py_DECREF(*value); *value = (PyObject *)Nuitka_LongNew(0); return; } #else if (ival >= NUITKA_STATIC_SMALLINT_VALUE_MIN && ival <= NUITKA_STATIC_SMALLINT_VALUE_MAX) { Py_DECREF(*value); *value = Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(ival)]; Py_INCREF(*value); return; } #endif // We go via unsigned long to avoid overflows when shifting and we need // the sign separate in the end anyway. unsigned long abs_ival; bool negative; if (ival < 0) { abs_ival = 0U - (unsigned long)ival; negative = true; } else { abs_ival = (unsigned long)ival; negative = false; } // Fast path for single digit values if (!(abs_ival >> PyLong_SHIFT)) { PyLongObject *result; if (unlikely(Py_SIZE(*value) == 0)) { *value = Nuitka_LongRealloc(*value, 1); CHECK_OBJECT(*value); result = (PyLongObject *)*value; } else { result = (PyLongObject *)(*value); } Py_SIZE(result) = negative ? -1 : 1; result->ob_digit[0] = (digit)abs_ival; return; } // Fast path for two digit values on suitable platforms, e.g. armv7l #if PyLong_SHIFT == 15 if (!(abs_ival >> 2 * PyLong_SHIFT)) { PyLongObject *result; if (unlikely(Py_ABS(Py_SIZE(*value)) < 2)) { *value = Nuitka_LongRealloc(*value, 2); CHECK_OBJECT(*value); result = (PyLongObject *)*value; } else { result = (PyLongObject *)(*value); } Py_SIZE(result) = negative ? -2 : 2; result->ob_digit[0] = (digit)(abs_ival & PyLong_MASK); result->ob_digit[1] = (digit)(abs_ival >> PyLong_SHIFT); return; } #endif // Slow path for the rest. unsigned long t = abs_ival; Py_ssize_t ndigits = 0; // First determine the number of digits needed. while (t != 0) { ndigits++; t >>= PyLong_SHIFT; } if (unlikely(Py_ABS(Py_SIZE(*value)) < ndigits)) { *value = Nuitka_LongRealloc(*value, ndigits); } CHECK_OBJECT(*value); Py_SIZE(*value) = negative ? -ndigits : ndigits; digit *d = ((PyLongObject *)(*value))->ob_digit; // Now copy the digits t = abs_ival; while (t) { *d++ = (digit)(t & PyLong_MASK); t >>= PyLong_SHIFT; } return; } #if 0 // Note: We are manually inlining this so far. static PyLongObject *Nuitka_LongStripZeros(PyLongObject *v) { Py_ssize_t j = Py_ABS(Py_SIZE(v)); Py_ssize_t i = j; while (i > 0 && v->ob_digit[i - 1] == 0) { i -= 1; } if (i != j) { Py_SIZE(v) = (Py_SIZE(v) < 0) ? -i : i; } return v; } #endif static PyLongObject *_Nuitka_LongAddDigits(digit const *a, Py_ssize_t size_a, digit const *b, Py_ssize_t size_b) { // Make sure we know a is the longest value. if (size_a < size_b) { { digit const *temp = a; a = b; b = temp; } { Py_ssize_t temp = size_a; size_a = size_b; size_b = temp; } } // We do not know ahead of time, if we need a new digit, lets just allocate it. PyLongObject *result = Nuitka_LongNew(size_a + 1); CHECK_OBJECT(result); digit *r = &result->ob_digit[0]; digit carry = 0; // First common digits. Py_ssize_t i; for (i = 0; i < size_b; i++) { carry += a[i] + b[i]; r[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; } // Digits from longest one only. for (; i < size_a; i++) { carry += a[i]; r[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; } // Only the top digit can be zero, so we can strip this faster. if (carry) { r[i] = carry; } else { Py_SIZE(result) -= 1; } return result; } static PyObject *_Nuitka_LongAddInplaceDigits(PyObject *left, digit const *b, Py_ssize_t size_b) { digit const *a = Nuitka_LongGetDigitPointer(left); Py_ssize_t size_a = Nuitka_LongGetDigitSize(left); digit const *aa = a; digit const *bb = b; // Make sure we know aa is the longest value by swapping a/b attributes. if (size_a < size_b) { { aa = b; bb = a; } { Py_ssize_t temp = size_a; size_a = size_b; size_b = temp; } } digit carry = 0; // First common digits. Py_ssize_t i; for (i = 0; i < size_b; i++) { carry += aa[i] + bb[i]; carry >>= PyLong_SHIFT; } // Digits from longest one only might cause a new digit through carry. Py_ssize_t needed = size_a; for (; i < size_a; i++) { carry += aa[i]; carry >>= PyLong_SHIFT; // No more carry, that means size cannot increase. if (carry == 0) { break; } } // Final digit needs to be added. if (carry) { needed = i + 1; } // Need to keep the old value around, or else we commit use after free potentially. PyObject *old = left; if (needed > Nuitka_LongGetDigitSize(left)) { left = (PyObject *)Nuitka_LongNew(needed); } else { Py_INCREF(old); } digit *r = Nuitka_LongGetDigitPointer(left); // Now do the real thing, with actual storage to left digits. carry = 0; // First common digits. for (i = 0; i < size_b; i++) { carry += aa[i] + bb[i]; r[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; } // Digits from longest one only. for (; i < size_a; i++) { carry += aa[i]; r[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; } // Final digit from the carry. if (carry != 0) { r[i] = carry; Py_SIZE(left) = i + 1; } else { Py_SIZE(left) = i; } // Release reference to old value Py_DECREF(old); return left; } static PyLongObject *_Nuitka_LongSubDigits(digit const *a, Py_ssize_t size_a, digit const *b, Py_ssize_t size_b) { // Sign of the result. int sign = 1; // Make sure we know a is the largest value. if (size_a < size_b) { sign = -1; { digit const *temp = a; a = b; b = temp; } { Py_ssize_t temp = size_a; size_a = size_b; size_b = temp; } } else if (size_a == size_b) { // Find highest digit where a and b differ: Py_ssize_t i = size_a; while (--i >= 0 && a[i] == b[i]) { } if (i < 0) { #if PYTHON_VERSION < 0x300 return (PyLongObject *)Nuitka_LongFromCLong(0); #else // For Python3, we have this prepared. PyObject *result = Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(0)]; Py_INCREF(result); return (PyLongObject *)result; #endif } if (a[i] < b[i]) { sign = -1; { digit const *temp = a; a = b; b = temp; } } size_a = size_b = i + 1; } PyLongObject *result = Nuitka_LongNew(size_a); CHECK_OBJECT(result); digit *r = &result->ob_digit[0]; digit borrow = 0; Py_ssize_t i; // First common digits. for (i = 0; i < size_b; i++) { borrow = a[i] - b[i] - borrow; r[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; } // Digits from largest one only. for (; i < size_a; i++) { borrow = a[i] - borrow; r[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; } assert(borrow == 0); // Strip leading zeros. while (i > 0 && r[i - 1] == 0) { i -= 1; } Py_SIZE(result) = (sign < 0) ? -i : i; #if PYTHON_VERSION >= 0x300 // Normalize small integers. if (i <= 1) { long ival = MEDIUM_VALUE(result); if (ival >= NUITKA_STATIC_SMALLINT_VALUE_MIN && ival <= NUITKA_STATIC_SMALLINT_VALUE_MAX) { Py_DECREF(result); result = (PyLongObject *)Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(ival)]; Py_INCREF(result); } } #endif return result; } static PyObject *_Nuitka_LongSubInplaceDigits(PyObject *left, digit const *b, Py_ssize_t size_b, int sign) { digit const *a = Nuitka_LongGetDigitPointer(left); Py_ssize_t size_a = Nuitka_LongGetDigitSize(left); digit const *aa = a; digit const *bb = b; // Make sure we know a is the largest value. if (size_a < size_b) { // Invert the sign of the result by swapping the order. sign *= -1; { aa = b; bb = a; } { Py_ssize_t temp = size_a; size_a = size_b; size_b = temp; } } else if (size_a == size_b) { // Find highest digit where a and b differ: Py_ssize_t i = size_a; while (--i >= 0 && a[i] == b[i]) { } // TODO: This will benefit a lot by being in a template. if (i < 0) { #if PYTHON_VERSION < 0x300 PyObject *r = const_long_0; #else PyObject *r = Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(0)]; #endif Py_INCREF(r); Py_DECREF(left); return r; } if (aa[i] < bb[i]) { sign *= -1; { aa = b; bb = a; } } size_a = size_b = i + 1; } Py_ssize_t needed = size_a; // Need to keep the old value around, or else we commit use after free potentially. PyObject *old = left; if (needed > Nuitka_LongGetDigitSize(left)) { left = (PyObject *)Nuitka_LongNew(needed); } else { Py_INCREF(old); } digit *r = Nuitka_LongGetDigitPointer(left); digit borrow = 0; Py_ssize_t i; // First common digits. for (i = 0; i < size_b; i++) { borrow = aa[i] - bb[i] - borrow; r[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; } // Digits from largest one only. for (; i < size_a; i++) { borrow = aa[i] - borrow; r[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; } assert(borrow == 0); // Strip leading zeros. while (i > 0 && r[i - 1] == 0) { i -= 1; } Py_SIZE(left) = (sign < 0) ? -i : i; // Release reference to old value Py_DECREF(old); #if PYTHON_VERSION >= 0x300 // Normalize small integers. if (i <= 1) { long ival = MEDIUM_VALUE(left); if (ival >= NUITKA_STATIC_SMALLINT_VALUE_MIN && ival <= NUITKA_STATIC_SMALLINT_VALUE_MAX) { Py_DECREF(left); left = Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(ival)]; Py_INCREF(left); } } #endif return left; } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersExceptions.c0000600000372100037210000000743414166627112030637 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /** For setting exceptions. * * These are non-inline variants for exception raises, done so to avoid the code bloat. * **/ // This file is included from another C file, help IDEs to still parse it on // its own. #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif void SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyObject *exception_type, char const *format, char const *value) { PyErr_Format(exception_type, format, value); } void SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyObject *exception_type, char const *format, char const *value1, char const *value2) { PyErr_Format(exception_type, format, value1, value2); } void SET_CURRENT_EXCEPTION_TYPE0_FORMAT3(PyObject *exception_type, char const *format, char const *value1, char const *value2, char const *value3) { PyErr_Format(exception_type, format, value1, value2, value3); } void SET_CURRENT_EXCEPTION_TYPE_COMPLAINT(char const *format, PyObject *mistyped) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, format, Py_TYPE(mistyped)->tp_name); } static char const *TYPE_NAME_DESC(PyObject *type) { if (type == Py_None) { return "None"; } else { return Py_TYPE(type)->tp_name; } } void SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE(char const *format, PyObject *mistyped) { SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError, format, TYPE_NAME_DESC(mistyped)); } void FORMAT_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name) { *exception_type = PyExc_NameError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat("name '%s' is not defined", Nuitka_String_AsString_Unchecked(variable_name)); CHECK_OBJECT(*exception_value); } #if PYTHON_VERSION < 0x340 void FORMAT_GLOBAL_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name) { *exception_type = PyExc_NameError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat("global name '%s' is not defined", Nuitka_String_AsString_Unchecked(variable_name)); CHECK_OBJECT(*exception_value); } #endif void FORMAT_UNBOUND_LOCAL_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name) { *exception_type = PyExc_UnboundLocalError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat("local variable '%s' referenced before assignment", Nuitka_String_AsString_Unchecked(variable_name)); CHECK_OBJECT(*exception_value); } void FORMAT_UNBOUND_CLOSURE_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name) { *exception_type = PyExc_NameError; Py_INCREF(*exception_type); *exception_value = Nuitka_String_FromFormat("free variable '%s' referenced before assignment in enclosing scope", Nuitka_String_AsString_Unchecked(variable_name)); CHECK_OBJECT(*exception_value); }Nuitka-0.6.19.1/nuitka/build/static_src/HelpersOperationInplaceLshift.c0000600000372100037210000014257014166627112033125 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "<<" (LSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_lshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyLong_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'long'", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyLong_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(operand1, operand2); } bool BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(operand1, operand2); } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_lshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_lshift == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyLong_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and '%s'", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); #endif goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. NUITKA_MAY_BE_UNUSED PyObject *obj_result; PyObject *x = PyLong_Type.tp_as_number->nb_lshift(*operand1, operand2); assert(x != Py_NotImplemented); obj_result = x; goto exit_result_object; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(operand1, operand2); } #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } bool BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_lshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = PyInt_Type.tp_as_number->nb_coerce; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and 'int'", type1->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = &PyInt_Type; if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ static HEDLEY_NEVER_INLINE bool __BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_lshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_lshift == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = PyInt_Type.tp_as_number->nb_coerce; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and '%s'", type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } static inline bool _BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); if (type1 == type2) { assert(type1 == type2); // return _BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(operand1, operand2); // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } return __BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(operand1, operand2); } bool BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ static inline bool _BINARY_OPERATION_LSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = &PyLong_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_lshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_lshift == NULL); { binaryfunc slot1 = PyInt_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyLong_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'int' and 'long'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_LSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_INT_LONG_INPLACE(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ static inline bool _BINARY_OPERATION_LSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); assert(PyLong_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = &PyInt_Type; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif // No inplace number slot nb_inplace_lshift available for this type. assert(type1->tp_as_number == NULL || type1->tp_as_number->nb_inplace_lshift == NULL); { binaryfunc slot1 = PyLong_Type.tp_as_number->nb_lshift; binaryfunc slot2 = NULL; if (!(0)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = PyInt_Type.tp_as_number->nb_lshift; } if (slot1 != NULL) { PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } // Statically recognized that coercion is not possible with these types PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: 'long' and 'int'"); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_LSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_LONG_INT_INPLACE(operand1, operand2); } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ static inline bool _BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); // Pointer must be non-null. CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) { // Not every code path will make use of all possible results. #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; NUITKA_MAY_BE_UNUSED long clong_result; NUITKA_MAY_BE_UNUSED double cfloat_result; #ifdef _MSC_VER #pragma warning(pop) #endif CHECK_OBJECT(*operand1); assert(PyInt_CheckExact(*operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(*operand1); const long b = PyInt_AS_LONG(operand2); if (unlikely(b < 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "negative shift count"); goto exit_result_exception; } /* Short cut for zero shift or shifting zero. */ if (a == 0 || b == 0) { goto exit_result_ok_left; } else if (b >= LONG_BIT) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { long c = a << b; if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { PyObject *operand1_long = PyLong_FromLong(a); PyObject *operand2_long = PyLong_FromLong(b); // TODO: Change this to using CLONG once we specialize that too. PyObject *r = _BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(operand1_long, operand2_long); Py_DECREF(operand1_long); Py_DECREF(operand2_long); obj_result = r; goto exit_result_object; } else { clong_result = c; goto exit_result_ok_clong; } } exit_result_ok_clong: // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = PyInt_FromLong(clong_result); goto exit_result_ok; exit_result_ok_left: goto exit_result_ok; exit_result_object: if (unlikely(obj_result == NULL)) { goto exit_result_exception; } // We got an object handed, that we have to release. Py_DECREF(*operand1); *operand1 = obj_result; goto exit_result_ok; exit_result_ok: return true; exit_result_exception: return false; } #endif if (Py_REFCNT(*operand1) == 1) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. } if (Py_TYPE(*operand1) == Py_TYPE(operand2)) { #if PYTHON_VERSION >= 0x300 if (PyLong_CheckExact(operand2)) { return _BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(operand1, operand2); } #endif } PyTypeObject *type1 = Py_TYPE(*operand1); PyTypeObject *type2 = Py_TYPE(operand2); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #endif NUITKA_MAY_BE_UNUSED bool cbool_result; NUITKA_MAY_BE_UNUSED PyObject *obj_result; #ifdef _MSC_VER #pragma warning(pop) #endif binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_lshift : NULL; if (islot != NULL) { PyObject *x = islot(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } { binaryfunc slot1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_lshift : NULL; binaryfunc slot2 = NULL; if (!(type1 == type2)) { assert(type1 != type2); /* Different types, need to consider second value slot. */ slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_lshift : NULL; if (slot1 == slot2) { slot2 = NULL; } } if (slot1 != NULL) { if (slot2 != NULL) { if (PyType_IsSubtype(type2, type1)) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); slot2 = NULL; } } PyObject *x = slot1(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } if (slot2 != NULL) { PyObject *x = slot2(*operand1, operand2); if (x != Py_NotImplemented) { obj_result = x; goto exit_inplace_result_object; } Py_DECREF(x); } #if PYTHON_VERSION < 0x300 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) { coercion c1 = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL; if (c1 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c1(&coerced1, &coerced2); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } coercion c2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL; if (c2 != NULL) { PyObject *coerced1 = *operand1; PyObject *coerced2 = operand2; int err = c2(&coerced2, &coerced1); if (unlikely(err < 0)) { goto exit_inplace_exception; } if (err == 0) { PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number; if (likely(mv == NULL)) { binaryfunc slot = mv->nb_lshift; if (likely(slot != NULL)) { PyObject *x = slot(coerced1, coerced2); Py_DECREF(coerced1); Py_DECREF(coerced2); obj_result = x; goto exit_inplace_result_object; } } // nb_coerce took a reference. Py_DECREF(coerced1); Py_DECREF(coerced2); } } } #endif PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and '%s'", type1->tp_name, type2->tp_name); goto exit_inplace_exception; } exit_inplace_result_object: if (unlikely(obj_result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = obj_result; return true; exit_inplace_exception: return false; } bool BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { return _BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INPLACE(operand1, operand2); } Nuitka-0.6.19.1/nuitka/build/static_src/HelpersComparisonEq.c0000600000372100037210000157470414166627112031130 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif #include "HelpersComparisonEqUtils.c" /* C helpers for type specialized "==" (EQ) comparisons */ #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_EQ_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a == b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_EQ_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a == b; // Convert to target type. bool result = r; return result; } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_EQ_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyInt_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyInt_CheckExact(operand2)); const long a = PyInt_AS_LONG(operand1); const long b = PyInt_AS_LONG(operand2); bool r = a == b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_EQ_OBJECT_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_EQ_CBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; bool result = r; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) { #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) { return COMPARE_EQ_NBOOL_INT_INT(operand1, operand2); } #endif // Quick path for avoidable checks, compatible with CPython. if (operand1 == operand2 && IS_SANE_TYPE(Py_TYPE(operand1))) { bool r = true; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !PyInstance_Check(operand1)) { richcmpfunc frich = RICHCOMPARE(type1); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = type1->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == %s()", type1->tp_name, type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and '%s'", type1->tp_name, type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #if PYTHON_VERSION < 0x300 static PyObject *COMPARE_EQ_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_EQ_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 static bool COMPARE_EQ_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. bool result = r; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. bool result = r; return result; } else { bool r = false; // Convert to target type. bool result = r; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_EQ_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 static nuitka_bool COMPARE_EQ_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyString_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyString_CheckExact(operand2)); PyStringObject *a = (PyStringObject *)operand1; PyStringObject *b = (PyStringObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyString_Type) { return COMPARE_EQ_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyString_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyString_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyString_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_STR_STR(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyString_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyString_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyString_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ PyObject *RICH_COMPARE_EQ_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ bool RICH_COMPARE_EQ_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_STR_STR(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_STR_STR(operand1, operand2); } #endif static PyObject *COMPARE_EQ_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } PyObject *result = BOOL_FROM(r == true); Py_INCREF(result); return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } PyObject *result = BOOL_FROM(r == true); Py_INCREF(result); return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_EQ_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NULL; } #endif } static bool COMPARE_EQ_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } bool result = r == true; return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } bool result = r == true; return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_EQ_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return false; } #endif } static nuitka_bool COMPARE_EQ_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyUnicode_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(operand2)); PyUnicodeObject *a = (PyUnicodeObject *)operand1; PyUnicodeObject *b = (PyUnicodeObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } #if PYTHON_VERSION >= 0x300 bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { int kind1 = PyUnicode_KIND(a); if (unlikely(kind1 == 0)) { int res = _PyUnicode_Ready((PyObject *)a); assert(res != -1); kind1 = PyUnicode_KIND(a); assert(kind1 != 0); } int kind2 = PyUnicode_KIND(b); if (unlikely(kind2 == 0)) { int res = _PyUnicode_Ready((PyObject *)b); assert(res != -1); kind2 = PyUnicode_KIND(b); assert(kind2 != 0); } if (kind1 != kind2) { r = false; } else { const void *data1 = PyUnicode_DATA(a); const void *data2 = PyUnicode_DATA(b); int cmp = memcmp(data1, data2, len * kind1); r = (cmp == 0); } } nuitka_bool result = r == true ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool r; Py_ssize_t len = PyUnicode_GET_LENGTH(a); if (PyUnicode_GET_LENGTH(b) != len) { r = false; } else { const Py_UNICODE *data1 = a->str; const Py_UNICODE *data2 = b->str; int cmp = memcmp(data1, data2, len * sizeof(Py_UNICODE)); r = (cmp == 0); } nuitka_bool result = r == true ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #endif } /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyUnicode_Type) { return COMPARE_EQ_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyUnicode_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == unicode()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == str()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'str'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyUnicode_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyUnicode_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyUnicode_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyUnicode_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyUnicode_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: unicode() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: str() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'str' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ PyObject *RICH_COMPARE_EQ_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ bool RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_UNICODE_UNICODE(operand1, operand2); } /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_UNICODE_UNICODE(operand1, operand2); } #if PYTHON_VERSION >= 0x300 static bool COMPARE_EQ_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. bool result = r; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. bool result = r; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. bool result = r; return result; } else { bool r = false; // Convert to target type. bool result = r; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_EQ_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 static nuitka_bool COMPARE_EQ_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } else { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } } /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyBytes_Type) { return COMPARE_EQ_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyBytes_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == bytes()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'bytes'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 static PyObject *COMPARE_EQ_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyBytes_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyBytes_CheckExact(operand2)); PyBytesObject *a = (PyBytesObject *)operand1; PyBytesObject *b = (PyBytesObject *)operand2; // Same object has fast path for all operations. if (operand1 == operand2) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } Py_ssize_t len_a = Py_SIZE(operand1); Py_ssize_t len_b = Py_SIZE(operand2); if (len_a != len_b) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { if ((a->ob_sval[0] == b->ob_sval[0]) && (memcmp(a->ob_sval, b->ob_sval, len_a) == 0)) { bool r = true; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } else { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } } /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyBytes_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_BYTES_BYTES(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyBytes_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyBytes_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyBytes_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: bytes() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'bytes' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ PyObject *RICH_COMPARE_EQ_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ bool RICH_COMPARE_EQ_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_BYTES_BYTES(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_EQ_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ bool RICH_COMPARE_EQ_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_INT_INT(operand1, operand2); } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_EQ_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_EQ_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyInt_Type) { return COMPARE_EQ_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyInt_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = NULL; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = NULL; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyInt_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_INT_INT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyInt_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = NULL; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyInt_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = NULL; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } #endif static PyObject *COMPARE_EQ_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = false; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = false; break; } } } // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_EQ_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_LONG_LONG(operand1, operand2); } static bool COMPARE_EQ_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = false; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = false; break; } } } // Convert to target type. bool result = r; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_EQ_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_LONG_LONG(operand1, operand2); } static nuitka_bool COMPARE_EQ_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyLong_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyLong_CheckExact(operand2)); PyLongObject *a = (PyLongObject *)operand1; PyLongObject *b = (PyLongObject *)operand2; bool r; if (a == b) { r = true; } else if (Py_SIZE(a) != Py_SIZE(b)) { r = false; } else { Py_ssize_t i = Py_ABS(Py_SIZE(a)); r = true; while (--i >= 0) { if (a->ob_digit[i] != b->ob_digit[i]) { r = false; break; } } } // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_LONG_LONG(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_EQ_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_EQ_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyLong_Type) { return COMPARE_EQ_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyLong_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type2)); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == long()", type1->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == int()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'int'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyLong_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_LONG_LONG(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyLong_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = PyLong_Type.tp_compare; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = (PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(type1)); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: long() == %s()", type2->tp_name); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: int() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'int' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_EQ_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a == b; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_EQ_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_FLOAT_FLOAT(operand1, operand2); } static bool COMPARE_EQ_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a == b; // Convert to target type. bool result = r; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_EQ_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_FLOAT_FLOAT(operand1, operand2); } static nuitka_bool COMPARE_EQ_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyFloat_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyFloat_CheckExact(operand2)); const double a = PyFloat_AS_DOUBLE(operand1); const double b = PyFloat_AS_DOUBLE(operand2); bool r = a == b; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_FLOAT_FLOAT(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_EQ_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_EQ_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyFloat_Type) { return COMPARE_EQ_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyFloat_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == float()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'float'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyFloat_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_FLOAT_FLOAT(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyFloat_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyFloat_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyFloat_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: float() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'float' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_EQ_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_EQ_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_TUPLE_TUPLE(operand1, operand2); } static bool COMPARE_EQ_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. bool result = r; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. bool result = r; return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_EQ_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_TUPLE_TUPLE(operand1, operand2); } static nuitka_bool COMPARE_EQ_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyTuple_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyTuple_CheckExact(operand2)); PyTupleObject *a = (PyTupleObject *)operand1; PyTupleObject *b = (PyTupleObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_TUPLE_TUPLE(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_EQ_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_EQ_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyTuple_Type) { return COMPARE_EQ_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyTuple_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == tuple()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'tuple'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyTuple_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_TUPLE_TUPLE(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyTuple_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyTuple_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyTuple_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: tuple() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'tuple' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } static PyObject *COMPARE_EQ_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NULL; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_EQ_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_OBJECT_LIST_LIST(operand1, operand2); } static bool COMPARE_EQ_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. bool result = r; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return false; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. bool result = r; return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ bool RICH_COMPARE_EQ_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_CBOOL_LIST_LIST(operand1, operand2); } static nuitka_bool COMPARE_EQ_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { CHECK_OBJECT(operand1); assert(PyList_CheckExact(operand1)); CHECK_OBJECT(operand2); assert(PyList_CheckExact(operand2)); PyListObject *a = (PyListObject *)operand1; PyListObject *b = (PyListObject *)operand2; Py_ssize_t len_a = Py_SIZE(a); Py_ssize_t len_b = Py_SIZE(b); if (len_a != len_b) { bool r = false; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } nuitka_bool res = NUITKA_BOOL_TRUE; Py_ssize_t i; for (i = 0; i < len_a && i < len_b; i++) { PyObject *aa = a->ob_item[i]; PyObject *bb = b->ob_item[i]; if (aa == bb) { continue; } res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(aa, bb); if (res == NUITKA_BOOL_EXCEPTION) { return NUITKA_BOOL_EXCEPTION; } if (res == NUITKA_BOOL_FALSE) { break; } } bool r = res == NUITKA_BOOL_TRUE; // Convert to target type. nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2) { return COMPARE_EQ_NBOOL_LIST_LIST(operand1, operand2); } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_EQ_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NULL; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ bool RICH_COMPARE_EQ_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_EQ_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return false; } #endif } /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2) { if (Py_TYPE(operand1) == &PyList_Type) { return COMPARE_EQ_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = Py_TYPE(operand1); PyTypeObject *type2 = &PyList_Type; #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && 0) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (PyInstance_Check(operand1)) { c = (*type1->tp_compare)(operand1, operand2); } else if (0) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = PyList_Type.tp_richcompare; if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = RICHCOMPARE(type1); if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %s() == list()", type1->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of '%s' and 'list'", type1->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ PyObject *RICH_COMPARE_EQ_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_EQ_OBJECT_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NULL; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NULL; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); return result; } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } case Py_NE: { bool r = operand1 != operand2; PyObject *result = BOOL_FROM(r); Py_INCREF(result); return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NULL; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ bool RICH_COMPARE_EQ_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_EQ_CBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return false; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return false; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; bool result = r; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return false; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; bool result = r; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return false; } { bool r = CHECK_IF_TRUE(result) == 1; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; bool result = r; return result; } case Py_NE: { bool r = operand1 != operand2; bool result = r; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return false; } #endif } /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ nuitka_bool RICH_COMPARE_EQ_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2) { if (&PyList_Type == Py_TYPE(operand2)) { return COMPARE_EQ_NBOOL_LIST_LIST(operand1, operand2); } #if PYTHON_VERSION < 0x300 if (unlikely(Py_EnterRecursiveCall((char *)" in cmp"))) { return NUITKA_BOOL_EXCEPTION; } #else if (unlikely(Py_EnterRecursiveCall((char *)" in comparison"))) { return NUITKA_BOOL_EXCEPTION; } #endif PyTypeObject *type1 = &PyList_Type; PyTypeObject *type2 = Py_TYPE(operand2); #if PYTHON_VERSION < 0x300 // If the types are equal, we may get away immediately except for instances. if (type1 == type2 && !0) { richcmpfunc frich = PyList_Type.tp_richcompare; if (frich != NULL) { PyObject *result = (*frich)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } // No rich comparison worked, but maybe compare works. cmpfunc fcmp = NULL; if (fcmp != NULL) { int c = (*fcmp)(operand1, operand2); c = adjust_tp_compare(c); Py_LeaveRecursiveCall(); if (c == -2) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; default: NUITKA_CANNOT_GET_HERE("wrong op_code"); } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } } // Fast path was not successful or not taken richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } int c; if (0) { c = (*type1->tp_compare)(operand1, operand2); } else if (PyInstance_Check(operand2)) { c = (*type2->tp_compare)(operand1, operand2); } else { c = try_3way_compare(operand1, operand2); } if (c >= 2) { if (type1 == type2) { Py_uintptr_t aa = (Py_uintptr_t)operand1; Py_uintptr_t bb = (Py_uintptr_t)operand2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else if (operand1 == Py_None) { // None is smaller than everything else c = -1; } else if (operand2 == Py_None) { // None is smaller than everything else c = 1; } else if (PyNumber_Check(operand1)) { // different type: compare type names but numbers are smaller than // others. if (PyNumber_Check(operand2)) { // Both numbers, need to make a decision based on types. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } else { c = -1; } } else if (PyNumber_Check(operand2)) { c = 1; } else { // TODO: Could be hard coded if one is known. int s = strcmp(type1->tp_name, type2->tp_name); if (s < 0) { c = -1; } else if (s > 0) { c = 1; } else { // Same type name need to make a decision based on type address. Py_uintptr_t aa = (Py_uintptr_t)type1; Py_uintptr_t bb = (Py_uintptr_t)type2; c = (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } } } Py_LeaveRecursiveCall(); if (unlikely(c <= -2)) { return NUITKA_BOOL_EXCEPTION; } switch (Py_EQ) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } bool r = c != 0; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; #else bool checked_reverse_op = false; richcmpfunc f; if (type1 != type2 && PyType_IsSubtype(type2, type1)) { f = RICHCOMPARE(type2); if (f != NULL) { checked_reverse_op = true; PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } f = PyList_Type.tp_richcompare; if (f != NULL) { PyObject *result = (*f)(operand1, operand2, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } if (checked_reverse_op == false) { f = RICHCOMPARE(type2); if (f != NULL) { PyObject *result = (*f)(operand2, operand1, Py_EQ); if (result != Py_NotImplemented) { Py_LeaveRecursiveCall(); if (unlikely(result == NULL)) { return NUITKA_BOOL_EXCEPTION; } { nuitka_bool r = CHECK_IF_TRUE(result) ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; Py_DECREF(result); return r; } } Py_DECREF(result); } } Py_LeaveRecursiveCall(); // If it is not implemented, do pointer identity checks as "==" and "!=" and // otherwise give an error switch (Py_EQ) { case Py_EQ: { bool r = operand1 == operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } case Py_NE: { bool r = operand1 != operand2; nuitka_bool result = r ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE; return result; } default: #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: list() == %s()", type2->tp_name); #else PyErr_Format(PyExc_TypeError, "'==' not supported between instances of 'list' and '%s'", type2->tp_name); #endif return NUITKA_BOOL_EXCEPTION; } #endif } Nuitka-0.6.19.1/nuitka/build/static_src/CompiledCodeHelpers.c0000600000372100037210000015515314166627112031047 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* Implementations of compiled code helpers. * The definition of a compiled code helper is that it's being used in * generated C code and provides part of the operations implementation. * * Currently we also have standalone mode related code here, patches to CPython * runtime that we do, and e.g. the built-in module. TODO: Move these to their * own files for clarity. */ #include "nuitka/prelude.h" #include "HelpersBuiltinTypeMethods.c" void _initBuiltinTypeMethods() { #if PYTHON_VERSION < 0x300 _initStrBuiltinMethods(); #endif _initUnicodeBuiltinMethods(); _initDictBuiltinMethods(); } #include "HelpersBuiltin.c" #include "HelpersClasses.c" #include "HelpersDictionaries.c" #include "HelpersExceptions.c" #include "HelpersHeapStorage.c" #include "HelpersImport.c" #include "HelpersImportHard.c" #include "HelpersRaising.c" #include "HelpersStrings.c" #include "HelpersSafeStrings.c" #if PYTHON_VERSION < 0x300 static Py_ssize_t ESTIMATE_RANGE(long low, long high, long step) { if (low >= high) { return 0; } else { return (high - low - 1) / step + 1; } } static PyObject *_BUILTIN_RANGE_INT3(long low, long high, long step) { assert(step != 0); Py_ssize_t size; if (step > 0) { size = ESTIMATE_RANGE(low, high, step); } else { size = ESTIMATE_RANGE(high, low, -step); } PyObject *result = PyList_New(size); long current = low; for (int i = 0; i < size; i++) { PyList_SET_ITEM(result, i, PyInt_FromLong(current)); current += step; } return result; } static PyObject *_BUILTIN_RANGE_INT2(long low, long high) { return _BUILTIN_RANGE_INT3(low, high, 1); } static PyObject *_BUILTIN_RANGE_INT(long boundary) { PyObject *result = PyList_New(boundary > 0 ? boundary : 0); for (int i = 0; i < boundary; i++) { PyList_SET_ITEM(result, i, PyInt_FromLong(i)); } return result; } static PyObject *TO_RANGE_ARG(PyObject *value, char const *name) { if (likely(PyInt_Check(value) || PyLong_Check(value))) { Py_INCREF(value); return value; } PyTypeObject *type = Py_TYPE(value); PyNumberMethods *tp_as_number = type->tp_as_number; // Everything that casts to int is allowed. if ( #if PYTHON_VERSION >= 0x270 PyFloat_Check(value) || #endif tp_as_number == NULL || tp_as_number->nb_int == NULL) { PyErr_Format(PyExc_TypeError, "range() integer %s argument expected, got %s.", name, type->tp_name); return NULL; } PyObject *result = tp_as_number->nb_int(value); if (unlikely(result == NULL)) { return NULL; } return result; } #endif #if PYTHON_VERSION < 0x300 NUITKA_DEFINE_BUILTIN(range); PyObject *BUILTIN_RANGE(PyObject *boundary) { PyObject *boundary_temp = TO_RANGE_ARG(boundary, "end"); if (unlikely(boundary_temp == NULL)) { return NULL; } long start = PyInt_AsLong(boundary_temp); if (start == -1 && ERROR_OCCURRED()) { CLEAR_ERROR_OCCURRED(); NUITKA_ASSIGN_BUILTIN(range); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(range), boundary_temp); Py_DECREF(boundary_temp); return result; } Py_DECREF(boundary_temp); return _BUILTIN_RANGE_INT(start); } PyObject *BUILTIN_RANGE2(PyObject *low, PyObject *high) { PyObject *low_temp = TO_RANGE_ARG(low, "start"); if (unlikely(low_temp == NULL)) { return NULL; } PyObject *high_temp = TO_RANGE_ARG(high, "end"); if (unlikely(high_temp == NULL)) { Py_DECREF(low_temp); return NULL; } bool fallback = false; long start = PyInt_AsLong(low_temp); if (unlikely(start == -1 && ERROR_OCCURRED())) { CLEAR_ERROR_OCCURRED(); fallback = true; } long end = PyInt_AsLong(high_temp); if (unlikely(end == -1 && ERROR_OCCURRED())) { CLEAR_ERROR_OCCURRED(); fallback = true; } if (fallback) { PyObject *pos_args = PyTuple_New(2); PyTuple_SET_ITEM(pos_args, 0, low_temp); PyTuple_SET_ITEM(pos_args, 1, high_temp); NUITKA_ASSIGN_BUILTIN(range); PyObject *result = CALL_FUNCTION_WITH_POSARGS2(NUITKA_ACCESS_BUILTIN(range), pos_args); Py_DECREF(pos_args); return result; } else { Py_DECREF(low_temp); Py_DECREF(high_temp); return _BUILTIN_RANGE_INT2(start, end); } } PyObject *BUILTIN_RANGE3(PyObject *low, PyObject *high, PyObject *step) { PyObject *low_temp = TO_RANGE_ARG(low, "start"); if (unlikely(low_temp == NULL)) { return NULL; } PyObject *high_temp = TO_RANGE_ARG(high, "end"); if (unlikely(high_temp == NULL)) { Py_DECREF(low_temp); return NULL; } PyObject *step_temp = TO_RANGE_ARG(step, "step"); if (unlikely(high_temp == NULL)) { Py_DECREF(low_temp); Py_DECREF(high_temp); return NULL; } bool fallback = false; long start = PyInt_AsLong(low_temp); if (unlikely(start == -1 && ERROR_OCCURRED())) { CLEAR_ERROR_OCCURRED(); fallback = true; } long end = PyInt_AsLong(high_temp); if (unlikely(end == -1 && ERROR_OCCURRED())) { CLEAR_ERROR_OCCURRED(); fallback = true; } long step_long = PyInt_AsLong(step_temp); if (unlikely(step_long == -1 && ERROR_OCCURRED())) { CLEAR_ERROR_OCCURRED(); fallback = true; } if (fallback) { PyObject *pos_args = PyTuple_New(3); PyTuple_SET_ITEM(pos_args, 0, low_temp); PyTuple_SET_ITEM(pos_args, 1, high_temp); PyTuple_SET_ITEM(pos_args, 2, step_temp); NUITKA_ASSIGN_BUILTIN(range); PyObject *result = CALL_FUNCTION_WITH_POSARGS3(NUITKA_ACCESS_BUILTIN(range), pos_args); Py_DECREF(pos_args); return result; } else { Py_DECREF(low_temp); Py_DECREF(high_temp); Py_DECREF(step_temp); if (unlikely(step_long == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "range() step argument must not be zero"); return NULL; } return _BUILTIN_RANGE_INT3(start, end, step_long); } } #endif #if PYTHON_VERSION < 0x300 /* Same as CPython2: */ static unsigned long getLengthOfRange(long lo, long hi, long step) { assert(step != 0); if (step > 0 && lo < hi) { return 1UL + (hi - 1UL - lo) / step; } else if (step < 0 && lo > hi) { return 1UL + (lo - 1UL - hi) / (0UL - step); } else { return 0UL; } } /* Create a "xrange" object from C long values. Used for constant ranges. */ PyObject *MAKE_XRANGE(long start, long stop, long step) { /* TODO: It would be sweet to calculate that on user side already. */ unsigned long n = getLengthOfRange(start, stop, step); if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_OverflowError, "xrange() result has too many items"); return NULL; } struct _rangeobject2 *result = (struct _rangeobject2 *)PyObject_New(struct _rangeobject2, &PyRange_Type); assert(result != NULL); result->start = start; result->len = (long)n; result->step = step; return (PyObject *)result; } #else /* Same as CPython3: */ static PyObject *getLengthOfRange(PyObject *start, PyObject *stop, PyObject *step) { int res = PyObject_RichCompareBool(step, const_int_0, Py_GT); if (unlikely(res == -1)) { return NULL; } PyObject *lo, *hi; // Make sure we use step as a positive number. if (res == 1) { lo = start; hi = stop; Py_INCREF(step); } else { lo = stop; hi = start; step = PyNumber_Negative(step); if (unlikely(step == NULL)) { return NULL; } res = PyObject_RichCompareBool(step, const_int_0, Py_EQ); if (unlikely(res == -1)) { return NULL; } if (res == 1) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "range() arg 3 must not be zero"); return NULL; } } // Negative difference, we got zero length. res = PyObject_RichCompareBool(lo, hi, Py_GE); if (res != 0) { Py_XDECREF(step); if (res < 0) { return NULL; } Py_INCREF(const_int_0); return const_int_0; } PyObject *tmp1 = PyNumber_Subtract(hi, lo); if (unlikely(tmp1 == NULL)) { Py_DECREF(step); return NULL; } PyObject *diff = PyNumber_Subtract(tmp1, const_int_pos_1); Py_DECREF(tmp1); if (unlikely(diff == NULL)) { Py_DECREF(step); Py_DECREF(tmp1); return NULL; } tmp1 = PyNumber_FloorDivide(diff, step); Py_DECREF(diff); Py_DECREF(step); if (unlikely(tmp1 == NULL)) { return NULL; } PyObject *result = PyNumber_Add(tmp1, const_int_pos_1); Py_DECREF(tmp1); return result; } static PyObject *MAKE_XRANGE(PyObject *start, PyObject *stop, PyObject *step) { start = PyNumber_Index(start); if (unlikely(start == NULL)) { return NULL; } stop = PyNumber_Index(stop); if (unlikely(stop == NULL)) { return NULL; } step = PyNumber_Index(step); if (unlikely(step == NULL)) { return NULL; } PyObject *length = getLengthOfRange(start, stop, step); if (unlikely(length == NULL)) { return NULL; } struct _rangeobject3 *result = (struct _rangeobject3 *)PyObject_New(struct _rangeobject3, &PyRange_Type); assert(result != NULL); result->start = start; result->stop = stop; result->step = step; result->length = length; return (PyObject *)result; } #endif /* Built-in xrange (Python2) or xrange (Python3) with one argument. */ PyObject *BUILTIN_XRANGE1(PyObject *high) { #if PYTHON_VERSION < 0x300 if (unlikely(PyFloat_Check(high))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_high = PyInt_AsLong(high); if (unlikely(int_high == -1 && ERROR_OCCURRED())) { return NULL; } return MAKE_XRANGE(0, int_high, 1); #else PyObject *stop = PyNumber_Index(high); if (unlikely(stop == NULL)) { return NULL; } struct _rangeobject3 *result = (struct _rangeobject3 *)PyObject_New(struct _rangeobject3, &PyRange_Type); assert(result != NULL); result->start = const_int_0; Py_INCREF(const_int_0); result->stop = stop; result->step = const_int_pos_1; Py_INCREF(const_int_pos_1); result->length = stop; Py_INCREF(stop); return (PyObject *)result; #endif } /* Built-in xrange (Python2) or xrange (Python3) with two arguments. */ PyObject *BUILTIN_XRANGE2(PyObject *low, PyObject *high) { #if PYTHON_VERSION < 0x300 if (unlikely(PyFloat_Check(low))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_low = PyInt_AsLong(low); if (unlikely(int_low == -1 && ERROR_OCCURRED())) { return NULL; } if (unlikely(PyFloat_Check(high))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_high = PyInt_AsLong(high); if (unlikely(int_high == -1 && ERROR_OCCURRED())) { return NULL; } return MAKE_XRANGE(int_low, int_high, 1); #else return MAKE_XRANGE(low, high, const_int_pos_1); #endif } /* Built-in xrange (Python2) or xrange (Python3) with three arguments. */ PyObject *BUILTIN_XRANGE3(PyObject *low, PyObject *high, PyObject *step) { #if PYTHON_VERSION < 0x300 if (unlikely(PyFloat_Check(low))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_low = PyInt_AsLong(low); if (unlikely(int_low == -1 && ERROR_OCCURRED())) { return NULL; } if (unlikely(PyFloat_Check(high))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_high = PyInt_AsLong(high); if (unlikely(int_high == -1 && ERROR_OCCURRED())) { return NULL; } if (unlikely(PyFloat_Check(step))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "integer argument expected, got float"); return NULL; } long int_step = PyInt_AsLong(step); if (unlikely(int_step == -1 && ERROR_OCCURRED())) { return NULL; } if (unlikely(int_step == 0)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "range() arg 3 must not be zero"); return NULL; } return MAKE_XRANGE(int_low, int_high, int_step); #else return MAKE_XRANGE(low, high, step); #endif } PyObject *BUILTIN_ALL(PyObject *value) { CHECK_OBJECT(value); PyObject *it = PyObject_GetIter(value); if (unlikely((it == NULL))) { return NULL; } iternextfunc iternext = Py_TYPE(it)->tp_iternext; for (;;) { PyObject *item = iternext(it); if (unlikely((item == NULL))) break; int cmp = PyObject_IsTrue(item); Py_DECREF(item); if (unlikely(cmp < 0)) { Py_DECREF(it); return NULL; } if (cmp == 0) { Py_DECREF(it); Py_INCREF(Py_False); return Py_False; } } Py_DECREF(it); if (unlikely(!CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED())) { return NULL; } Py_INCREF(Py_True); return Py_True; } PyObject *BUILTIN_LEN(PyObject *value) { CHECK_OBJECT(value); Py_ssize_t res = PyObject_Size(value); if (unlikely(res < 0 && ERROR_OCCURRED())) { return NULL; } return PyInt_FromSsize_t(res); } PyObject *BUILTIN_ANY(PyObject *value) { CHECK_OBJECT(value); PyObject *it = PyObject_GetIter(value); if (unlikely((it == NULL))) { return NULL; } iternextfunc iternext = Py_TYPE(it)->tp_iternext; for (;;) { PyObject *item = iternext(it); if (unlikely((item == NULL))) break; int cmp = PyObject_IsTrue(item); Py_DECREF(item); if (unlikely(cmp < 0)) { Py_DECREF(it); return NULL; } if (cmp > 0) { Py_DECREF(it); Py_INCREF(Py_True); return Py_True; } } Py_DECREF(it); if (unlikely(!CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED())) { return NULL; } Py_INCREF(Py_False); return Py_False; } PyObject *BUILTIN_ABS(PyObject *o) { CHECK_OBJECT(o); PyNumberMethods *m = o->ob_type->tp_as_number; if (likely(m && m->nb_absolute)) { return m->nb_absolute(o); } return PyErr_Format(PyExc_TypeError, "bad operand type for abs(): '%s'", Py_TYPE(o)->tp_name); } NUITKA_DEFINE_BUILTIN(format); PyObject *BUILTIN_FORMAT(PyObject *value, PyObject *format_spec) { CHECK_OBJECT(value); CHECK_OBJECT(format_spec); NUITKA_ASSIGN_BUILTIN(format); PyObject *args[2] = {value, format_spec}; return CALL_FUNCTION_WITH_ARGS2(NUITKA_ACCESS_BUILTIN(format), args); } // Helper functions for print. Need to play nice with Python softspace // behaviour. #if PYTHON_VERSION >= 0x300 NUITKA_DEFINE_BUILTIN(print); #endif bool PRINT_NEW_LINE_TO(PyObject *file) { #if PYTHON_VERSION < 0x300 if (file == NULL || file == Py_None) { file = GET_STDOUT(); if (unlikely(file == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "lost sys.stdout"); return false; } } // need to hold a reference to the file or else __getattr__ may release // "file" in the mean time. Py_INCREF(file); if (unlikely(PyFile_WriteString("\n", file) == -1)) { Py_DECREF(file); return false; } PyFile_SoftSpace(file, 0); CHECK_OBJECT(file); Py_DECREF(file); return true; #else NUITKA_ASSIGN_BUILTIN(print); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED_UNTRACED(&exception_type, &exception_value, &exception_tb); PyObject *result; if (likely(file == NULL)) { result = CALL_FUNCTION_NO_ARGS(NUITKA_ACCESS_BUILTIN(print)); } else { PyObject *kw_args = PyDict_New(); PyDict_SetItem(kw_args, const_str_plain_file, GET_STDOUT()); result = CALL_FUNCTION_WITH_KEYARGS(NUITKA_ACCESS_BUILTIN(print), kw_args); Py_DECREF(kw_args); } Py_XDECREF(result); RESTORE_ERROR_OCCURRED_UNTRACED(exception_type, exception_value, exception_tb); return result != NULL; #endif } bool PRINT_ITEM_TO(PyObject *file, PyObject *object) { // The print built-in function cannot replace "softspace" behavior of CPython // print statement, so this code is really necessary. #if PYTHON_VERSION < 0x300 if (file == NULL || file == Py_None) { file = GET_STDOUT(); if (unlikely(file == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "lost sys.stdout"); return false; } } CHECK_OBJECT(file); CHECK_OBJECT(object); // need to hold a reference to the file or else "__getattr__" code may // release "file" in the mean time. Py_INCREF(file); // Check for soft space indicator if (PyFile_SoftSpace(file, 0)) { if (unlikely(PyFile_WriteString(" ", file) == -1)) { Py_DECREF(file); return false; } } if (unlikely(PyFile_WriteObject(object, file, Py_PRINT_RAW) == -1)) { Py_DECREF(file); return false; } if (PyString_Check(object)) { char *buffer; Py_ssize_t length; #ifndef __NUITKA_NO_ASSERT__ int status = #endif PyString_AsStringAndSize(object, &buffer, &length); assert(status != -1); if (length == 0 || !isspace(Py_CHARMASK(buffer[length - 1])) || buffer[length - 1] == ' ') { PyFile_SoftSpace(file, 1); } } else if (PyUnicode_Check(object)) { Py_UNICODE *buffer = PyUnicode_AS_UNICODE(object); Py_ssize_t length = PyUnicode_GET_SIZE(object); if (length == 0 || !Py_UNICODE_ISSPACE(buffer[length - 1]) || buffer[length - 1] == ' ') { PyFile_SoftSpace(file, 1); } } else { PyFile_SoftSpace(file, 1); } CHECK_OBJECT(file); Py_DECREF(file); return true; #else NUITKA_ASSIGN_BUILTIN(print); PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED_UNTRACED(&exception_type, &exception_value, &exception_tb); PyObject *print_kw = PyDict_New(); PyDict_SetItem(print_kw, const_str_plain_end, const_str_empty); if (file == NULL) { PyDict_SetItem(print_kw, const_str_plain_file, GET_STDOUT()); } else { PyDict_SetItem(print_kw, const_str_plain_file, file); } PyObject *print_args = PyTuple_New(1); PyTuple_SET_ITEM(print_args, 0, object); Py_INCREF(object); PyObject *result = CALL_FUNCTION(NUITKA_ACCESS_BUILTIN(print), print_args, print_kw); Py_DECREF(print_args); Py_DECREF(print_kw); Py_XDECREF(result); RESTORE_ERROR_OCCURRED_UNTRACED(exception_type, exception_value, exception_tb); return result != NULL; #endif } void PRINT_REFCOUNT(PyObject *object) { if (object) { char buffer[1024]; snprintf(buffer, sizeof(buffer) - 1, " refcnt %" PY_FORMAT_SIZE_T "d ", Py_REFCNT(object)); PRINT_STRING(buffer); } else { PRINT_STRING(""); } } bool PRINT_STRING(char const *str) { if (str) { PyObject *tmp = PyUnicode_FromString(str); bool res = PRINT_ITEM(tmp); Py_DECREF(tmp); return res; } else { return PRINT_STRING(""); } } bool PRINT_FORMAT(char const *fmt, ...) { va_list args; va_start(args, fmt); // Only used for debug purposes, lets be unsafe here. char buffer[4096]; vsprintf(buffer, fmt, args); return PRINT_STRING(buffer); } bool PRINT_REPR(PyObject *object) { PyObject *exception_type, *exception_value; PyTracebackObject *exception_tb; FETCH_ERROR_OCCURRED_UNTRACED(&exception_type, &exception_value, &exception_tb); bool res; if (object != NULL) { CHECK_OBJECT(object); // Cannot have error set for this function, it asserts against that // in debug builds. PyObject *repr = PyObject_Repr(object); res = PRINT_ITEM(repr); Py_DECREF(repr); } else { res = PRINT_NULL(); } RESTORE_ERROR_OCCURRED_UNTRACED(exception_type, exception_value, exception_tb); return res; } bool PRINT_NULL(void) { return PRINT_STRING(""); } void _PRINT_EXCEPTION(PyObject *exception_type, PyObject *exception_value, PyObject *exception_tb) { PRINT_REPR(exception_type); if (exception_type) { PRINT_REFCOUNT(exception_type); } PRINT_STRING("|"); PRINT_REPR(exception_value); if (exception_value) { PRINT_REFCOUNT(exception_value); } #if PYTHON_VERSION >= 0x300 if (exception_value != NULL && PyExceptionInstance_Check(exception_value)) { PRINT_STRING(" <- context "); PyObject *context = PyException_GetContext(exception_value); PRINT_REPR(context); Py_XDECREF(context); } #endif PRINT_STRING("|"); PRINT_REPR(exception_tb); PRINT_NEW_LINE(); } void PRINT_CURRENT_EXCEPTION(void) { PyThreadState *tstate = PyThreadState_GET(); PRINT_STRING("current_exc="); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); } void PRINT_PUBLISHED_EXCEPTION(void) { PyThreadState *tstate = PyThreadState_GET(); PRINT_STRING("thread_exc="); PRINT_EXCEPTION(EXC_TYPE(tstate), EXC_VALUE(tstate), EXC_TRACEBACK(tstate)); } // TODO: Could be ported, the "printf" stuff would need to be split. On Python3 // the normal C print output gets lost. #if PYTHON_VERSION < 0x300 void PRINT_TRACEBACK(PyTracebackObject *traceback) { PRINT_STRING("Dumping traceback:\n"); if (traceback == NULL) PRINT_STRING("\n"); while (traceback != NULL) { printf(" line %d (frame object chain):\n", traceback->tb_lineno); PyFrameObject *frame = traceback->tb_frame; while (frame != NULL) { printf(" Frame at %s\n", PyString_AsString(PyObject_Str((PyObject *)frame->f_code))); frame = frame->f_back; } assert(traceback->tb_next != traceback); traceback = traceback->tb_next; } PRINT_STRING("End of Dump.\n"); } #endif PyObject *GET_STDOUT() { PyObject *result = Nuitka_SysGetObject("stdout"); if (unlikely(result == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "lost sys.stdout"); return NULL; } return result; } PyObject *GET_STDERR() { PyObject *result = Nuitka_SysGetObject("stderr"); if (unlikely(result == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_RuntimeError, "lost sys.stderr"); return NULL; } return result; } bool PRINT_NEW_LINE(void) { return PRINT_NEW_LINE_TO(NULL); } bool PRINT_ITEM(PyObject *object) { if (object == NULL) { return PRINT_NULL(); } else { return PRINT_ITEM_TO(NULL, object); } } #if PYTHON_VERSION < 0x300 static void set_slot(PyObject **slot, PyObject *value) { PyObject *temp = *slot; Py_XINCREF(value); *slot = value; Py_XDECREF(temp); } static void set_attr_slots(PyClassObject *klass) { set_slot(&klass->cl_getattr, FIND_ATTRIBUTE_IN_CLASS(klass, const_str_plain___getattr__)); set_slot(&klass->cl_setattr, FIND_ATTRIBUTE_IN_CLASS(klass, const_str_plain___setattr__)); set_slot(&klass->cl_delattr, FIND_ATTRIBUTE_IN_CLASS(klass, const_str_plain___delattr__)); } static bool set_dict(PyClassObject *klass, PyObject *value) { if (value == NULL || !PyDict_Check(value)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__dict__ must be a dictionary object"); return false; } else { set_slot(&klass->cl_dict, value); set_attr_slots(klass); return true; } } static bool set_bases(PyClassObject *klass, PyObject *value) { if (value == NULL || !PyTuple_Check(value)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__bases__ must be a tuple object"); return false; } else { Py_ssize_t n = PyTuple_GET_SIZE(value); for (Py_ssize_t i = 0; i < n; i++) { PyObject *base = PyTuple_GET_ITEM(value, i); if (unlikely(!PyClass_Check(base))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__bases__ items must be classes"); return false; } if (unlikely(PyClass_IsSubclass(base, (PyObject *)klass))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "a __bases__ item causes an inheritance cycle"); return false; } } set_slot(&klass->cl_bases, value); set_attr_slots(klass); return true; } } static bool set_name(PyClassObject *klass, PyObject *value) { if (value == NULL || !PyDict_Check(value)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must be a string object"); return false; } if (strlen(PyString_AS_STRING(value)) != (size_t)PyString_GET_SIZE(value)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "__name__ must not contain null bytes"); return false; } set_slot(&klass->cl_name, value); return true; } static int nuitka_class_setattr(PyClassObject *klass, PyObject *attr_name, PyObject *value) { char const *sattr_name = PyString_AsString(attr_name); if (sattr_name[0] == '_' && sattr_name[1] == '_') { Py_ssize_t n = PyString_Size(attr_name); if (sattr_name[n - 2] == '_' && sattr_name[n - 1] == '_') { if (strcmp(sattr_name, "__dict__") == 0) { if (set_dict(klass, value) == false) { return -1; } else { return 0; } } else if (strcmp(sattr_name, "__bases__") == 0) { if (set_bases(klass, value) == false) { return -1; } else { return 0; } } else if (strcmp(sattr_name, "__name__") == 0) { if (set_name(klass, value) == false) { return -1; } else { return 0; } } else if (strcmp(sattr_name, "__getattr__") == 0) { set_slot(&klass->cl_getattr, value); } else if (strcmp(sattr_name, "__setattr__") == 0) { set_slot(&klass->cl_setattr, value); } else if (strcmp(sattr_name, "__delattr__") == 0) { set_slot(&klass->cl_delattr, value); } } } if (value == NULL) { int status = PyDict_DelItem(klass->cl_dict, attr_name); if (status < 0) { PyErr_Format(PyExc_AttributeError, "class %s has no attribute '%s'", PyString_AS_STRING(klass->cl_name), sattr_name); } return status; } else { return PyDict_SetItem(klass->cl_dict, attr_name, value); } } static PyObject *nuitka_class_getattr(PyClassObject *klass, PyObject *attr_name) { char const *sattr_name = PyString_AsString(attr_name); if (sattr_name[0] == '_' && sattr_name[1] == '_') { if (strcmp(sattr_name, "__dict__") == 0) { Py_INCREF(klass->cl_dict); return klass->cl_dict; } else if (strcmp(sattr_name, "__bases__") == 0) { Py_INCREF(klass->cl_bases); return klass->cl_bases; } else if (strcmp(sattr_name, "__name__") == 0) { if (klass->cl_name == NULL) { Py_INCREF(Py_None); return Py_None; } else { Py_INCREF(klass->cl_name); return klass->cl_name; } } } PyObject *value = FIND_ATTRIBUTE_IN_CLASS(klass, attr_name); if (unlikely(value == NULL)) { PyErr_Format(PyExc_AttributeError, "class %s has no attribute '%s'", PyString_AS_STRING(klass->cl_name), sattr_name); return NULL; } PyTypeObject *type = Py_TYPE(value); descrgetfunc tp_descr_get = NuitkaType_HasFeatureClass(type) ? type->tp_descr_get : NULL; if (tp_descr_get == NULL) { Py_INCREF(value); return value; } else { return tp_descr_get(value, (PyObject *)NULL, (PyObject *)klass); } } #endif void enhancePythonTypes(void) { #if PYTHON_VERSION < 0x300 // Our own variant won't call PyEval_GetRestricted, saving quite some cycles // not doing that. PyClass_Type.tp_setattro = (setattrofunc)nuitka_class_setattr; PyClass_Type.tp_getattro = (getattrofunc)nuitka_class_getattr; #endif } #ifdef __APPLE__ #ifdef __cplusplus extern "C" #endif wchar_t * _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size); #endif #ifdef __FreeBSD__ #include #endif #if !defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) PyObject *original_isinstance = NULL; // Note: Installed and used by "InspectPatcher" as "instance" too. int Nuitka_IsInstance(PyObject *inst, PyObject *cls) { CHECK_OBJECT(original_isinstance); CHECK_OBJECT(inst); CHECK_OBJECT(cls); // Quick paths if (Py_TYPE(inst) == (PyTypeObject *)cls) { return true; } // Our paths for the types we need to hook. if (cls == (PyObject *)&PyFunction_Type && Nuitka_Function_Check(inst)) { return true; } if (cls == (PyObject *)&PyGen_Type && Nuitka_Generator_Check(inst)) { return true; } if (cls == (PyObject *)&PyMethod_Type && Nuitka_Method_Check(inst)) { return true; } if (cls == (PyObject *)&PyFrame_Type && Nuitka_Frame_Check(inst)) { return true; } #if PYTHON_VERSION >= 0x350 if (cls == (PyObject *)&PyCoro_Type && Nuitka_Coroutine_Check(inst)) { return true; } #endif #if PYTHON_VERSION >= 0x360 if (cls == (PyObject *)&PyAsyncGen_Type && Nuitka_Asyncgen_Check(inst)) { return true; } #endif // May need to be recursive for tuple arguments. if (PyTuple_Check(cls)) { for (Py_ssize_t i = 0, size = PyTuple_GET_SIZE(cls); i < size; i++) { PyObject *element = PyTuple_GET_ITEM(cls, i); if (unlikely(Py_EnterRecursiveCall((char *)" in __instancecheck__"))) { return -1; } int res = Nuitka_IsInstance(inst, element); Py_LeaveRecursiveCall(); if (res != 0) { return res; } } return 0; } else { PyObject *args[] = {inst, cls}; PyObject *result = CALL_FUNCTION_WITH_ARGS2(original_isinstance, args); if (result == NULL) { return -1; } int res = CHECK_IF_TRUE(result); Py_DECREF(result); if (res == 0) { if (cls == (PyObject *)&PyFunction_Type) { args[1] = (PyObject *)&Nuitka_Function_Type; } else if (cls == (PyObject *)&PyMethod_Type) { args[1] = (PyObject *)&Nuitka_Method_Type; } else if (cls == (PyObject *)&PyFrame_Type) { args[1] = (PyObject *)&Nuitka_Frame_Type; } #if PYTHON_VERSION >= 0x350 else if (cls == (PyObject *)&PyCoro_Type) { args[1] = (PyObject *)&Nuitka_Coroutine_Type; } #endif #if PYTHON_VERSION >= 0x360 else if (cls == (PyObject *)&PyAsyncGen_Type) { args[1] = (PyObject *)&Nuitka_Asyncgen_Type; } #endif else { return 0; } result = CALL_FUNCTION_WITH_ARGS2(original_isinstance, args); if (result == NULL) { return -1; } res = CHECK_IF_TRUE(result); Py_DECREF(result); } return res; } } #endif #define ITERATOR_GENERIC 0 #define ITERATOR_COMPILED_GENERATOR 1 #define ITERATOR_TUPLE 2 #define ITERATOR_LIST 3 struct Nuitka_QuickIterator { int iterator_mode; union { // ITERATOR_GENERIC PyObject *iter; // ITERATOR_COMPILED_GENERATOR struct Nuitka_GeneratorObject *generator; // ITERATOR_TUPLE struct { PyTupleObject *tuple; Py_ssize_t tuple_index; } tuple_data; // ITERATOR_LIST struct { PyListObject *list; Py_ssize_t list_index; } list_data; } iterator_data; }; static bool MAKE_QUICK_ITERATOR(PyObject *sequence, struct Nuitka_QuickIterator *qiter) { if (Nuitka_Generator_Check(sequence)) { qiter->iterator_mode = ITERATOR_COMPILED_GENERATOR; qiter->iterator_data.generator = (struct Nuitka_GeneratorObject *)sequence; } else if (PyTuple_CheckExact(sequence)) { qiter->iterator_mode = ITERATOR_TUPLE; qiter->iterator_data.tuple_data.tuple = (PyTupleObject *)sequence; qiter->iterator_data.tuple_data.tuple_index = 0; } else if (PyList_CheckExact(sequence)) { qiter->iterator_mode = ITERATOR_LIST; qiter->iterator_data.list_data.list = (PyListObject *)sequence; qiter->iterator_data.list_data.list_index = 0; } else { qiter->iterator_mode = ITERATOR_GENERIC; qiter->iterator_data.iter = MAKE_ITERATOR(sequence); if (unlikely(qiter->iterator_data.iter == NULL)) { return false; } } return true; } static PyObject *QUICK_ITERATOR_NEXT(struct Nuitka_QuickIterator *qiter, bool *finished) { PyObject *result; switch (qiter->iterator_mode) { case ITERATOR_GENERIC: result = ITERATOR_NEXT(qiter->iterator_data.iter); if (result == NULL) { Py_DECREF(qiter->iterator_data.iter); if (unlikely(!CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED())) { *finished = false; return NULL; } *finished = true; return NULL; } *finished = false; return result; case ITERATOR_COMPILED_GENERATOR: result = Nuitka_Generator_qiter(qiter->iterator_data.generator, finished); return result; case ITERATOR_TUPLE: if (qiter->iterator_data.tuple_data.tuple_index < PyTuple_GET_SIZE(qiter->iterator_data.tuple_data.tuple)) { result = PyTuple_GET_ITEM(qiter->iterator_data.tuple_data.tuple, qiter->iterator_data.tuple_data.tuple_index); qiter->iterator_data.tuple_data.tuple_index += 1; *finished = false; Py_INCREF(result); return result; } else { *finished = true; return NULL; } case ITERATOR_LIST: if (qiter->iterator_data.list_data.list_index < PyList_GET_SIZE(qiter->iterator_data.list_data.list)) { result = PyList_GET_ITEM(qiter->iterator_data.list_data.list, qiter->iterator_data.list_data.list_index); qiter->iterator_data.list_data.list_index += 1; *finished = false; Py_INCREF(result); return result; } else { *finished = true; return NULL; } } assert(false); return NULL; } PyObject *BUILTIN_SUM1(PyObject *sequence) { struct Nuitka_QuickIterator qiter; if (unlikely(MAKE_QUICK_ITERATOR(sequence, &qiter) == false)) { return NULL; } PyObject *result; long int_result = 0; PyObject *item; for (;;) { bool finished; item = QUICK_ITERATOR_NEXT(&qiter, &finished); if (finished) { #if PYTHON_VERSION < 0x300 return PyInt_FromLong(int_result); #else return PyLong_FromLong(int_result); #endif } else if (item == NULL) { return NULL; } CHECK_OBJECT(item); // For Python2 int objects: #if PYTHON_VERSION < 0x300 if (PyInt_CheckExact(item)) { long b = PyInt_AS_LONG(item); long x = int_result + b; if ((x ^ int_result) >= 0 || (x ^ b) >= 0) { int_result = x; Py_DECREF(item); continue; } } #endif // For Python2 long, Python3 int objects #if PYTHON_VERSION >= 0x270 if (PyLong_CheckExact(item)) { int overflow; long b = PyLong_AsLongAndOverflow(item, &overflow); if (overflow) { break; } long x = int_result + b; if ((x ^ int_result) >= 0 || (x ^ b) >= 0) { int_result = x; Py_DECREF(item); continue; } } #endif if (item == Py_False) { Py_DECREF(item); continue; } if (item == Py_True) { long b = 1; long x = int_result + b; if ((x ^ int_result) >= 0 || (x ^ b) >= 0) { int_result = x; Py_DECREF(item); continue; } } /* Either overflowed or not one of the supported int alike types. */ break; } /* Switch over to objects, and redo last step. */ #if PYTHON_VERSION < 0x300 result = PyInt_FromLong(int_result); #else result = PyLong_FromLong(int_result); #endif CHECK_OBJECT(result); PyObject *temp = PyNumber_Add(result, item); Py_DECREF(result); Py_DECREF(item); result = temp; if (unlikely(result == NULL)) { return NULL; } for (;;) { CHECK_OBJECT(result); bool finished; item = QUICK_ITERATOR_NEXT(&qiter, &finished); if (finished) { break; } else if (item == NULL) { Py_DECREF(result); return NULL; } CHECK_OBJECT(item); PyObject *temp2 = PyNumber_Add(result, item); Py_DECREF(item); Py_DECREF(result); if (unlikely(temp2 == NULL)) { return NULL; } result = temp2; } CHECK_OBJECT(result); return result; } NUITKA_DEFINE_BUILTIN(sum); PyObject *BUILTIN_SUM2(PyObject *sequence, PyObject *start) { NUITKA_ASSIGN_BUILTIN(sum); CHECK_OBJECT(sequence); CHECK_OBJECT(start); PyObject *pos_args = PyTuple_New(2); PyTuple_SET_ITEM(pos_args, 0, sequence); Py_INCREF(sequence); PyTuple_SET_ITEM(pos_args, 1, start); Py_INCREF(start); PyObject *result = CALL_FUNCTION_WITH_POSARGS2(NUITKA_ACCESS_BUILTIN(sum), pos_args); Py_DECREF(pos_args); return result; } PyDictObject *dict_builtin = NULL; PyModuleObject *builtin_module = NULL; static PyTypeObject Nuitka_BuiltinModule_Type = { PyVarObject_HEAD_INIT(NULL, 0) "compiled_module", // tp_name sizeof(PyModuleObject), // tp_size }; int Nuitka_BuiltinModule_SetAttr(PyModuleObject *module, PyObject *name, PyObject *value) { CHECK_OBJECT(module); CHECK_OBJECT(name); // This is used for "del" as well. assert(value == NULL || Py_REFCNT(value) > 0); // only checks the builtins that we can refresh at this time, if we have // many value to check maybe need create a dict first. bool found = false; int res = PyObject_RichCompareBool(name, const_str_plain_open, Py_EQ); if (unlikely(res == -1)) { return -1; } if (res == 1) { NUITKA_UPDATE_BUILTIN(open, value); found = true; } if (found == false) { res = PyObject_RichCompareBool(name, const_str_plain___import__, Py_EQ); if (unlikely(res == -1)) { return -1; } if (res == 1) { NUITKA_UPDATE_BUILTIN(__import__, value); found = true; } } #if PYTHON_VERSION >= 0x300 if (found == false) { res = PyObject_RichCompareBool(name, const_str_plain_print, Py_EQ); if (unlikely(res == -1)) { return -1; } if (res == 1) { NUITKA_UPDATE_BUILTIN(print, value); found = true; } } #endif return PyObject_GenericSetAttr((PyObject *)module, name, value); } #include #if defined(_WIN32) #include #elif defined(__APPLE__) #include #include #include #else #include #include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif PyObject *JOIN_PATH2(PyObject *dirname, PyObject *filename) { CHECK_OBJECT(dirname); CHECK_OBJECT(filename); static PyObject *sep_object = NULL; if (sep_object == NULL) { static char const sep[2] = {SEP, 0}; sep_object = Nuitka_String_FromString(sep); } CHECK_OBJECT(sep_object); // Avoid string APIs, so str, unicode doesn't matter for input. PyObject *result = PyNumber_Add(dirname, sep_object); CHECK_OBJECT(result); result = PyNumber_InPlaceAdd(result, filename); CHECK_OBJECT(result); return result; } #if defined(_NUITKA_EXE) #ifndef _WIN32 char const *getBinaryDirectoryHostEncoded() { static char binary_directory[MAXPATHLEN + 1]; static bool init_done = false; if (init_done) { return binary_directory; } #if defined(__APPLE__) uint32_t bufsize = sizeof(binary_directory); int res = _NSGetExecutablePath(binary_directory, &bufsize); if (unlikely(res != 0)) { abort(); } // On macOS, the "dirname" call creates a separate internal string, we can // safely copy back. copyStringSafe(binary_directory, dirname(binary_directory), sizeof(binary_directory)); #elif defined(__FreeBSD__) || defined(__OpenBSD__) /* Not all of FreeBSD has /proc file system, so use the appropriate * "sysctl" instead. */ int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; size_t cb = sizeof(binary_directory); int res = sysctl(mib, 4, binary_directory, &cb, NULL, 0); if (unlikely(res != 0)) { abort(); } /* We want the directory name, the above gives the full executable name. */ copyStringSafe(binary_directory, dirname(binary_directory), sizeof(binary_directory)); #else /* The remaining platforms, mostly Linux or compatible. */ /* The "readlink" call does not terminate result, so fill zeros there, then * it is a proper C string right away. */ memset(binary_directory, 0, sizeof(binary_directory)); ssize_t res = readlink("/proc/self/exe", binary_directory, sizeof(binary_directory) - 1); if (unlikely(res == -1)) { abort(); } copyStringSafe(binary_directory, dirname(binary_directory), sizeof(binary_directory)); #endif init_done = true; return binary_directory; } #endif #if defined(_WIN32) // Replacement for RemoveFileSpecW, slightly smaller. static void stripFilenameW(wchar_t *path) { wchar_t *last_slash = NULL; while (*path != 0) { if (*path == L'\\') { last_slash = path; } path++; } if (last_slash != NULL) { *last_slash = 0; } } #endif wchar_t const *getBinaryDirectoryWideChars() { static wchar_t binary_directory[MAXPATHLEN + 1]; static bool init_done = false; if (init_done == false) { binary_directory[0] = 0; #ifdef _WIN32 DWORD res = GetModuleFileNameW(NULL, binary_directory, sizeof(binary_directory)); assert(res != 0); stripFilenameW(binary_directory); // Query length of result first. DWORD length = GetShortPathNameW(binary_directory, NULL, 0); assert(length != 0); wchar_t *short_binary_directory = (wchar_t *)malloc((length + 1) * sizeof(wchar_t)); res = GetShortPathNameW(binary_directory, short_binary_directory, length); assert(res != 0); if (unlikely(res > length)) { abort(); } binary_directory[0] = 0; appendWStringSafeW(binary_directory, short_binary_directory, sizeof(binary_directory) / sizeof(wchar_t)); free(short_binary_directory); #else appendStringSafeW(binary_directory, getBinaryDirectoryHostEncoded(), sizeof(binary_directory) / sizeof(wchar_t)); #endif init_done = true; } return (wchar_t const *)binary_directory; } #if defined(_WIN32) && PYTHON_VERSION < 0x300 char const *getBinaryDirectoryHostEncoded() { static char *binary_directory = NULL; if (binary_directory != NULL) { return binary_directory; } wchar_t const *w = getBinaryDirectoryWideChars(); DWORD bufsize = WideCharToMultiByte(CP_ACP, 0, w, -1, NULL, 0, NULL, NULL); assert(bufsize != 0); binary_directory = (char *)malloc(bufsize + 1); assert(binary_directory); DWORD res2 = WideCharToMultiByte(CP_ACP, 0, w, -1, binary_directory, bufsize, NULL, NULL); assert(res2 != 0); if (unlikely(res2 > bufsize)) { abort(); } return (char const *)binary_directory; } #endif static PyObject *getBinaryDirectoryObject() { static PyObject *binary_directory = NULL; if (binary_directory != NULL) { CHECK_OBJECT(binary_directory); return binary_directory; } // On Python3, this must be a unicode object, it cannot be on Python2, // there e.g. code objects expect Python2 strings. #if PYTHON_VERSION >= 0x300 #ifdef _WIN32 wchar_t const *bin_directory = getBinaryDirectoryWideChars(); binary_directory = NuitkaUnicode_FromWideChar(bin_directory, -1); #else binary_directory = PyUnicode_DecodeFSDefault(getBinaryDirectoryHostEncoded()); #endif #else binary_directory = PyString_FromString(getBinaryDirectoryHostEncoded()); #endif if (unlikely(binary_directory == NULL)) { PyErr_Print(); abort(); } // Make sure it's usable for caching. Py_INCREF(binary_directory); return binary_directory; } #ifdef _NUITKA_STANDALONE // Helper function to create path. PyObject *getStandaloneSysExecutablePath(PyObject *basename) { PyObject *dir_name = getBinaryDirectoryObject(); PyObject *sys_executable = JOIN_PATH2(dir_name, basename); return sys_executable; } #endif #else #if defined(_WIN32) /* Small helper function to get current DLL handle. */ static HMODULE getDllModuleHandle() { static HMODULE hm = NULL; if (hm == NULL) { int res = GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&getDllModuleHandle, &hm); assert(res != 0); } assert(hm != NULL); return hm; } #endif #if defined(_WIN32) // Replacement for RemoveFileSpecA, slightly smaller. static void stripFilenameA(char *path) { char *last_slash = NULL; while (*path != 0) { if (*path == '\\') { last_slash = path; } path++; } if (last_slash != NULL) { *last_slash = 0; } } #endif static char const *getDllDirectory() { #if defined(_WIN32) static char path[MAXPATHLEN + 1]; path[0] = '\0'; #if PYTHON_VERSION >= 0x300 WCHAR path2[MAXPATHLEN + 1]; path2[0] = 0; int res = GetModuleFileNameW(getDllModuleHandle(), path2, MAXPATHLEN + 1); assert(res != 0); int res2 = WideCharToMultiByte(CP_UTF8, 0, path2, -1, path, MAXPATHLEN + 1, NULL, NULL); assert(res2 != 0); #else int res = GetModuleFileNameA(getDllModuleHandle(), path, MAXPATHLEN + 1); assert(res != 0); #endif stripFilenameA(path); return path; #else Dl_info where; int res = dladdr((void *)getDllDirectory, &where); assert(res != 0); return dirname((char *)where.dli_fname); #endif } #endif static void _initDeepCopy(); void _initBuiltinModule() { _initBuiltinTypeMethods(); _initDeepCopy(); #if _NUITKA_MODULE if (builtin_module != NULL) { return; } #else assert(builtin_module == NULL); #endif #if PYTHON_VERSION < 0x300 builtin_module = (PyModuleObject *)PyImport_ImportModule("__builtin__"); #else builtin_module = (PyModuleObject *)PyImport_ImportModule("builtins"); #endif assert(builtin_module); dict_builtin = (PyDictObject *)builtin_module->md_dict; assert(PyDict_Check(dict_builtin)); #ifdef _NUITKA_STANDALONE int res = PyDict_SetItemString((PyObject *)dict_builtin, "__nuitka_binary_dir", getBinaryDirectoryObject()); assert(res == 0); #endif // init Nuitka_BuiltinModule_Type, PyType_Ready won't copy all member from // base type, so we need copy all members from PyModule_Type manual for // safety. PyType_Ready will change tp_flags, we need define it again. Set // tp_setattro to Nuitka_BuiltinModule_SetAttr and we can detect value // change. Set tp_base to PyModule_Type and PyModule_Check will pass. Nuitka_BuiltinModule_Type.tp_dealloc = PyModule_Type.tp_dealloc; Nuitka_BuiltinModule_Type.tp_repr = PyModule_Type.tp_repr; Nuitka_BuiltinModule_Type.tp_setattro = (setattrofunc)Nuitka_BuiltinModule_SetAttr; Nuitka_BuiltinModule_Type.tp_getattro = PyModule_Type.tp_getattro; Nuitka_BuiltinModule_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE; Nuitka_BuiltinModule_Type.tp_doc = PyModule_Type.tp_doc; Nuitka_BuiltinModule_Type.tp_traverse = PyModule_Type.tp_traverse; Nuitka_BuiltinModule_Type.tp_members = PyModule_Type.tp_members; Nuitka_BuiltinModule_Type.tp_base = &PyModule_Type; Nuitka_BuiltinModule_Type.tp_dictoffset = PyModule_Type.tp_dictoffset; Nuitka_BuiltinModule_Type.tp_init = PyModule_Type.tp_init; Nuitka_BuiltinModule_Type.tp_alloc = PyModule_Type.tp_alloc; Nuitka_BuiltinModule_Type.tp_new = PyModule_Type.tp_new; Nuitka_BuiltinModule_Type.tp_free = PyModule_Type.tp_free; int ret = PyType_Ready(&Nuitka_BuiltinModule_Type); assert(ret == 0); // Replace type of builtin module to take over. ((PyObject *)builtin_module)->ob_type = &Nuitka_BuiltinModule_Type; assert(PyModule_Check(builtin_module) == 1); } #include "HelpersCalling.c" #include "HelpersCalling2.c" PyObject *MAKE_RELATIVE_PATH(PyObject *relative) { CHECK_OBJECT(relative); static PyObject *our_path_object = NULL; if (our_path_object == NULL) { #if defined(_NUITKA_EXE) our_path_object = getBinaryDirectoryObject(); #else our_path_object = Nuitka_String_FromString(getDllDirectory()); #endif } return JOIN_PATH2(our_path_object, relative); } #ifdef _NUITKA_EXE NUITKA_DEFINE_BUILTIN(type) NUITKA_DEFINE_BUILTIN(len) NUITKA_DEFINE_BUILTIN(repr) NUITKA_DEFINE_BUILTIN(int) NUITKA_DEFINE_BUILTIN(iter) #if PYTHON_VERSION < 0x300 NUITKA_DEFINE_BUILTIN(long) #else NUITKA_DEFINE_BUILTIN(range); #endif void _initBuiltinOriginalValues() { NUITKA_ASSIGN_BUILTIN(type); NUITKA_ASSIGN_BUILTIN(len); NUITKA_ASSIGN_BUILTIN(range); NUITKA_ASSIGN_BUILTIN(repr); NUITKA_ASSIGN_BUILTIN(int); NUITKA_ASSIGN_BUILTIN(iter); #if PYTHON_VERSION < 0x300 NUITKA_ASSIGN_BUILTIN(long); #endif CHECK_OBJECT(_python_original_builtin_value_range); } #endif // Used for threading. #if PYTHON_VERSION >= 0x300 && !defined(NUITKA_USE_PYCORE_THREADSTATE) volatile int _Py_Ticker = _Py_CheckInterval; #endif #if PYTHON_VERSION >= 0x270 iternextfunc default_iternext; void _initSlotIternext() { PyObject *pos_args = PyTuple_New(1); PyTuple_SET_ITEM(pos_args, 0, (PyObject *)&PyBaseObject_Type); Py_INCREF(&PyBaseObject_Type); PyObject *kw_args = PyDict_New(); PyDict_SetItem(kw_args, const_str_plain___iter__, Py_True); PyObject *c = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, const_str_plain___iter__, pos_args, kw_args, NULL); Py_DECREF(pos_args); Py_DECREF(kw_args); PyObject *r = PyObject_CallFunctionObjArgs(c, NULL); Py_DECREF(c); CHECK_OBJECT(r); assert(Py_TYPE(r)->tp_iternext); default_iternext = Py_TYPE(r)->tp_iternext; Py_DECREF(r); } #endif #if PYTHON_VERSION >= 0x3a0 PyObject *MAKE_UNION_TYPE(PyObject *args) { assert(PyTuple_CheckExact(args)); assert(PyTuple_GET_SIZE(args) > 1); CHECK_OBJECT_DEEP(args); PyObject *result = NULL; for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(args); i++) { PyObject *value = PyTuple_GET_ITEM(args, i); if (result == NULL) { assert(i == 0); result = value; } else { result = PyNumber_InPlaceBitor(result, value); } } return result; } #endif #include "HelpersDeepcopy.c" #include "HelpersAttributes.c" #include "HelpersLists.c" #include "HelpersOperationBinaryAdd.c" #include "HelpersOperationBinaryBitand.c" #include "HelpersOperationBinaryBitor.c" #include "HelpersOperationBinaryBitxor.c" #include "HelpersOperationBinaryDivmod.c" #include "HelpersOperationBinaryFloordiv.c" #include "HelpersOperationBinaryLshift.c" #include "HelpersOperationBinaryMod.c" #include "HelpersOperationBinaryMult.c" #include "HelpersOperationBinaryPow.c" #include "HelpersOperationBinaryRshift.c" #include "HelpersOperationBinarySub.c" #include "HelpersOperationBinaryTruediv.c" #if PYTHON_VERSION < 0x300 #include "HelpersOperationBinaryOlddiv.c" #endif #if PYTHON_VERSION >= 0x350 #include "HelpersOperationBinaryMatmult.c" #endif #include "HelpersOperationInplaceAdd.c" #include "HelpersOperationInplaceBitand.c" #include "HelpersOperationInplaceBitor.c" #include "HelpersOperationInplaceBitxor.c" #include "HelpersOperationInplaceFloordiv.c" #include "HelpersOperationInplaceLshift.c" #include "HelpersOperationInplaceMod.c" #include "HelpersOperationInplaceMult.c" #include "HelpersOperationInplacePow.c" #include "HelpersOperationInplaceRshift.c" #include "HelpersOperationInplaceSub.c" #include "HelpersOperationInplaceTruediv.c" #if PYTHON_VERSION < 0x300 #include "HelpersOperationInplaceOlddiv.c" #endif #if PYTHON_VERSION >= 0x350 #include "HelpersOperationInplaceMatmult.c" #endif #include "HelpersComparisonEq.c" #include "HelpersComparisonGe.c" #include "HelpersComparisonGt.c" #include "HelpersComparisonLe.c" #include "HelpersComparisonLt.c" #include "HelpersComparisonNe.c" #include "HelpersConstantsBlob.c" #if _NUITKA_PROFILE #include "HelpersProfiling.c" #endif #if _NUITKA_PGO_PYTHON #include "HelpersPythonPgo.c" #endifNuitka-0.6.19.1/nuitka/build/include/0000700000372100037210000000000014167275622024310 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/build/include/nuitka/0000700000372100037210000000000014167275622025603 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/build/include/nuitka/tracing.h0000600000372100037210000000611014166627112027375 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_TRACING_H__ #define __NUITKA_TRACING_H__ /* Stupid tracing, intended to help where debugging is not an option * and to give kind of progress record of startup and the running of * the program. */ #ifdef _NUITKA_TRACE #define NUITKA_PRINT_TRACE(value) \ { \ puts(value); \ fflush(stdout); \ } #define NUITKA_PRINTF_TRACE(...) \ { \ printf(__VA_ARGS__); \ fflush(stdout); \ } #else #define NUITKA_PRINT_TRACE(value) #define NUITKA_PRINTF_TRACE(...) #endif #if defined(_NUITKA_EXPERIMENTAL_SHOW_STARTUP_TIME) #if defined(_WIN32) #include static void inline PRINT_TIME_STAMP(void) { SYSTEMTIME t; GetSystemTime(&t); // or GetLocalTime(&t) printf("%02d:%02d:%02d.%03d:", t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); } #else static void inline PRINT_TIME_STAMP(void) {} #endif #define NUITKA_PRINT_TIMING(value) \ { \ PRINT_TIME_STAMP(); \ puts(value); \ fflush(stdout); \ } #else #define NUITKA_PRINT_TIMING(value) NUITKA_PRINT_TRACE(value) #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_coroutine.h0000600000372100037210000002010514166627112031631 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_COROUTINE_H__ #define __NUITKA_COMPILED_COROUTINE_H__ // Compiled coroutine type. // Another cornerstone of the integration into CPython. Try to behave as well as // normal coroutine objects do or even better. #if PYTHON_VERSION >= 0x350 // The Nuitka_CoroutineObject is the storage associated with a compiled // coroutine object instance of which there can be many for each code. struct Nuitka_CoroutineObject { /* Python object folklore: */ PyObject_VAR_HEAD PyObject *m_name; // TODO: Only to make traceback for non-started throw PyObject *m_module; PyObject *m_qualname; PyObject *m_yieldfrom; // Weak references are supported for coroutine objects in CPython. PyObject *m_weakrefs; int m_running; // When a coroutine is awaiting, this flag is set. int m_awaiting; void *m_code; // The parent frame of the coroutine, if created. struct Nuitka_FrameObject *m_frame; PyCodeObject *m_code_object; // While yielding, this was the frame currently active, restore when // resuming. struct Nuitka_FrameObject *m_resume_frame; // Was it ever used, is it still running, or already finished. Generator_Status m_status; #if PYTHON_VERSION >= 0x370 _PyErr_StackItem m_exc_state; // The cr_origin attribute. PyObject *m_origin; #endif // The label index to resume after yield. int m_yield_return_index; // Returned value if yielded value is NULL, is // NULL if not a return PyObject *m_returned; // A kind of uuid for the generator object, used in comparisons. long m_counter; /* The heap of generator objects at run time. */ void *m_heap_storage; /* Closure variables given, if any, we reference cells here. The last * part is dynamically allocated, the array size differs per coroutine * and includes the heap storage. */ Py_ssize_t m_closure_given; struct Nuitka_CellObject *m_closure[1]; }; extern PyTypeObject Nuitka_Coroutine_Type; typedef PyObject *(*coroutine_code)(struct Nuitka_CoroutineObject *, PyObject *); extern PyObject *Nuitka_Coroutine_New(coroutine_code code, PyObject *module, PyObject *name, PyObject *qualname, PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size); static inline bool Nuitka_Coroutine_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Coroutine_Type; } struct Nuitka_CoroutineWrapperObject { /* Python object folklore: */ PyObject_HEAD struct Nuitka_CoroutineObject *m_coroutine; }; extern PyTypeObject Nuitka_CoroutineWrapper_Type; static inline bool Nuitka_CoroutineWrapper_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_CoroutineWrapper_Type; } static inline void SAVE_COROUTINE_EXCEPTION(struct Nuitka_CoroutineObject *coroutine) { /* Before Python3.7: When yielding from an exception handler in Python3, * the exception preserved to the frame is restored, while the current one * is put as there. * * Python3.7: The exception is preserved in the coroutine object itself * which has a new "m_exc_state" structure just for that. */ PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; #else EXC_TYPE(thread_state) = coroutine->m_exc_state.exc_type; EXC_VALUE(thread_state) = coroutine->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = coroutine->m_exc_state.exc_traceback; #endif CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); #if PYTHON_VERSION < 0x370 thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else coroutine->m_exc_state.exc_type = saved_exception_type; coroutine->m_exc_state.exc_value = saved_exception_value; coroutine->m_exc_state.exc_traceback = saved_exception_traceback; #endif } static inline void RESTORE_COROUTINE_EXCEPTION(struct Nuitka_CoroutineObject *coroutine) { // When returning from yield, the exception of the frame is preserved, and // the one that enters should be there. PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else EXC_TYPE(thread_state) = coroutine->m_exc_state.exc_type; EXC_VALUE(thread_state) = coroutine->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = coroutine->m_exc_state.exc_traceback; coroutine->m_exc_state.exc_type = saved_exception_type; coroutine->m_exc_state.exc_value = saved_exception_value; coroutine->m_exc_state.exc_traceback = saved_exception_traceback; #endif CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); } #ifdef __cplusplus enum Await_Kind { await_normal, // user provided "await" await_enter, // async with statement "__enter__" await_exit // async with statement "__enter__" }; #else typedef int Generator_Status; static const int await_normal = 0; static const int await_enter = 1; static const int await_exit = 2; #endif // Create the object to await for async for "iter". extern PyObject *ASYNC_MAKE_ITERATOR(PyObject *value); // Create the object to await for async for "next". extern PyObject *ASYNC_ITERATOR_NEXT(PyObject *value); // Create the object for plain "await". extern PyObject *ASYNC_AWAIT(PyObject *awaitable, int await_kind); #endif // For reference count debugging. #if _DEBUG_REFCOUNTS extern int count_active_Nuitka_Coroutine_Type; extern int count_allocated_Nuitka_Coroutine_Type; extern int count_released_Nuitka_Coroutine_Type; extern int count_active_Nuitka_CoroutineWrapper_Type; extern int count_allocated_Nuitka_CoroutineWrapper_Type; extern int count_released_Nuitka_CoroutineWrapper_Type; extern int count_active_Nuitka_AIterWrapper_Type; extern int count_allocated_Nuitka_AIterWrapper_Type; extern int count_released_Nuitka_AIterWrapper_Type; #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/allocator.h0000600000372100037210000000244314166627112027733 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_ALLOCATOR_H__ #define __NUITKA_ALLOCATOR_H__ NUITKA_MAY_BE_UNUSED static void *Nuitka_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) { assert(nitems >= 0); size_t size = _PyObject_VAR_SIZE(tp, nitems); PyVarObject *op = (PyVarObject *)_PyObject_GC_Malloc(size); assert(op != NULL); Py_TYPE(op) = tp; Py_SIZE(op) = size; Py_REFCNT(op) = 1; // TODO: Above assignments might replace this actually. op = PyObject_INIT_VAR(op, tp, nitems); return op; } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helpers.h0000600000372100037210000003715714166627112027427 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPERS_H__ #define __NUITKA_HELPERS_H__ #define _DEBUG_FRAME 0 #define _DEBUG_REFRAME 0 #define _DEBUG_EXCEPTIONS 0 #ifdef _NUITKA_EXPERIMENTAL_DEBUG_GENERATOR #define _DEBUG_GENERATOR 1 #else #define _DEBUG_GENERATOR 0 #endif #ifdef _NUITKA_EXPERIMENTAL_DEBUG_COROUTINE #define _DEBUG_COROUTINE 1 #else #define _DEBUG_COROUTINE 0 #endif #ifdef _NUITKA_EXPERIMENTAL_DEBUG_ASYNCGEN #define _DEBUG_ASYNCGEN 1 #else #define _DEBUG_ASYNCGEN 0 #endif #ifdef _NUITKA_EXPERIMENTAL_DEBUG_CLASSES #define _DEBUG_CLASSES 1 #else #define _DEBUG_CLASSES 0 #endif #ifdef _NUITKA_EXPERIMENTAL_REPORT_REFCOUNTS #define _DEBUG_REFCOUNTS 1 #else #define _DEBUG_REFCOUNTS 0 #endif // From CPython, to allow us quick access to the dictionary of an module, the // structure is normally private, but we need it for quick access to the module // dictionary. typedef struct { /* Python object folklore: */ PyObject_HEAD PyObject *md_dict; } PyModuleObject; // Generated code helpers, used in static helper codes: extern PyObject *CALL_FUNCTION_WITH_ARGS2(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_ARGS3(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_ARGS4(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_ARGS5(PyObject *called, PyObject *const *args); // Most fundamental, because we use it for debugging in everything else. #include "nuitka/helper/printing.h" // Helper to check that an object is valid and has positive reference count. #define CHECK_OBJECT(value) (assert((value) != NULL), assert(Py_REFCNT(value) > 0)) #define CHECK_OBJECT_X(value) (assert((value) == NULL || Py_REFCNT(value) > 0)) // Helper to check an array of objects with CHECK_OBJECT #ifndef __NUITKA_NO_ASSERT__ #define CHECK_OBJECTS(values, count) \ { \ for (int i = 0; i < count; i++) { \ CHECK_OBJECT((values)[i]); \ } \ } #else #define CHECK_OBJECTS(values, count) #endif extern void CHECK_OBJECT_DEEP(PyObject *value); extern void CHECK_OBJECTS_DEEP(PyObject *const *values, Py_ssize_t size); #include "nuitka/exceptions.h" // For use with "--trace-execution", code can make outputs. Otherwise they // are just like comments. #include "nuitka/tracing.h" // For checking values if they changed or not. #ifndef __NUITKA_NO_ASSERT__ extern Py_hash_t DEEP_HASH(PyObject *value); #endif // For profiling of Nuitka compiled binaries #if _NUITKA_PROFILE extern void startProfiling(void); extern void stopProfiling(void); #endif #include "nuitka/helper/boolean.h" #include "nuitka/helper/dictionaries.h" #include "nuitka/helper/mappings.h" #include "nuitka/helper/operations_builtin_types.h" #include "nuitka/helper/sets.h" #include "nuitka/helper/strings.h" #include "nuitka/helper/raising.h" #include "nuitka/helper/richcomparisons.h" #include "nuitka/helper/sequences.h" static inline bool Nuitka_Function_Check(PyObject *object); static inline PyObject *Nuitka_Function_GetName(PyObject *object); static inline bool Nuitka_Generator_Check(PyObject *object); static inline PyObject *Nuitka_Generator_GetName(PyObject *object); #include "nuitka/calling.h" NUITKA_MAY_BE_UNUSED static PyObject *TO_FLOAT(PyObject *value) { PyObject *result; #if PYTHON_VERSION < 0x300 if (PyString_CheckExact(value)) { result = PyFloat_FromString(value, NULL); } #else if (PyUnicode_CheckExact(value)) { result = PyFloat_FromString(value); } #endif else { result = PyNumber_Float(value); } if (unlikely(result == NULL)) { return NULL; } return result; } #include "nuitka/helper/complex.h" #include "nuitka/helper/ints.h" NUITKA_MAY_BE_UNUSED static PyObject *TO_UNICODE3(PyObject *value, PyObject *encoding, PyObject *errors) { CHECK_OBJECT(value); CHECK_OBJECT_X(encoding); CHECK_OBJECT_X(errors); char const *encoding_str; if (encoding == NULL) { encoding_str = NULL; } else if (Nuitka_String_Check(encoding)) { encoding_str = Nuitka_String_AsString_Unchecked(encoding); } #if PYTHON_VERSION < 0x300 else if (PyUnicode_Check(encoding)) { PyObject *uarg2 = _PyUnicode_AsDefaultEncodedString(encoding, NULL); CHECK_OBJECT(uarg2); encoding_str = Nuitka_String_AsString_Unchecked(uarg2); } #endif else { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("unicode() argument 2 must be string, not %s", encoding); return NULL; } char const *errors_str; if (errors == NULL) { errors_str = NULL; } else if (Nuitka_String_Check(errors)) { errors_str = Nuitka_String_AsString_Unchecked(errors); } #if PYTHON_VERSION < 0x300 else if (PyUnicode_Check(errors)) { PyObject *uarg3 = _PyUnicode_AsDefaultEncodedString(errors, NULL); CHECK_OBJECT(uarg3); errors_str = Nuitka_String_AsString_Unchecked(uarg3); } #endif else { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("unicode() argument 3 must be string, not %s", errors); return NULL; } PyObject *result = PyUnicode_FromEncodedObject(value, encoding_str, errors_str); if (unlikely(result == NULL)) { return NULL; } assert(PyUnicode_Check(result)); return result; } NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_VARS(PyObject *source) { CHECK_OBJECT(source); PyObject *result = PyObject_GetAttr(source, const_str_plain___dict__); if (unlikely(result == NULL)) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "vars() argument must have __dict__ attribute"); return NULL; } return result; } #include "nuitka/helper/attributes.h" #include "nuitka/helper/bytearrays.h" #include "nuitka/helper/iterators.h" #include "nuitka/helper/lists.h" #include "nuitka/helper/rangeobjects.h" #include "nuitka/helper/slices.h" #include "nuitka/helper/subscripts.h" #include "nuitka/helper/tuples.h" #include "nuitka/builtins.h" #include "nuitka/allocator.h" #include "helper/operations.h" // Compile source code given, pretending the file name was given. #if PYTHON_VERSION < 0x300 extern PyObject *COMPILE_CODE(PyObject *source_code, PyObject *file_name, PyObject *mode, PyObject *flags, PyObject *dont_inherit); #else extern PyObject *COMPILE_CODE(PyObject *source_code, PyObject *file_name, PyObject *mode, PyObject *flags, PyObject *dont_inherit, PyObject *optimize); #endif #if PYTHON_VERSION < 0x300 extern bool EXEC_FILE_ARG_HANDLING(PyObject **prog, PyObject **name); #endif // For quicker built-in open() functionality. #if PYTHON_VERSION < 0x300 extern PyObject *BUILTIN_OPEN(PyObject *file_name, PyObject *mode, PyObject *buffering); #else extern PyObject *BUILTIN_OPEN(PyObject *file_name, PyObject *mode, PyObject *buffering, PyObject *encoding, PyObject *errors, PyObject *newline, PyObject *closefd, PyObject *opener); #endif // For quicker built-in chr() functionality. extern PyObject *BUILTIN_CHR(PyObject *value); // For quicker built-in ord() functionality. extern PyObject *BUILTIN_ORD(PyObject *value); // For quicker built-in bin() functionality. extern PyObject *BUILTIN_BIN(PyObject *value); // For quicker built-in oct() functionality. extern PyObject *BUILTIN_OCT(PyObject *value); // For quicker built-in hex() functionality. extern PyObject *BUILTIN_HEX(PyObject *value); // For quicker callable() functionality. extern PyObject *BUILTIN_CALLABLE(PyObject *value); // For quicker iter() functionality if 2 arguments arg given. extern PyObject *BUILTIN_ITER2(PyObject *callable, PyObject *sentinel); // For quicker type() functionality if 1 argument is given. extern PyObject *BUILTIN_TYPE1(PyObject *arg); // For quicker type() functionality if 3 arguments are given (to build a new // type). extern PyObject *BUILTIN_TYPE3(PyObject *module_name, PyObject *name, PyObject *bases, PyObject *dict); // For built-in built-in len() functionality. extern PyObject *BUILTIN_LEN(PyObject *boundary); // For built-in built-in any() functionality. extern PyObject *BUILTIN_ANY(PyObject *value); // For built-in built-in super() no args and 2 user args functionality. extern PyObject *BUILTIN_SUPER2(PyObject *type, PyObject *object); extern PyObject *BUILTIN_SUPER0(PyObject *type, PyObject *object); // For built-in built-in all() functionality. extern PyObject *BUILTIN_ALL(PyObject *value); #if !defined(_NUITKA_EXPERIMENTAL_FUNCTION_BASE) // The patched isinstance() functionality used for the built-in. extern int Nuitka_IsInstance(PyObject *inst, PyObject *cls); #endif // For built-in getattr() functionality. extern PyObject *BUILTIN_GETATTR(PyObject *object, PyObject *attribute, PyObject *default_value); // For built-in setattr() functionality. extern PyObject *BUILTIN_SETATTR(PyObject *object, PyObject *attribute, PyObject *value); // For built-in bytearray() functionality. extern PyObject *BUILTIN_BYTEARRAY1(PyObject *value); extern PyObject *BUILTIN_BYTEARRAY3(PyObject *string, PyObject *encoding, PyObject *errors); // For built-in hash() functionality. extern PyObject *BUILTIN_HASH(PyObject *value); extern Py_hash_t HASH_VALUE_WITHOUT_ERROR(PyObject *value); extern Py_hash_t HASH_VALUE_WITH_ERROR(PyObject *value); // For built-in sum() functionality. extern PyObject *BUILTIN_SUM1(PyObject *sequence); extern PyObject *BUILTIN_SUM2(PyObject *sequence, PyObject *start); // For built-in built-in abs() functionality. extern PyObject *BUILTIN_ABS(PyObject *o); // For built-in bytes() functionality. #if PYTHON_VERSION >= 0x300 extern PyObject *BUILTIN_BYTES1(PyObject *value); extern PyObject *BUILTIN_BYTES3(PyObject *value, PyObject *encoding, PyObject *errors); #endif // For built-in eval() functionality, works on byte compiled code already. extern PyObject *EVAL_CODE(PyObject *code, PyObject *globals, PyObject *locals); // For built-in format() functionality. extern PyObject *BUILTIN_FORMAT(PyObject *value, PyObject *format_spec); // For built-in staticmethod() functionality. extern PyObject *BUILTIN_STATICMETHOD(PyObject *function); // For built-in classmethod() functionality. extern PyObject *BUILTIN_CLASSMETHOD(PyObject *function); // For built-in "int()" functionality with 2 arguments. extern PyObject *BUILTIN_INT2(PyObject *value, PyObject *base); #if PYTHON_VERSION < 0x300 // For built-in "long()" functionality with 2 arguments. extern PyObject *BUILTIN_LONG2(PyObject *value, PyObject *base); #endif #include "nuitka/importing.h" // Hard imports have their own helpers. #include "nuitka/helper/import_hard.h" // For the constant loading: // Call this to initialize all common constants pre-main. extern void createGlobalConstants(void); // Call this to check of common constants are still intact. #ifndef __NUITKA_NO_ASSERT__ extern void checkGlobalConstants(void); #ifdef _NUITKA_EXE extern void checkModuleConstants___main__(void); #endif #endif // Call this to initialize __main__ constants in non-standard processes. #ifdef _NUITKA_EXE extern void createMainModuleConstants(void); #endif // Unstreaming constants from a blob. #include "nuitka/constants_blob.h" // Performance enhancements to Python types. extern void enhancePythonTypes(void); // Setup meta path based loader if any. extern void setupMetaPathBasedLoader(void); // Replace built-in functions with ones that accept compiled types too. extern void patchBuiltinModule(void); /* Replace inspect functions with ones that handle compiles types too. */ #if PYTHON_VERSION >= 0x300 extern void patchInspectModule(void); #endif // Replace type comparison with one that accepts compiled types too, will work // for "==" and "!=", but not for "is" checks. extern void patchTypeComparison(void); // Patch the CPython type for tracebacks and make it use a freelist mechanism // to be slightly faster for exception control flows. extern void patchTracebackDealloc(void); // Initialize value for "tp_compare" and "tp_init" defaults. extern void _initSlotCompare(void); // Default __init__ slot wrapper. extern python_initproc default_tp_init_wrapper; #if PYTHON_VERSION >= 0x300 // Select the metaclass from specified one and given bases. extern PyObject *SELECT_METACLASS(PyObject *metaclass, PyObject *bases); #endif NUITKA_MAY_BE_UNUSED static PyObject *MODULE_NAME1(PyObject *module) { assert(PyModule_Check(module)); PyObject *module_dict = ((PyModuleObject *)module)->md_dict; return DICT_GET_ITEM1(module_dict, const_str_plain___name__); } NUITKA_MAY_BE_UNUSED static PyObject *MODULE_NAME0(PyObject *module) { assert(PyModule_Check(module)); PyObject *module_dict = ((PyModuleObject *)module)->md_dict; return DICT_GET_ITEM0(module_dict, const_str_plain___name__); } // Get the binary directory was wide characters. extern wchar_t const *getBinaryDirectoryWideChars(); #if !defined(_WIN32) || PYTHON_VERSION < 0x300 // Get the binary directory, translated to native path extern char const *getBinaryDirectoryHostEncoded(); #endif #if _NUITKA_STANDALONE extern void setEarlyFrozenModulesFileAttribute(void); #endif /* For making paths relative to where we got loaded from. Do not provide any * absolute paths as relative value, this is not as capable as "os.path.join", * instead just works on strings. */ extern PyObject *MAKE_RELATIVE_PATH(PyObject *relative); /* For concatenating two elemented path, typically a dirname and a filename. We do this in a lot of helper code, and this is shared functionality. */ extern PyObject *JOIN_PATH2(PyObject *dirname, PyObject *filename); #include NUITKA_MAY_BE_UNUSED static PyObject *MAKE_TUPLE(PyObject *const *elements, Py_ssize_t size) { PyObject *result = PyTuple_New(size); for (Py_ssize_t i = 0; i < size; i++) { PyObject *item = elements[i]; Py_INCREF(item); PyTuple_SET_ITEM(result, i, item); } return result; } // Make a deep copy of an object of general or specific type. extern PyObject *DEEP_COPY(PyObject *value); extern PyObject *DEEP_COPY_DICT(PyObject *value); extern PyObject *DEEP_COPY_LIST(PyObject *value); extern PyObject *DEEP_COPY_TUPLE(PyObject *value); extern PyObject *DEEP_COPY_SET(PyObject *value); // Force a garbage collection, for debugging purposes. NUITKA_MAY_BE_UNUSED static void forceGC() { PyObject_CallObject(PyObject_GetAttrString(PyImport_ImportModule("gc"), "collect"), NULL); } // We provide the sys.version info shortcut as a global value here for ease of use. extern PyObject *Py_SysVersionInfo; #include "nuitka/python_pgo.h" extern PyObject *MAKE_UNION_TYPE(PyObject *args); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/freelists.h0000600000372100037210000001415514166627112027756 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_FREELISTS_H__ #define __NUITKA_FREELISTS_H__ #define allocateFromFreeList(free_list, object_type, type_type, size) \ if (free_list != NULL) { \ result = free_list; \ free_list = *((object_type **)free_list); \ free_list##_count -= 1; \ assert(free_list##_count >= 0); \ \ if (Py_SIZE(result) < size) { \ result = PyObject_GC_Resize(object_type, result, size); \ assert(result != NULL); \ } \ \ _Py_NewReference((PyObject *)result); \ } else { \ result = (object_type *)Nuitka_GC_NewVar(&type_type, size); \ } \ CHECK_OBJECT(result); #define allocateFromFreeListFixed(free_list, object_type, type_type) \ if (free_list != NULL) { \ result = free_list; \ free_list = *((object_type **)free_list); \ free_list##_count -= 1; \ assert(free_list##_count >= 0); \ \ _Py_NewReference((PyObject *)result); \ } else { \ result = (object_type *)PyObject_GC_New(object_type, &type_type); \ } \ CHECK_OBJECT(result); #define releaseToFreeList(free_list, object, max_free_list_count) \ if (free_list != NULL) { \ if (free_list##_count > max_free_list_count) { \ PyObject_GC_Del(object); \ } else { \ *((void **)object) = (void *)free_list; \ free_list = object; \ \ free_list##_count += 1; \ } \ } else { \ free_list = object; \ *((void **)object) = NULL; \ \ assert(free_list##_count == 0); \ \ free_list##_count += 1; \ } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_frame.h0000600000372100037210000002132514166627112030721 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_FRAME_H__ #define __NUITKA_COMPILED_FRAME_H__ // Create a frame object for the given code object, frame or module. extern struct Nuitka_FrameObject *MAKE_MODULE_FRAME(PyCodeObject *code, PyObject *module); extern struct Nuitka_FrameObject *MAKE_FUNCTION_FRAME(PyCodeObject *code, PyObject *module, Py_ssize_t locals_size); // Create a code object for the given filename and function name #if PYTHON_VERSION < 0x300 #define MAKE_CODEOBJECT(filename, line, flags, function_name, argnames, freevars, arg_count, kw_only_count, \ pos_only_count) \ makeCodeObject(filename, line, flags, function_name, argnames, freevars, arg_count) extern PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name, PyObject *argnames, PyObject *freevars, int arg_count); #elif PYTHON_VERSION < 0x380 #define MAKE_CODEOBJECT(filename, line, flags, function_name, argnames, freevars, arg_count, kw_only_count, \ pos_only_count) \ makeCodeObject(filename, line, flags, function_name, argnames, freevars, arg_count, kw_only_count) extern PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name, PyObject *argnames, PyObject *freevars, int arg_count, int kw_only_count); #else #define MAKE_CODEOBJECT(filename, line, flags, function_name, argnames, freevars, arg_count, kw_only_count, \ pos_only_count) \ makeCodeObject(filename, line, flags, function_name, argnames, freevars, arg_count, kw_only_count, pos_only_count) extern PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name, PyObject *argnames, PyObject *freevars, int arg_count, int kw_only_count, int pos_only_count); #endif extern PyTypeObject Nuitka_Frame_Type; static inline bool Nuitka_Frame_Check(PyObject *object) { CHECK_OBJECT(object); return Py_TYPE(object) == &Nuitka_Frame_Type; } struct Nuitka_FrameObject { PyFrameObject m_frame; // Our own extra stuff, attached variables. char const *m_type_description; char m_locals_storage[1]; }; inline static void assertCodeObject(PyCodeObject *code_object) { CHECK_OBJECT(code_object); } NUITKA_MAY_BE_UNUSED static inline bool isFrameUnusable(struct Nuitka_FrameObject *frame_object) { CHECK_OBJECT_X(frame_object); bool result = // Never used. frame_object == NULL || // Still in use Py_REFCNT(frame_object) > 1 || #if PYTHON_VERSION < 0x340 // Last used by another thread (TODO: Could just set it when re-using) frame_object->m_frame.f_tstate != PyThreadState_GET() || #endif // Not currently linked. frame_object->m_frame.f_back != NULL; #if _DEBUG_REFRAME if (result && frame_object != NULL) { PRINT_STRING("NOT REUSING FRAME:"); PRINT_ITEM((PyObject *)frame_object); PRINT_REFCOUNT((PyObject *)frame_object); if (frame_object->m_frame.f_back) { PRINT_ITEM((PyObject *)frame_object->m_frame.f_back); } PRINT_NEW_LINE(); } #endif return result; } #if _DEBUG_REFCOUNTS extern int count_active_frame_cache_instances; extern int count_allocated_frame_cache_instances; extern int count_released_frame_cache_instances; extern int count_hit_frame_cache_instances; #endif extern void dumpFrameStack(void); inline static void assertFrameObject(struct Nuitka_FrameObject *frame_object) { CHECK_OBJECT(frame_object); assertCodeObject(frame_object->m_frame.f_code); } // Mark frame as currently executed. Starting with Python 3.4 that means it // can or cannot be cleared, or should lead to a generator close. For Python2 // this is a no-op. Using a define to spare the compile from inlining an empty // function. #if PYTHON_VERSION >= 0x340 static inline void Nuitka_Frame_MarkAsExecuting(struct Nuitka_FrameObject *frame) { CHECK_OBJECT(frame); #if PYTHON_VERSION >= 0x3a0 frame->m_frame.f_state = FRAME_EXECUTING; #else frame->m_frame.f_executing = 1; #endif } #else #define Nuitka_Frame_MarkAsExecuting(frame) ; #endif #if PYTHON_VERSION >= 0x340 static inline void Nuitka_Frame_MarkAsNotExecuting(struct Nuitka_FrameObject *frame) { CHECK_OBJECT(frame); #if PYTHON_VERSION >= 0x3a0 frame->m_frame.f_state = FRAME_SUSPENDED; #else frame->m_frame.f_executing = 0; #endif } #else #define Nuitka_Frame_MarkAsNotExecuting(frame) ; #endif #if PYTHON_VERSION >= 0x340 static inline bool Nuitka_Frame_IsExecuting(struct Nuitka_FrameObject *frame) { CHECK_OBJECT(frame); #if PYTHON_VERSION >= 0x3a0 return frame->m_frame.f_state == FRAME_EXECUTING; #else return frame->m_frame.f_executing == 1; #endif } #endif // Put frame at the top of the frame stack and mark as executing. NUITKA_MAY_BE_UNUSED inline static void pushFrameStack(struct Nuitka_FrameObject *frame_object) { // Make sure it's healthy. assertFrameObject(frame_object); // We don't allow frame objects where this is not true. assert(frame_object->m_frame.f_back == NULL); // Look at current frame, "old" is the one previously active. PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *old = tstate->frame; CHECK_OBJECT_X(old); #if _DEBUG_FRAME if (old) { assertCodeObject(old->f_code); printf("Upstacking to frame %s %s\n", Nuitka_String_AsString(PyObject_Str((PyObject *)old)), Nuitka_String_AsString(PyObject_Repr((PyObject *)old->f_code))); } #endif // No recursion with identical frames allowed, assert against it. assert(old != &frame_object->m_frame); // Push the new frame as the currently active one. tstate->frame = (PyFrameObject *)frame_object; // Transfer ownership of old frame. if (old != NULL) { assertFrameObject((struct Nuitka_FrameObject *)old); frame_object->m_frame.f_back = old; } Nuitka_Frame_MarkAsExecuting(frame_object); Py_INCREF(frame_object); #if _DEBUG_FRAME printf("Now at top frame %s %s\n", Nuitka_String_AsString(PyObject_Str((PyObject *)tstate->frame)), Nuitka_String_AsString(PyObject_Repr((PyObject *)tstate->frame->f_code))); #endif } NUITKA_MAY_BE_UNUSED inline static void popFrameStack(void) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *old = tstate->frame; CHECK_OBJECT(old); #if _DEBUG_FRAME printf("Taking off frame %s %s\n", Nuitka_String_AsString(PyObject_Str((PyObject *)old)), Nuitka_String_AsString(PyObject_Repr((PyObject *)old->f_code))); #endif // Put previous frame on top. tstate->frame = old->f_back; old->f_back = NULL; Nuitka_Frame_MarkAsNotExecuting((struct Nuitka_FrameObject *)old); Py_DECREF(old); #if _DEBUG_FRAME if (tstate->frame) { printf("Now at top frame %s %s\n", Nuitka_String_AsString(PyObject_Str((PyObject *)tstate->frame)), Nuitka_String_AsString(PyObject_Repr((PyObject *)tstate->frame->f_code))); } else { printf("Now at top no frame\n"); } #endif } // Attach locals to a frame object. TODO: Upper case, this is for generated code only. extern void Nuitka_Frame_AttachLocals(struct Nuitka_FrameObject *frame, char const *type_description, ...); // Codes used for type_description. #define NUITKA_TYPE_DESCRIPTION_NULL 'N' #define NUITKA_TYPE_DESCRIPTION_CELL 'c' #define NUITKA_TYPE_DESCRIPTION_OBJECT 'o' #define NUITKA_TYPE_DESCRIPTION_OBJECT_PTR 'O' #define NUITKA_TYPE_DESCRIPTION_BOOL 'b' #if _DEBUG_REFCOUNTS extern int count_active_Nuitka_Frame_Type; extern int count_allocated_Nuitka_Frame_Type; extern int count_released_Nuitka_Frame_Type; #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/unfreezing.h0000600000372100037210000000417214166627112030130 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_UNFREEZING_H__ #define __NUITKA_UNFREEZING_H__ /* Modes for loading modules, can be compiled, external shared library, or * bytecode. */ #define NUITKA_COMPILED_MODULE 0 #define NUITKA_SHLIB_FLAG 1 #define NUITKA_PACKAGE_FLAG 2 #define NUITKA_BYTECODE_FLAG 4 #define NUITKA_ABORT_MODULE_FLAG 8 #define NUITKA_TRANSLATED_FLAG 16 struct Nuitka_MetaPathBasedLoaderEntry; typedef PyObject *(*module_initfunc)(PyObject *module, struct Nuitka_MetaPathBasedLoaderEntry const *loader_entry); struct Nuitka_MetaPathBasedLoaderEntry { /* Full module name, including package name. */ char const *name; /* Entry function if compiled module, otherwise NULL. */ module_initfunc python_initfunc; /* For bytecode modules, start and size inside the constants blob. */ int bytecode_index; int bytecode_size; /* Flags: Indicators if this is compiled, bytecode or shared library. */ int flags; }; /* For embedded modules, register the meta path based loader. Used by main * program/package only. */ extern void registerMetaPathBasedUnfreezer(struct Nuitka_MetaPathBasedLoaderEntry *loader_entries, unsigned char **bytecode_data); /* Create a loader object responsible for a package. */ extern PyObject *Nuitka_Loader_New(struct Nuitka_MetaPathBasedLoaderEntry const *entry); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/importing.h0000600000372100037210000001137114166627112027763 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_IMPORTING_H__ #define __NUITKA_IMPORTING_H__ /* These are for the built-in import. * * They call the real thing with varying amount of arguments. For keyword * calls using default values, the _KW helper is used. * */ extern PyObject *IMPORT_MODULE1(PyObject *module_name); extern PyObject *IMPORT_MODULE2(PyObject *module_name, PyObject *globals); extern PyObject *IMPORT_MODULE3(PyObject *module_name, PyObject *globals, PyObject *locals); extern PyObject *IMPORT_MODULE4(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items); extern PyObject *IMPORT_MODULE5(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items, PyObject *level); extern PyObject *IMPORT_MODULE_KW(PyObject *module_name, PyObject *globals, PyObject *locals, PyObject *import_items, PyObject *level); extern bool IMPORT_MODULE_STAR(PyObject *target, bool is_module, PyObject *module); // Import an embedded module directly. extern PyObject *IMPORT_EMBEDDED_MODULE(char const *name); // Execute a module, the module object is prepared empty, but with __name__. extern PyObject *EXECUTE_EMBEDDED_MODULE(PyObject *module); // Import a name from a module. extern PyObject *IMPORT_NAME(PyObject *module, PyObject *import_name); // import a name from a module, potentially making an import of it if necessary. #if PYTHON_VERSION >= 0x350 extern PyObject *IMPORT_NAME_OR_MODULE(PyObject *module, PyObject *globals, PyObject *import_name, PyObject *level); #endif #if PYTHON_VERSION >= 0x300 extern PyObject *getImportLibBootstrapModule(); #endif // Replacement for PyImport_GetModule working across all versions and less checks. NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_GetModule(PyObject *module_name) { #if PYTHON_VERSION < 0x370 return DICT_GET_ITEM1(PyImport_GetModuleDict(), module_name); #else return PyImport_GetModule(module_name); #endif } // Replacement for PyImport_GetModule working across all versions and less checks. NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_GetModuleString(char const *module_name) { PyObject *module_name_object = Nuitka_String_FromString(module_name); PyObject *result = Nuitka_GetModule(module_name_object); Py_DECREF(module_name_object); return result; } // Add a module to the modules dictionary from name object NUITKA_MAY_BE_UNUSED static bool Nuitka_SetModule(PyObject *module_name, PyObject *module) { CHECK_OBJECT(module_name); CHECK_OBJECT(module); assert(PyModule_Check(module)); return SET_SUBSCRIPT(PyImport_GetModuleDict(), module_name, module); } // Add a module to the modules dictionary from name C string NUITKA_MAY_BE_UNUSED static bool Nuitka_SetModuleString(char const *module_name, PyObject *module) { PyObject *module_name_object = Nuitka_String_FromString(module_name); bool result = Nuitka_SetModule(module_name_object, module); Py_DECREF(module_name_object); return result; } // Remove a module to the modules dictionary from name object NUITKA_MAY_BE_UNUSED static bool Nuitka_DelModule(PyObject *module_name) { CHECK_OBJECT(module_name); PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); bool result = DEL_SUBSCRIPT(PyImport_GetModuleDict(), module_name); RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); return result; } // Wrapper for PyModule_GetFilenameObject that has no error. NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_GetFilenameObject(PyObject *module) { #if PYTHON_VERSION < 0x300 PyObject *filename = LOOKUP_ATTRIBUTE(module, const_str_plain___file__); #else PyObject *filename = PyModule_GetFilenameObject(module); #endif if (unlikely(filename == NULL)) { DROP_ERROR_OCCURRED(); filename = PyUnicode_FromString("unknown location"); } return filename; } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/threading.h0000600000372100037210000000707514166627112027726 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_THREADING_H__ #define __NUITKA_THREADING_H__ #if PYTHON_VERSION < 0x300 // We share this with CPython bytecode main loop. PyAPI_DATA(volatile int) _Py_Ticker; #else extern volatile int _Py_Ticker; #define _Py_CheckInterval 20 #endif #ifdef NUITKA_USE_PYCORE_THREADSTATE #if PYTHON_VERSION < 0x380 // Signals pending got their own indicator only in 3.8, covered by calls to do before. #define HAS_WORK_TO_DO(ceval, ceval2) (ceval2->pending.calls_to_do._value) #else #define HAS_WORK_TO_DO(ceval, ceval2) (ceval->signals_pending._value || ceval2->pending.calls_to_do._value) #endif NUITKA_MAY_BE_UNUSED static inline bool CONSIDER_THREADING(void) { PyThreadState *tstate = PyThreadState_GET(); #if PYTHON_VERSION >= 0x390 _PyRuntimeState *const runtime = tstate->interp->runtime; #else _PyRuntimeState *const runtime = &_PyRuntime; #endif // This was split in 2 parts in 3.9 or higher. struct _ceval_runtime_state *ceval = &runtime->ceval; #if PYTHON_VERSION >= 0x390 struct _ceval_state *ceval2 = &tstate->interp->ceval; #else struct _ceval_runtime_state *ceval2 = ceval; #endif /* Pending signals or calls to do*/ if (HAS_WORK_TO_DO(ceval, ceval2)) { int res = Py_MakePendingCalls(); if (unlikely(res < 0 && ERROR_OCCURRED())) { return false; } } /* GIL drop request */ if (ceval2->gil_drop_request._value) { /* Give another thread a chance */ PyEval_SaveThread(); PyEval_AcquireThread(tstate); } if (unlikely(tstate->async_exc != NULL)) { PyObject *async_exc = tstate->async_exc; tstate->async_exc = NULL; Py_INCREF(async_exc); RESTORE_ERROR_OCCURRED(async_exc, NULL, NULL); return false; } return true; } #else NUITKA_MAY_BE_UNUSED static inline bool CONSIDER_THREADING(void) { // Decrease ticker if (--_Py_Ticker < 0) { _Py_Ticker = _Py_CheckInterval; int res = Py_MakePendingCalls(); if (unlikely(res < 0 && ERROR_OCCURRED())) { return false; } PyThreadState *tstate = PyThreadState_GET(); assert(tstate); if (PyEval_ThreadsInitialized()) { // Release and acquire the GIL, it's very inefficient, because we // don't even know if it makes sense to do it. A controlling thread // should be used to determine if it's needed at all. PyEval_SaveThread(); PyEval_AcquireThread(tstate); } if (unlikely(tstate->async_exc != NULL)) { PyObject *async_exc = tstate->async_exc; tstate->async_exc = NULL; Py_INCREF(async_exc); RESTORE_ERROR_OCCURRED(async_exc, NULL, NULL); return false; } } return true; } #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_cell.h0000600000372100037210000000372214166627112030547 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_CELL_H__ #define __NUITKA_COMPILED_CELL_H__ /* This is a clone of the normal PyCell structure. We should keep it binary * compatible, just in case somebody crazy insists on it. */ extern PyTypeObject Nuitka_Cell_Type; static inline bool Nuitka_Cell_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Cell_Type; } struct Nuitka_CellObject { /* Python object folklore: */ PyObject_HEAD /* Content of the cell or NULL when empty */ PyObject *ob_ref; }; // Create cell with out value, and with or without reference given. extern struct Nuitka_CellObject *Nuitka_Cell_Empty(void); extern struct Nuitka_CellObject *Nuitka_Cell_New0(PyObject *value); extern struct Nuitka_CellObject *Nuitka_Cell_New1(PyObject *value); // Check stuff while accessing a compile cell in debug mode. #ifdef __NUITKA_NO_ASSERT__ #define Nuitka_Cell_GET(cell) (((struct Nuitka_CellObject *)(cell))->ob_ref) #else #define Nuitka_Cell_GET(cell) \ (CHECK_OBJECT(cell), assert(Nuitka_Cell_Check((PyObject *)cell)), (((struct Nuitka_CellObject *)(cell))->ob_ref)) #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_asyncgen.h0000600000372100037210000002015214166627112031433 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_ASYNCGEN_H__ #define __NUITKA_COMPILED_ASYNCGEN_H__ // Compiled async generator type. // Another cornerstone of the integration into CPython. Try to behave as well as // normal asyncgen objects do or even better. #if PYTHON_VERSION >= 0x360 // The Nuitka_AsyncgenObject is the storage associated with a compiled // async generator object instance of which there can be many for each code. struct Nuitka_AsyncgenObject { /* Python object folklore: */ PyObject_VAR_HEAD PyObject *m_name; // TODO: Only to make traceback for non-started throw PyObject *m_module; PyObject *m_qualname; PyObject *m_yieldfrom; // Weak references are supported for asyncgen objects in CPython. PyObject *m_weakrefs; int m_running; // When an asyncgen is awaiting, this flag is set. int m_awaiting; #if PYTHON_VERSION >= 0x380 // When an asyncgen is running, this is set int m_running_async; #endif void *m_code; // The parent frame of the coroutine, if created. struct Nuitka_FrameObject *m_frame; PyCodeObject *m_code_object; // While yielding, this was the frame currently active, restore when // resuming. struct Nuitka_FrameObject *m_resume_frame; // Was it ever used, is it still running, or already finished. Generator_Status m_status; #if PYTHON_VERSION >= 0x370 _PyErr_StackItem m_exc_state; #endif // The label index to resume after yield. int m_yield_return_index; // The finalizer associated through a hook PyObject *m_finalizer; // The hooks were initialized bool m_hooks_init_done; // It is closed, and cannot be closed again. bool m_closed; // A kind of uuid for the generator object, used in comparisons. long m_counter; /* The heap of generator objects at run time. */ void *m_heap_storage; /* Closure variables given, if any, we reference cells here. The last * part is dynamically allocated, the array size differs per asyncgen * and includes the heap storage. */ Py_ssize_t m_closure_given; struct Nuitka_CellObject *m_closure[1]; }; extern PyTypeObject Nuitka_Asyncgen_Type; typedef PyObject *(*asyncgen_code)(struct Nuitka_AsyncgenObject *, PyObject *); extern PyObject *Nuitka_Asyncgen_New(asyncgen_code code, PyObject *module, PyObject *name, PyObject *qualname, PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size); static inline bool Nuitka_Asyncgen_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Asyncgen_Type; } static inline void SAVE_ASYNCGEN_EXCEPTION(struct Nuitka_AsyncgenObject *asyncgen) { /* Before Python3.7: When yielding from an exception handler in Python3, * the exception preserved to the frame is restored, while the current one * is put as there. * * Python3.7: The exception is preserved in the asyncgen object itself * which has a new "m_exc_state" structure just for that. */ PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); #if _DEBUG_EXCEPTIONS PRINT_STRING("SAVE_ASYNCGEN_EXCEPTION: Enter\n"); PRINT_EXCEPTION(saved_exception_type, saved_exception_value, saved_exception_traceback); #endif CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; #else EXC_TYPE(thread_state) = asyncgen->m_exc_state.exc_type; EXC_VALUE(thread_state) = asyncgen->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = asyncgen->m_exc_state.exc_traceback; #endif #if _DEBUG_EXCEPTIONS PRINT_STRING("SAVE_ASYNCGEN_EXCEPTION: Leave\n"); PRINT_EXCEPTION(EXC_TYPE(thread_state), EXC_VALUE(thread_state), EXC_TRACEBACK(thread_state)); #endif CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); #if PYTHON_VERSION < 0x370 thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else asyncgen->m_exc_state.exc_type = saved_exception_type; asyncgen->m_exc_state.exc_value = saved_exception_value; asyncgen->m_exc_state.exc_traceback = saved_exception_traceback; #endif } static inline void RESTORE_ASYNCGEN_EXCEPTION(struct Nuitka_AsyncgenObject *asyncgen) { // When returning from yield, the exception of the frame is preserved, and // the one that enters should be there. PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); #if _DEBUG_EXCEPTIONS PRINT_STRING("RESTORE_ASYNCGEN_EXCEPTION: Enter\n"); PRINT_EXCEPTION(saved_exception_type, saved_exception_value, saved_exception_traceback); #endif CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else EXC_TYPE(thread_state) = asyncgen->m_exc_state.exc_type; EXC_VALUE(thread_state) = asyncgen->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = asyncgen->m_exc_state.exc_traceback; asyncgen->m_exc_state.exc_type = saved_exception_type; asyncgen->m_exc_state.exc_value = saved_exception_value; asyncgen->m_exc_state.exc_traceback = saved_exception_traceback; #endif #if _DEBUG_EXCEPTIONS PRINT_STRING("RESTORE_ASYNCGEN_EXCEPTION: Leave\n"); PRINT_EXCEPTION(EXC_TYPE(thread_state), EXC_VALUE(thread_state), EXC_TRACEBACK(thread_state)); #endif CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); } #endif // For reference count debugging. #if _DEBUG_REFCOUNTS extern int count_active_Nuitka_Asyncgen_Type; extern int count_allocated_Nuitka_Asyncgen_Type; extern int count_released_Nuitka_Asyncgen_Type; extern int count_active_Nuitka_AsyncgenValueWrapper_Type; extern int count_allocated_Nuitka_AsyncgenValueWrapper_Type; extern int count_released_Nuitka_AsyncgenValueWrapper_Type; extern int count_active_Nuitka_AsyncgenAsend_Type; extern int count_allocated_Nuitka_AsyncgenAsend_Type; extern int count_released_Nuitka_AsyncgenAsend_Type; extern int count_active_Nuitka_AsyncgenAthrow_Type; extern int count_allocated_Nuitka_AsyncgenAthrow_Type; extern int count_released_Nuitka_AsyncgenAthrow_Type; #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/constants_blob.h0000600000372100037210000000241514166627112030764 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_CONSTANTS_BLOB_H__ #define __NUITKA_CONSTANTS_BLOB_H__ /** Declaration of the constants binary blob. * * There are multiple ways, the constants binary is accessed, and its * definition depends on how that is done. * * It could be a Windows resource, then it must be a pointer. If it's defined * externally in a C file, or at link time with "ld", it must be an array. This * hides these facts. * */ extern void loadConstantsBlob(PyObject **, char const *name); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_generator.h0000600000372100037210000001772214166627112031623 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_GENERATOR_H__ #define __NUITKA_COMPILED_GENERATOR_H__ #include "Python.h" #include "frameobject.h" #include "methodobject.h" // Compiled generator function type. // Another cornerstone of the integration into CPython. Try to behave as well as // normal generator objects do or even better. // Status of the generator object. #ifdef __cplusplus enum Generator_Status { status_Unused, // Not used so far status_Running, // Running, used but didn't stop yet status_Finished // Stopped, no more values to come }; #else typedef int Generator_Status; static const int status_Unused = 0; static const int status_Running = 1; static const int status_Finished = 2; #endif // We use this even before Python3.10 #if PYTHON_VERSION < 0x3a0 typedef enum { PYGEN_RETURN = 0, PYGEN_ERROR = -1, PYGEN_NEXT = 1, } PySendResult; #endif // The Nuitka_GeneratorObject is the storage associated with a compiled // generator object instance of which there can be many for each code. struct Nuitka_GeneratorObject { /* Python object folklore: */ PyObject_VAR_HEAD PyObject *m_name; // TODO: Only to make traceback for non-started throw PyObject *m_module; #if PYTHON_VERSION >= 0x350 PyObject *m_qualname; #endif #if PYTHON_VERSION >= 0x300 // The value currently yielded from. PyObject *m_yieldfrom; #endif // Weak references are supported for generator objects in CPython. PyObject *m_weakrefs; int m_running; void *m_code; struct Nuitka_FrameObject *m_frame; PyCodeObject *m_code_object; // Was it ever used, is it still running, or already finished. Generator_Status m_status; #if PYTHON_VERSION >= 0x370 _PyErr_StackItem m_exc_state; #endif // The label index to resume after yield. int m_yield_return_index; // Returned value if yielded value is NULL, is // NULL if not a return #if PYTHON_VERSION >= 0x300 PyObject *m_returned; #endif // A kind of uuid for the generator object, used in comparisons. long m_counter; /* The heap of generator objects at run time. */ void *m_heap_storage; /* Closure variables given, if any, we reference cells here. The last * part is dynamically allocated, the array size differs per generator * and includes the heap storage. */ Py_ssize_t m_closure_given; struct Nuitka_CellObject *m_closure[1]; }; extern PyTypeObject Nuitka_Generator_Type; typedef PyObject *(*generator_code)(struct Nuitka_GeneratorObject *, PyObject *); extern PyObject *Nuitka_Generator_New(generator_code code, PyObject *module, PyObject *name, #if PYTHON_VERSION >= 0x350 PyObject *qualname, #endif PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given, Py_ssize_t heap_storage_size); extern PyObject *Nuitka_Generator_NewEmpty(PyObject *module, PyObject *name, #if PYTHON_VERSION >= 0x350 PyObject *qualname, #endif PyCodeObject *code_object, struct Nuitka_CellObject **closure, Py_ssize_t closure_given); extern PyObject *Nuitka_Generator_qiter(struct Nuitka_GeneratorObject *generator, bool *finished); static inline bool Nuitka_Generator_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Generator_Type; } static inline PyObject *Nuitka_Generator_GetName(PyObject *object) { return ((struct Nuitka_GeneratorObject *)object)->m_name; } static inline void SAVE_GENERATOR_EXCEPTION(struct Nuitka_GeneratorObject *generator) { /* Before Python3.7: When yielding from an exception handler in Python3, * the exception preserved to the frame is restored, while the current one * is put as there. * * Python3.7: The exception is preserved in the generator object itself * which has a new "m_exc_state" structure just for that. */ PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; #else EXC_TYPE(thread_state) = generator->m_exc_state.exc_type; EXC_VALUE(thread_state) = generator->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = generator->m_exc_state.exc_traceback; #endif #if _DEBUG_EXCEPTIONS PRINT_STRING("YIELD exit:\n"); PRINT_PUBLISHED_EXCEPTION(); #endif CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); #if PYTHON_VERSION < 0x370 thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else generator->m_exc_state.exc_type = saved_exception_type; generator->m_exc_state.exc_value = saved_exception_value; generator->m_exc_state.exc_traceback = saved_exception_traceback; #endif } static inline void RESTORE_GENERATOR_EXCEPTION(struct Nuitka_GeneratorObject *generator) { // When returning from yield, the exception of the frame is preserved, and // the one that enters should be there. PyThreadState *thread_state = PyThreadState_GET(); PyObject *saved_exception_type = EXC_TYPE(thread_state); PyObject *saved_exception_value = EXC_VALUE(thread_state); PyObject *saved_exception_traceback = EXC_TRACEBACK(thread_state); CHECK_OBJECT_X(saved_exception_type); CHECK_OBJECT_X(saved_exception_value); CHECK_OBJECT_X(saved_exception_traceback); #if PYTHON_VERSION < 0x370 EXC_TYPE(thread_state) = thread_state->frame->f_exc_type; EXC_VALUE(thread_state) = thread_state->frame->f_exc_value; EXC_TRACEBACK(thread_state) = thread_state->frame->f_exc_traceback; thread_state->frame->f_exc_type = saved_exception_type; thread_state->frame->f_exc_value = saved_exception_value; thread_state->frame->f_exc_traceback = saved_exception_traceback; #else EXC_TYPE(thread_state) = generator->m_exc_state.exc_type; EXC_VALUE(thread_state) = generator->m_exc_state.exc_value; EXC_TRACEBACK(thread_state) = generator->m_exc_state.exc_traceback; generator->m_exc_state.exc_type = saved_exception_type; generator->m_exc_state.exc_value = saved_exception_value; generator->m_exc_state.exc_traceback = saved_exception_traceback; CHECK_OBJECT_X(EXC_TYPE(thread_state)); CHECK_OBJECT_X(EXC_VALUE(thread_state)); CHECK_OBJECT_X(EXC_TRACEBACK(thread_state)); #endif } // Functions to preserver and restore from heap area temporary values during // yield/yield from/await exits of generator functions. extern void Nuitka_PreserveHeap(void *dest, ...); extern void Nuitka_RestoreHeap(void *source, ...); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/calling.h0000600000372100037210000000766514166627112027377 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_CALLING_H__ #define __NUITKA_CALLING_H__ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif // Also used in generated helper code. NUITKA_MAY_BE_UNUSED static inline PyObject *Nuitka_CheckFunctionResult(PyObject *result) { if (result == NULL) { if (unlikely(!ERROR_OCCURRED())) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_SystemError, "NULL result without error from call"); } return NULL; } else { // Some buggy C functions do this, and Nuitka inner workings can get // upset from it. if (unlikely(DROP_ERROR_OCCURRED())) { Py_DECREF(result); #if PYTHON_VERSION < 0x3a0 SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_SystemError, "result with error set from call"); #else SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_SystemError, "result with exception set from call"); #endif return NULL; } return result; } } NUITKA_MAY_BE_UNUSED static PyObject *CALL_FUNCTION(PyObject *function_object, PyObject *positional_args, PyObject *named_args) { // Not allowed to enter with an error set. This often catches leaked errors from // elsewhere. assert(!ERROR_OCCURRED()); CHECK_OBJECT(function_object); CHECK_OBJECT(positional_args); assert(named_args == NULL || Py_REFCNT(named_args) > 0); ternaryfunc call_slot = Py_TYPE(function_object)->tp_call; if (unlikely(call_slot == NULL)) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not callable", function_object); return NULL; } if (unlikely(Py_EnterRecursiveCall((char *)" while calling a Python object"))) { return NULL; } PyObject *result = (*call_slot)(function_object, positional_args, named_args); Py_LeaveRecursiveCall(); return Nuitka_CheckFunctionResult(result); } // Function call variant with no arguments provided at all. extern PyObject *CALL_FUNCTION_NO_ARGS(PyObject *called); // Function call variants with positional arguments tuple. NUITKA_MAY_BE_UNUSED static PyObject *CALL_FUNCTION_WITH_POSARGS(PyObject *function_object, PyObject *positional_args) { return CALL_FUNCTION(function_object, positional_args, NULL); } // Method call variants with positional arguments tuple. extern PyObject *CALL_METHOD_WITH_POSARGS(PyObject *source, PyObject *attr_name, PyObject *positional_args); // TODO: Specialize in template too. NUITKA_MAY_BE_UNUSED static PyObject *CALL_FUNCTION_WITH_KEYARGS(PyObject *function_object, PyObject *named_args) { return CALL_FUNCTION(function_object, const_tuple_empty, named_args); } #include "nuitka/helper/calling2.h" // For exception test formatting and call code mostly. extern char const *GET_CALLABLE_NAME(PyObject *object); extern char const *GET_CALLABLE_DESC(PyObject *object); extern char const *GET_CLASS_NAME(PyObject *klass); extern char const *GET_INSTANCE_CLASS_NAME(PyObject *instance); // For abstract class instantiation error message, during call. extern void formatCannotInstantiateAbstractClass(PyTypeObject *type); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_method.h0000600000372100037210000000345614166627112031114 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_METHOD_H__ #define __NUITKA_COMPILED_METHOD_H__ // Compiled function and compile generator types may be referenced. #include "compiled_function.h" #include "compiled_generator.h" // The backbone of the integration into CPython. Try to behave as well as normal // method objects, or even better. // The Nuitka_MethodObject is the storage associated with a compiled method // instance of which there can be many for each code. struct Nuitka_MethodObject { /* Python object folklore: */ PyObject_HEAD struct Nuitka_FunctionObject *m_function; PyObject *m_weakrefs; PyObject *m_object; PyObject *m_class; #if PYTHON_VERSION >= 0x380 vectorcallfunc m_vectorcall; #endif }; extern PyTypeObject Nuitka_Method_Type; // Make a method out of a function. extern PyObject *Nuitka_Method_New(struct Nuitka_FunctionObject *function, PyObject *object, PyObject *klass); static inline bool Nuitka_Method_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Method_Type; } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/builtins.h0000600000372100037210000000636514166627112027613 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_BUILTINS_H__ #define __NUITKA_BUILTINS_H__ extern PyModuleObject *builtin_module; extern PyDictObject *dict_builtin; #include "nuitka/calling.h" NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_BUILTIN(PyObject *name) { CHECK_OBJECT(dict_builtin); CHECK_OBJECT(name); assert(Nuitka_String_CheckExact(name)); PyObject *result = GET_STRING_DICT_VALUE(dict_builtin, (Nuitka_StringObject *)name); // This is assumed to not fail, abort if it does. if (unlikely(result == NULL)) { PyErr_PrintEx(0); Py_Exit(1); } CHECK_OBJECT(result); return result; } NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_BUILTIN_STR(char const *name) { CHECK_OBJECT(dict_builtin); PyObject *result = PyDict_GetItemString((PyObject *)dict_builtin, name); // This is assumed to not fail, abort if it does. if (unlikely(result == NULL)) { PyErr_PrintEx(0); Py_Exit(1); } CHECK_OBJECT(result); return result; } extern void _initBuiltinModule(); #define NUITKA_DECLARE_BUILTIN(name) extern PyObject *_python_original_builtin_value_##name; #define NUITKA_DEFINE_BUILTIN(name) PyObject *_python_original_builtin_value_##name = NULL; #define NUITKA_ASSIGN_BUILTIN(name) \ if (_python_original_builtin_value_##name == NULL) \ _python_original_builtin_value_##name = LOOKUP_BUILTIN_STR(#name); #define NUITKA_UPDATE_BUILTIN(name, value) _python_original_builtin_value_##name = value; #define NUITKA_ACCESS_BUILTIN(name) (_python_original_builtin_value_##name) #ifdef _NUITKA_EXE // Original builtin values, currently only used for assertions. NUITKA_DECLARE_BUILTIN(type); NUITKA_DECLARE_BUILTIN(len); NUITKA_DECLARE_BUILTIN(range); NUITKA_DECLARE_BUILTIN(repr); NUITKA_DECLARE_BUILTIN(int); NUITKA_DECLARE_BUILTIN(iter); #if PYTHON_VERSION < 0x300 NUITKA_DECLARE_BUILTIN(long); #endif extern void _initBuiltinOriginalValues(); #endif // Avoid the casts needed for older Python, as it's easily forgotten and potentially // have our own better implementation later. NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_SysGetObject(char const *name) { return PySys_GetObject((char *)name); } NUITKA_MAY_BE_UNUSED static void Nuitka_SysSetObject(char const *name, PyObject *value) { // TODO: Check error in debug mode at least. PySys_SetObject((char *)name, value); } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/safe_string_ops.h0000600000372100037210000000353114166627112031137 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_SAFE_STRING_OPS_H__ #define __NUITKA_SAFE_STRING_OPS_H__ /* Safe to use function to copy a string, will abort program for overflow. */ extern void copyStringSafe(char *buffer, char const *source, size_t buffer_size); extern void copyStringSafeN(char *buffer, char const *source, size_t n, size_t buffer_size); /* Safe to use function to append a string, will abort program for overflow. */ extern void appendCharSafe(char *buffer, char c, size_t buffer_size); extern void appendStringSafe(char *buffer, char const *source, size_t buffer_size); /* Safe to use functions to append a wide char string, will abort program for overflow. */ extern void appendCharSafeW(wchar_t *target, char c, size_t buffer_size); extern void appendStringSafeW(wchar_t *target, char const *source, size_t buffer_size); extern void appendWStringSafeW(wchar_t *target, wchar_t const *source, size_t buffer_size); /* Expand symbolic paths, containing %TEMP%, %PID% without overflowing. */ extern bool expandTemplatePathW(wchar_t *target, wchar_t const *source, size_t buffer_size); #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/exceptions.h0000600000372100037210000006315714166627112030145 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_EXCEPTIONS_H__ #define __NUITKA_EXCEPTIONS_H__ // Exception helpers for generated code and compiled code helpers. // Did an error occur. NUITKA_MAY_BE_UNUSED static inline bool ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); return tstate->curexc_type != NULL; } // Get the error type occurred. NUITKA_MAY_BE_UNUSED static inline PyObject *GET_ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); return tstate->curexc_type; } // Clear error, which likely set. NUITKA_MAY_BE_UNUSED static inline void CLEAR_ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); PyObject *old_type = tstate->curexc_type; PyObject *old_value = tstate->curexc_value; PyObject *old_tb = tstate->curexc_traceback; tstate->curexc_type = NULL; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; Py_XDECREF(old_type); Py_XDECREF(old_value); Py_XDECREF(old_tb); } // Clear error, which is not likely set. This is about bugs from CPython, // use CLEAR_ERROR_OCCURRED is not sure. NUITKA_MAY_BE_UNUSED static inline bool DROP_ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); if (unlikely(tstate->curexc_type != NULL)) { PyObject *old_type = tstate->curexc_type; PyObject *old_value = tstate->curexc_value; PyObject *old_tb = tstate->curexc_traceback; tstate->curexc_type = NULL; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; Py_DECREF(old_type); Py_XDECREF(old_value); Py_XDECREF(old_tb); return true; } return false; } // Fetch the current error into object variables. NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_traceback) { PyThreadState *tstate = PyThreadState_GET(); *exception_type = tstate->curexc_type; *exception_value = tstate->curexc_value; *exception_traceback = (PyTracebackObject *)tstate->curexc_traceback; #if _DEBUG_EXCEPTIONS PRINT_STRING("FETCH_ERROR_OCCURRED:\n"); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); #endif tstate->curexc_type = NULL; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; } // Fetch the current error into object variables. NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED_UNTRACED(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_traceback) { PyThreadState *tstate = PyThreadState_GET(); *exception_type = tstate->curexc_type; *exception_value = tstate->curexc_value; *exception_traceback = (PyTracebackObject *)tstate->curexc_traceback; tstate->curexc_type = NULL; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; } NUITKA_MAY_BE_UNUSED static void RESTORE_ERROR_OCCURRED(PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_traceback) { PyThreadState *tstate = PyThreadState_GET(); PyObject *old_exception_type = tstate->curexc_type; PyObject *old_exception_value = tstate->curexc_value; PyObject *old_exception_traceback = tstate->curexc_traceback; tstate->curexc_type = exception_type; tstate->curexc_value = exception_value; tstate->curexc_traceback = (PyObject *)exception_traceback; #if _DEBUG_EXCEPTIONS PRINT_STRING("RESTORE_ERROR_OCCURRED:\n"); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); #endif Py_XDECREF(old_exception_type); Py_XDECREF(old_exception_value); Py_XDECREF(old_exception_traceback); } NUITKA_MAY_BE_UNUSED static void RESTORE_ERROR_OCCURRED_UNTRACED(PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_traceback) { PyThreadState *tstate = PyThreadState_GET(); PyObject *old_exception_type = tstate->curexc_type; PyObject *old_exception_value = tstate->curexc_value; PyObject *old_exception_traceback = tstate->curexc_traceback; tstate->curexc_type = exception_type; tstate->curexc_value = exception_value; tstate->curexc_traceback = (PyObject *)exception_traceback; Py_XDECREF(old_exception_type); Py_XDECREF(old_exception_value); Py_XDECREF(old_exception_traceback); } struct Nuitka_FrameObject; extern PyTracebackObject *MAKE_TRACEBACK(struct Nuitka_FrameObject *frame, int lineno); // Add a frame to an existing exception trace-back. NUITKA_MAY_BE_UNUSED static PyTracebackObject *ADD_TRACEBACK(PyTracebackObject *exception_tb, struct Nuitka_FrameObject *frame, int lineno) { CHECK_OBJECT(exception_tb); CHECK_OBJECT(frame); PyTracebackObject *traceback_new = MAKE_TRACEBACK(frame, lineno); traceback_new->tb_next = exception_tb; return traceback_new; } // Need some wrapper functions for accessing exception type, value, and traceback // due to changes in Python 3.7 #if PYTHON_VERSION < 0x370 #define EXC_TYPE(x) (x->exc_type) #define EXC_VALUE(x) (x->exc_value) #define EXC_TRACEBACK(x) (x->exc_traceback) #define EXC_TYPE_F(x) (x->m_frame->m_frame.f_exc_type) #define EXC_VALUE_F(x) (x->m_frame->m_frame.f_exc_value) #define EXC_TRACEBACK_F(x) (x->m_frame->m_frame.f_exc_traceback) #else #define EXC_TYPE(x) (x->exc_state.exc_type) #define EXC_VALUE(x) (x->exc_state.exc_value) #define EXC_TRACEBACK(x) (x->exc_state.exc_traceback) #define EXC_TYPE_F(x) (x->m_exc_state.exc_type) #define EXC_VALUE_F(x) (x->m_exc_state.exc_value) #define EXC_TRACEBACK_F(x) (x->m_exc_state.exc_traceback) #endif // Helper that gets the current thread exception, for use in exception handlers NUITKA_MAY_BE_UNUSED inline static void GET_CURRENT_EXCEPTION(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { PyThreadState *thread_state = PyThreadState_GET(); *exception_type = EXC_TYPE(thread_state); Py_XINCREF(*exception_type); *exception_value = EXC_VALUE(thread_state); Py_XINCREF(*exception_value); *exception_tb = (PyTracebackObject *)EXC_TRACEBACK(thread_state); Py_XINCREF(*exception_tb); }; #if PYTHON_VERSION < 0x300 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_SYS_EXC_VARS) #define _NUITKA_MAINTAIN_SYS_EXC_VARS 1 #endif // Helper that sets the current thread exception, releasing the current one, for // use in this file only. NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION(PyObject *exception_type, PyObject *exception_value, PyTracebackObject *exception_tb) { CHECK_OBJECT_X(exception_type); CHECK_OBJECT_X(exception_value); CHECK_OBJECT_X(exception_tb); PyThreadState *thread_state = PyThreadState_GET(); PyObject *old_type = EXC_TYPE(thread_state); PyObject *old_value = EXC_VALUE(thread_state); PyObject *old_tb = EXC_TRACEBACK(thread_state); CHECK_OBJECT_X(old_type); CHECK_OBJECT_X(old_value); CHECK_OBJECT_X(old_tb); EXC_TYPE(thread_state) = exception_type; EXC_VALUE(thread_state) = exception_value; EXC_TRACEBACK(thread_state) = (PyObject *)exception_tb; #if _DEBUG_EXCEPTIONS PRINT_STRING("SET_CURRENT_EXCEPTION:\n"); PRINT_EXCEPTION(exception_type, exception_value, exception_tb); #endif Py_XDECREF(old_type); Py_XDECREF(old_value); Py_XDECREF(old_tb); #if _NUITKA_MAINTAIN_SYS_EXC_VARS // Set sys attributes in the fastest possible way. PyObject *sys_dict = thread_state->interp->sysdict; CHECK_OBJECT(sys_dict); PyDict_SetItem(sys_dict, const_str_plain_exc_type, exception_type ? exception_type : Py_None); PyDict_SetItem(sys_dict, const_str_plain_exc_value, exception_value ? exception_value : Py_None); PyDict_SetItem(sys_dict, const_str_plain_exc_traceback, exception_tb ? (PyObject *)exception_tb : Py_None); if (exception_type) assert(Py_REFCNT(exception_type) >= 2); if (exception_value) assert(Py_REFCNT(exception_value) >= 2); if (exception_tb) assert(Py_REFCNT(exception_tb) >= 2); #endif } // Helper that sets the current thread exception, and has no reference passed. NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0(PyObject *exception_type) { CHECK_OBJECT(exception_type); PyThreadState *tstate = PyThreadState_GET(); PyObject *old_exception_type = tstate->curexc_type; PyObject *old_exception_value = tstate->curexc_value; PyObject *old_exception_traceback = tstate->curexc_traceback; tstate->curexc_type = exception_type; Py_INCREF(exception_type); tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; #if _DEBUG_EXCEPTIONS PRINT_STRING("SET_CURRENT_EXCEPTION_TYPE0:\n"); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); #endif Py_XDECREF(old_exception_type); Py_XDECREF(old_exception_value); Py_XDECREF(old_exception_traceback); } // Same as PyErr_SetObject CPython API, use this instead. NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyObject *exception_type, PyObject *exception_value) { PyThreadState *tstate = PyThreadState_GET(); PyObject *old_exception_type = tstate->curexc_type; PyObject *old_exception_value = tstate->curexc_value; PyObject *old_exception_traceback = tstate->curexc_traceback; tstate->curexc_type = exception_type; Py_INCREF(exception_type); tstate->curexc_value = exception_value; Py_INCREF(exception_value); tstate->curexc_traceback = NULL; #if _DEBUG_EXCEPTIONS PRINT_STRING("SET_CURRENT_EXCEPTION_TYPE0_VALUE0:\n"); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); #endif Py_XDECREF(old_exception_type); Py_XDECREF(old_exception_value); Py_XDECREF(old_exception_traceback); } NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyObject *exception_type, PyObject *exception_value) { PyThreadState *tstate = PyThreadState_GET(); PyObject *old_exception_type = tstate->curexc_type; PyObject *old_exception_value = tstate->curexc_value; PyObject *old_exception_traceback = tstate->curexc_traceback; tstate->curexc_type = exception_type; Py_INCREF(exception_type); tstate->curexc_value = exception_value; tstate->curexc_traceback = NULL; #if _DEBUG_EXCEPTIONS PRINT_STRING("SET_CURRENT_EXCEPTION_TYPE0_VALUE1:\n"); PRINT_EXCEPTION(tstate->curexc_type, tstate->curexc_value, tstate->curexc_traceback); #endif Py_XDECREF(old_exception_type); Py_XDECREF(old_exception_value); Py_XDECREF(old_exception_traceback); } // Helper that sets the current thread exception, and has no reference passed. // Same as CPython API PyErr_SetString NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0_STR(PyObject *exception_type, char const *value) { PyObject *exception_value = Nuitka_String_FromString(value); SET_CURRENT_EXCEPTION_TYPE0_VALUE1(exception_type, exception_value); } // Helper that sets the current thread exception with format of one or two arg, and has no reference passed. extern void SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyObject *exception_type, char const *format, char const *value); extern void SET_CURRENT_EXCEPTION_TYPE0_FORMAT2(PyObject *exception_type, char const *format, char const *value1, char const *value2); extern void SET_CURRENT_EXCEPTION_TYPE0_FORMAT3(PyObject *exception_type, char const *format, char const *value1, char const *value2, char const *value3); extern void SET_CURRENT_EXCEPTION_TYPE_COMPLAINT(char const *format, PyObject *mistyped); extern void SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE(char const *format, PyObject *mistyped); #if PYTHON_VERSION < 0x300 // Preserve the current exception as the frame to restore. NUITKA_MAY_BE_UNUSED static inline void PRESERVE_FRAME_EXCEPTION(struct Nuitka_FrameObject *frame_object) { PyFrameObject *frame = (PyFrameObject *)frame_object; // Setting exception for frame if not already done. if (frame->f_exc_type == NULL) { PyThreadState *thread_state = PyThreadState_GET(); if (thread_state->exc_type != NULL && thread_state->exc_type != Py_None) { #if _DEBUG_EXCEPTIONS PRINT_STRING("PRESERVE_FRAME_EXCEPTION: preserve thread exception\n"); #endif frame->f_exc_type = thread_state->exc_type; Py_INCREF(frame->f_exc_type); frame->f_exc_value = thread_state->exc_value; Py_XINCREF(frame->f_exc_value); frame->f_exc_traceback = thread_state->exc_traceback; Py_XINCREF(frame->f_exc_traceback); } else { #if _DEBUG_EXCEPTIONS PRINT_STRING("PRESERVE_FRAME_EXCEPTION: no exception to preserve\n"); #endif frame->f_exc_type = Py_None; Py_INCREF(frame->f_exc_type); frame->f_exc_value = NULL; frame->f_exc_traceback = NULL; } } #if _DEBUG_EXCEPTIONS else { PRINT_STRING("PRESERVE_FRAME_EXCEPTION: already preserving\n"); } PRINT_ITEM((PyObject *)frame_object); PRINT_NEW_LINE(); PRINT_EXCEPTION(frame->f_exc_type, frame->f_exc_value, frame->f_exc_traceback); #endif } // Restore a previously preserved exception to the frame. NUITKA_MAY_BE_UNUSED static inline void RESTORE_FRAME_EXCEPTION(struct Nuitka_FrameObject *frame_object) { PyFrameObject *frame = (PyFrameObject *)frame_object; if (frame->f_exc_type) { #if _DEBUG_EXCEPTIONS PRINT_STRING("RESTORE_FRAME_EXCEPTION: restoring preserved\n"); PRINT_ITEM((PyObject *)frame_object); PRINT_NEW_LINE(); #endif SET_CURRENT_EXCEPTION(frame->f_exc_type, frame->f_exc_value, (PyTracebackObject *)frame->f_exc_traceback); frame->f_exc_type = NULL; frame->f_exc_value = NULL; frame->f_exc_traceback = NULL; } #if _DEBUG_EXCEPTIONS else { PRINT_STRING("RESTORE_FRAME_EXCEPTION: nothing to restore\n"); PRINT_ITEM((PyObject *)frame_object); PRINT_NEW_LINE(); } #endif } #endif // Publish an exception, erasing the values of the variables. NUITKA_MAY_BE_UNUSED static inline void PUBLISH_EXCEPTION(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { #if _DEBUG_EXCEPTIONS PRINT_STRING("PUBLISH_EXCEPTION:\n"); #endif SET_CURRENT_EXCEPTION(*exception_type, *exception_value, *exception_tb); *exception_type = NULL; *exception_value = NULL; *exception_tb = NULL; } // Normalize an exception. NUITKA_MAY_BE_UNUSED static inline void NORMALIZE_EXCEPTION(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb) { #if _DEBUG_EXCEPTIONS PRINT_STRING("NORMALIZE_EXCEPTION: Enter\n"); PRINT_EXCEPTION(*exception_type, *exception_value, *exception_tb); #endif CHECK_OBJECT_X(*exception_type); CHECK_OBJECT_X(*exception_value); if (exception_tb) { CHECK_OBJECT_X(*exception_tb); } // TODO: Often we already know this to be true. if (*exception_type != Py_None && *exception_type != NULL) { // TODO: Inline for performance. PyErr_NormalizeException(exception_type, exception_value, (PyObject **)exception_tb); } #if _DEBUG_EXCEPTIONS PRINT_STRING("NORMALIZE_EXCEPTION: Leave\n"); PRINT_EXCEPTION(*exception_type, *exception_value, exception_tb ? *exception_tb : NULL); #endif } NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR(PyObject *exception_value) { CHECK_OBJECT(exception_value); // We need to check the class. if (PyExceptionInstance_Check(exception_value)) { exception_value = PyExceptionInstance_Class(exception_value); } // Lets be optimistic. If it matches, we would be wasting our time. if (exception_value == PyExc_GeneratorExit || exception_value == PyExc_StopIteration) { return true; } if (PyExceptionClass_Check(exception_value)) { // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); int res = PyObject_IsSubclass(exception_value, PyExc_GeneratorExit); // This function must not fail, so print the error here */ if (unlikely(res == -1)) { PyErr_WriteUnraisable(exception_value); } if (res == 1) return true; res = PyObject_IsSubclass(exception_value, PyExc_StopIteration); // This function must not fail, so print the error here */ if (unlikely(res == -1)) { PyErr_WriteUnraisable(exception_value); } RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); return res == 1; } return false; } NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_BOOL_SINGLE(PyObject *exception_value, PyObject *exception_checked) { CHECK_OBJECT(exception_value); CHECK_OBJECT(exception_checked); // We need to check the class. if (PyExceptionInstance_Check(exception_value)) { exception_value = PyExceptionInstance_Class(exception_value); } // Lets be optimistic. If it matches, we would be wasting our time. if (exception_value == exception_checked) { return true; } if (PyExceptionClass_Check(exception_value)) { // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED(&save_exception_type, &save_exception_value, &save_exception_tb); int res = PyObject_IsSubclass(exception_value, exception_checked); // This function must not fail, so print the error here */ if (unlikely(res == -1)) { PyErr_WriteUnraisable(exception_value); } RESTORE_ERROR_OCCURRED(save_exception_type, save_exception_value, save_exception_tb); return res == 1; } return false; } // This is for the actual comparison operation that is being done in the // node tree, no other code should use it. TODO: Then it's probably not // properly located here, and it could still in-line the code of // "PyErr_GivenExceptionMatches" to save on Python3 doing two tuple checks // and iterations. NUITKA_MAY_BE_UNUSED static inline int EXCEPTION_MATCH_BOOL(PyObject *exception_value, PyObject *exception_checked) { CHECK_OBJECT(exception_value); CHECK_OBJECT(exception_checked); #if PYTHON_VERSION >= 0x300 /* Note: Exact matching tuples seems to needed, despite using GET_ITEM later on, this probably cannot be overloaded that deep. */ if (PyTuple_Check(exception_checked)) { Py_ssize_t length = PyTuple_GET_SIZE(exception_checked); for (Py_ssize_t i = 0; i < length; i += 1) { PyObject *element = PyTuple_GET_ITEM(exception_checked, i); if (unlikely(!PyExceptionClass_Check(element))) { SET_CURRENT_EXCEPTION_TYPE0_STR( PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed"); return -1; } } } else if (unlikely(!PyExceptionClass_Check(exception_checked))) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed"); return -1; } #endif return PyErr_GivenExceptionMatches(exception_value, exception_checked); } #if PYTHON_VERSION >= 0x300 // Attach the exception context if necessary. NUITKA_MAY_BE_UNUSED static inline void ADD_EXCEPTION_CONTEXT(PyObject **exception_type, PyObject **exception_value) { PyThreadState *tstate = PyThreadState_GET(); PyObject *context = EXC_VALUE(tstate); if (context != NULL) { NORMALIZE_EXCEPTION(exception_type, exception_value, NULL); Py_INCREF(context); PyException_SetContext(*exception_value, context); } } #endif /* Special helper that checks for StopIteration and if so clears it, only indicating if it was set in the return value. Equivalent to if(PyErr_ExceptionMatches(PyExc_StopIteration) PyErr_Clear(); If error is raised by built-in function next() and an iterator’s __next__() method to signal that there are no further items produced by the iterator then it resets the TSTATE to NULL and returns True else return False */ NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); if (tstate->curexc_type == NULL) { return true; } else if (EXCEPTION_MATCH_BOOL_SINGLE(tstate->curexc_type, PyExc_StopIteration)) { // Clear the exception first, we know it doesn't have side effects. Py_DECREF(tstate->curexc_type); tstate->curexc_type = NULL; PyObject *old_value = tstate->curexc_value; PyObject *old_tb = tstate->curexc_traceback; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; Py_XDECREF(old_value); Py_XDECREF(old_tb); return true; } else { return false; } } /* Special helper that checks for KeyError and if so clears it, only indicating if it was set in the return value. Equivalent to if(PyErr_ExceptionMatches(PyExc_KeyError) PyErr_Clear(); */ NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_KEY_ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); if (tstate->curexc_type == NULL) { return true; } else if (EXCEPTION_MATCH_BOOL_SINGLE(tstate->curexc_type, PyExc_KeyError)) { // Clear the exception first, we know it doesn't have side effects. Py_DECREF(tstate->curexc_type); tstate->curexc_type = NULL; PyObject *old_value = tstate->curexc_value; PyObject *old_tb = tstate->curexc_traceback; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; Py_XDECREF(old_value); Py_XDECREF(old_tb); return true; } else { return false; } } NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED(void) { PyThreadState *tstate = PyThreadState_GET(); if (tstate->curexc_type == NULL) { return true; } else if (EXCEPTION_MATCH_BOOL_SINGLE(tstate->curexc_type, PyExc_AttributeError)) { // Clear the exception first, we know it doesn't have side effects. Py_DECREF(tstate->curexc_type); tstate->curexc_type = NULL; PyObject *old_value = tstate->curexc_value; PyObject *old_tb = tstate->curexc_traceback; tstate->curexc_value = NULL; tstate->curexc_traceback = NULL; Py_XDECREF(old_value); Py_XDECREF(old_tb); return true; } else { return false; } } // Format a NameError exception for a variable name. extern void FORMAT_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name); #if PYTHON_VERSION < 0x340 // Same as FORMAT_NAME_ERROR with different wording, sometimes used for older Python version. extern void FORMAT_GLOBAL_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name); #endif // Format a UnboundLocalError exception for a variable name. extern void FORMAT_UNBOUND_LOCAL_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name); extern void FORMAT_UNBOUND_CLOSURE_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name); // Similar to PyException_SetTraceback, only done for Python3. #if PYTHON_VERSION < 0x300 #define ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(exception_value, exception_tb) ; #else NUITKA_MAY_BE_UNUSED static inline void ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(PyObject *exception_value, PyTracebackObject *exception_tb) { CHECK_OBJECT(exception_value); CHECK_OBJECT(exception_tb); if (exception_tb == (PyTracebackObject *)Py_None || exception_tb == NULL) { return; } assert(PyExceptionInstance_Check(exception_value)); assert(PyTraceBack_Check(exception_tb)); PyBaseExceptionObject *e = (PyBaseExceptionObject *)exception_value; PyObject *old = e->traceback; Py_INCREF(exception_tb); e->traceback = (PyObject *)exception_tb; Py_XDECREF(old); } #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/0000700000372100037210000000000014167275622027062 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/attributes.h0000600000372100037210000000457014166627112031423 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_ATTRIBUTES_H__ #define __NUITKA_HELPER_ATTRIBUTES_H__ // Attribute lookup except special slots below. extern PyObject *LOOKUP_ATTRIBUTE(PyObject *source, PyObject *attr_name); // Attribute lookup of attribute slot "__dict__". extern PyObject *LOOKUP_ATTRIBUTE_DICT_SLOT(PyObject *source); // Attribute lookup of attribute slot "__class__". extern PyObject *LOOKUP_ATTRIBUTE_CLASS_SLOT(PyObject *source); // For built-in "hasattr" functionality. extern int BUILTIN_HASATTR_BOOL(PyObject *source, PyObject *attr_name); // Check for an attribute, cannot raise an exception. extern bool HAS_ATTR_BOOL(PyObject *source, PyObject *attr_name); // Set an attribute except for attribute slots below. extern bool SET_ATTRIBUTE(PyObject *target, PyObject *attr_name, PyObject *value); // Set the "__dict__" special attribute slot. extern bool SET_ATTRIBUTE_DICT_SLOT(PyObject *target, PyObject *value); // Set the "__class__" special attribute slot. extern bool SET_ATTRIBUTE_CLASS_SLOT(PyObject *target, PyObject *value); // Special attribute lookups, e.g. "__enter__". extern PyObject *LOOKUP_SPECIAL(PyObject *source, PyObject *attr_name); // Find an attribute in a class, Python2 only. #if PYTHON_VERSION < 0x300 extern PyObject *FIND_ATTRIBUTE_IN_CLASS(PyClassObject *klass, PyObject *attr_name); #endif extern PyObject *LOOKUP_MODULE_VALUE(PyDictObject *module_dict, PyObject *var_name); extern PyObject *GET_MODULE_VARIABLE_VALUE_FALLBACK(PyObject *variable_name); #if PYTHON_VERSION < 0x340 extern PyObject *GET_MODULE_VARIABLE_VALUE_FALLBACK_IN_FUNCTION(PyObject *variable_name); #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/ints.h0000600000372100037210000000452714166627112030214 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_INTS_H__ #define __NUITKA_HELPER_INTS_H__ typedef enum { NUITKA_INT_UNASSIGNED = 0, NUITKA_INT_OBJECT_VALID = 1, NUITKA_INT_VALUE_VALID = 2, NUITKA_INT_BOTH_VALID = 3 } nuitka_int_validity; typedef struct { nuitka_int_validity validity; PyObject *int_object; long int_value; } nuitka_int; typedef enum { NUITKA_LONG_UNASSIGNED = 0, NUITKA_LONG_OBJECT_VALID = 1, NUITKA_LONG_VALUE_VALID = 2, NUITKA_LONG_BOTH_VALID = 3 } nuitka_long_validity; typedef struct { nuitka_long_validity validity; PyObject *long_object; long long_value; } nuitka_long; #if PYTHON_VERSION < 0x300 typedef enum { NUITKA_ILONG_UNASSIGNED = 0, NUITKA_ILONG_OBJECT_VALID = 1, NUITKA_ILONG_VALUE_VALID = 2, NUITKA_ILONG_BOTH_VALID = 3 } nuitka_ilong_validity; typedef struct { nuitka_ilong_validity validity; PyObject *ilong_object; long ilong_value; } nuitka_ilong; NUITKA_MAY_BE_UNUSED static void ENFORCE_ILONG_OBJECT_VALUE(nuitka_ilong *value) { assert(value->validity != NUITKA_ILONG_UNASSIGNED); if ((value->validity & NUITKA_ILONG_OBJECT_VALID) == 0) { value->ilong_object = PyLong_FromLong(value->ilong_value); value->validity = NUITKA_ILONG_BOTH_VALID; } } #endif #define NUITKA_STATIC_SMALLINT_VALUE_MIN -5 #define NUITKA_STATIC_SMALLINT_VALUE_MAX 257 #define NUITKA_TO_SMALL_VALUE_OFFSET(value) (value - NUITKA_STATIC_SMALLINT_VALUE_MIN) extern PyObject *Nuitka_Long_SmallValues[NUITKA_STATIC_SMALLINT_VALUE_MAX - NUITKA_STATIC_SMALLINT_VALUE_MIN + 1]; #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_olddiv.h0000600000372100037210000002071314166627112034322 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "/" (OLDDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_OLDDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_add.h0000600000372100037210000002013114166627112033712 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "+" (ADD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_ADD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_ADD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_ADD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_ADD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_ADD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_ADD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_ADD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_ADD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_ADD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_ADD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_ADD_LIST_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_ADD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_ADD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_ADD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_ADD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_ADD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_ADD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_ADD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_ADD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_ADD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_ADD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_ADD_LIST_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_lshift.h0000600000372100037210000001177314166627112034340 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<<" (LSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_LSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/slices.h0000600000372100037210000002003314166627112030507 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_SLICES_H__ #define __NUITKA_HELPER_SLICES_H__ // Note: Cannot these cannot fail, PySlice_New does not return errors. NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICEOBJ3(PyObject *start, PyObject *stop, PyObject *step) { CHECK_OBJECT(start); CHECK_OBJECT(stop); CHECK_OBJECT(step); return PySlice_New(start, stop, step); } NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICEOBJ2(PyObject *start, PyObject *stop) { CHECK_OBJECT(start); CHECK_OBJECT(stop); return PySlice_New(start, stop, Py_None); } NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICEOBJ1(PyObject *stop) { CHECK_OBJECT(stop); return PySlice_New(Py_None, stop, Py_None); } #if PYTHON_VERSION < 0x300 // Note: It appears that Python3 has no index slicing operations anymore, but // uses slice objects all the time. That's fine and make sure we adhere to it by // guarding the presence of the helpers. static inline bool IS_INDEXABLE(PyObject *value) { return value == Py_None || #if PYTHON_VERSION < 0x300 PyInt_Check(value) || #endif PyLong_Check(value) || PyIndex_Check(value); } static Py_ssize_t CONVERT_TO_INDEX(PyObject *value) { CHECK_OBJECT(value); if (PyInt_Check(value)) { return PyInt_AS_LONG(value); } else if (PyIndex_Check(value)) { return PyNumber_AsSsize_t(value, NULL); } else { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_TypeError, "slice indices must be integers or None or have an __index__ method"); return -1; } } NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_SLICE(PyObject *source, PyObject *lower, PyObject *upper) { CHECK_OBJECT(source); CHECK_OBJECT(lower); CHECK_OBJECT(upper); PySequenceMethods *tp_as_sequence = Py_TYPE(source)->tp_as_sequence; if (tp_as_sequence && tp_as_sequence->sq_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) { Py_ssize_t ilow = 0; if (lower != Py_None) { ilow = CONVERT_TO_INDEX(lower); if (ilow == -1 && ERROR_OCCURRED()) { return NULL; } } Py_ssize_t ihigh = PY_SSIZE_T_MAX; if (upper != Py_None) { ihigh = CONVERT_TO_INDEX(upper); if (ihigh == -1 && ERROR_OCCURRED()) { return NULL; } } PyObject *result = PySequence_GetSlice(source, ilow, ihigh); if (unlikely(result == NULL)) { return NULL; } return result; } else { PyObject *slice = PySlice_New(lower, upper, NULL); if (unlikely(slice == NULL)) { return NULL; } PyObject *result = PyObject_GetItem(source, slice); Py_DECREF(slice); if (unlikely(result == NULL)) { return NULL; } return result; } } NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_INDEX_SLICE(PyObject *source, Py_ssize_t lower, Py_ssize_t upper) { CHECK_OBJECT(source); PyObject *result = PySequence_GetSlice(source, lower, upper); if (unlikely(result == NULL)) { return NULL; } return result; } NUITKA_MAY_BE_UNUSED static bool SET_SLICE(PyObject *target, PyObject *lower, PyObject *upper, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(lower); CHECK_OBJECT(upper); CHECK_OBJECT(value); PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence; if (tp_as_sequence && tp_as_sequence->sq_ass_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) { Py_ssize_t lower_int = 0; if (lower != Py_None) { lower_int = CONVERT_TO_INDEX(lower); if (lower_int == -1 && ERROR_OCCURRED()) { return false; } } Py_ssize_t upper_int = PY_SSIZE_T_MAX; if (upper != Py_None) { upper_int = CONVERT_TO_INDEX(upper); if (upper_int == -1 && ERROR_OCCURRED()) { return false; } } int status = PySequence_SetSlice(target, lower_int, upper_int, value); if (unlikely(status == -1)) { return false; } } else { PyObject *slice = PySlice_New(lower, upper, NULL); if (unlikely(slice == NULL)) { return false; } int status = PyObject_SetItem(target, slice, value); Py_DECREF(slice); if (unlikely(status == -1)) { return false; } } return true; } NUITKA_MAY_BE_UNUSED static bool SET_INDEX_SLICE(PyObject *target, Py_ssize_t lower, Py_ssize_t upper, PyObject *value) { CHECK_OBJECT(target); CHECK_OBJECT(value); PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence; if (tp_as_sequence && tp_as_sequence->sq_ass_slice) { int status = PySequence_SetSlice(target, lower, upper, value); if (unlikely(status == -1)) { return false; } } else { PyObject *slice = _PySlice_FromIndices(lower, upper); if (unlikely(slice == NULL)) { return false; } int status = PyObject_SetItem(target, slice, value); Py_DECREF(slice); if (unlikely(status == -1)) { return false; } } return true; } NUITKA_MAY_BE_UNUSED static bool DEL_SLICE(PyObject *target, PyObject *lower, PyObject *upper) { CHECK_OBJECT(target); CHECK_OBJECT(lower); CHECK_OBJECT(upper); PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence; if (tp_as_sequence && tp_as_sequence->sq_ass_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) { Py_ssize_t lower_int = 0; if (lower != Py_None) { lower_int = CONVERT_TO_INDEX(lower); if (lower_int == -1 && ERROR_OCCURRED()) { return false; } } Py_ssize_t upper_int = PY_SSIZE_T_MAX; if (upper != Py_None) { upper_int = CONVERT_TO_INDEX(upper); if (upper_int == -1 && ERROR_OCCURRED()) { return false; } } int status = PySequence_DelSlice(target, lower_int, upper_int); if (unlikely(status == -1)) { return false; } } else { PyObject *slice = PySlice_New(lower, upper, NULL); if (unlikely(slice == NULL)) { return false; } int status = PyObject_DelItem(target, slice); Py_DECREF(slice); if (unlikely(status == -1)) { return false; } } return true; } NUITKA_MAY_BE_UNUSED static bool DEL_INDEX_SLICE(PyObject *target, Py_ssize_t lower, Py_ssize_t upper) { CHECK_OBJECT(target); PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence; if (tp_as_sequence && tp_as_sequence->sq_ass_slice) { int status = PySequence_DelSlice(target, lower, upper); if (unlikely(status == -1)) { return false; } } else { PyObject *slice = _PySlice_FromIndices(lower, upper); if (unlikely(slice == NULL)) { return false; } int status = PyObject_DelItem(target, slice); Py_DECREF(slice); if (unlikely(status == -1)) { return false; } } return true; } #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_ne.h0000600000372100037210000003757714166627112032271 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "!=" (NE) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_NE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_NE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_NE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_NE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_NE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_NE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_NE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_NE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_NE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_NE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_NE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_NE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_NE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_lt.h0000600000372100037210000003757614166627112032305 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<" (LT) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_LT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_LT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_LT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_LT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_LT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_LT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_LT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_LT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_LT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_LT_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LT_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LT_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_rshift.h0000600000372100037210000001177314166627112034346 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">>" (RSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_RSHIFT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_lshift.h0000600000372100037210000000600214166627112034454 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "<<" (LSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_LSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_LSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_LSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_LSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_LSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_LSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_LSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_LSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_LSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/dictionaries.h0000600000372100037210000002724714166627112031720 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_DICTIONARIES_H__ #define __NUITKA_DICTIONARIES_H__ static inline Py_ssize_t DICT_SIZE(PyObject *dict) { CHECK_OBJECT(dict); return ((PyDictObject *)dict)->ma_used; } static inline PyDictObject *MODULE_DICT(PyObject *module) { CHECK_OBJECT(module); PyDictObject *dict = (PyDictObject *)(((PyModuleObject *)module)->md_dict); return dict; } #if PYTHON_VERSION < 0x300 // Quick dictionary lookup for a string value. typedef PyDictEntry *Nuitka_DictEntryHandle; static PyDictEntry *GET_STRING_DICT_ENTRY(PyDictObject *dict, Nuitka_StringObject *key) { assert(PyDict_CheckExact(dict)); assert(Nuitka_String_CheckExact(key)); Py_hash_t hash = key->ob_shash; // Only improvement would be to identify how to ensure that the hash is // computed already. Calling hash early on could do that potentially. if (hash == -1) { hash = PyString_Type.tp_hash((PyObject *)key); key->ob_shash = hash; } PyDictEntry *entry = dict->ma_lookup(dict, (PyObject *)key, hash); // The "entry" cannot be NULL, it can only be empty for a string dict // lookup, but at least assert it. assert(entry != NULL); return entry; } NUITKA_MAY_BE_UNUSED static PyObject *GET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle) { return handle->me_value; } NUITKA_MAY_BE_UNUSED static void SET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle, PyObject *value) { handle->me_value = value; } static PyObject *GET_STRING_DICT_VALUE(PyDictObject *dict, Nuitka_StringObject *key) { return GET_STRING_DICT_ENTRY(dict, key)->me_value; } #else // Python 3.3 or higher. // Quick dictionary lookup for a string value. typedef struct { /* Cached hash code of me_key. */ Py_hash_t me_hash; PyObject *me_key; PyObject *me_value; /* This field is only meaningful for combined tables */ } PyDictKeyEntry; #if PYTHON_VERSION < 0x360 typedef PyDictKeyEntry *(*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); #elif PYTHON_VERSION < 0x370 typedef Py_ssize_t (*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos); #else typedef Py_ssize_t (*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); #endif // Taken from CPython3.3 "Objects/dictobject.c", lives in "Objects/dict-common.h" later struct _dictkeysobject { Py_ssize_t dk_refcnt; Py_ssize_t dk_size; dict_lookup_func dk_lookup; Py_ssize_t dk_usable; #if PYTHON_VERSION < 0x360 PyDictKeyEntry dk_entries[1]; #else Py_ssize_t dk_nentries; union { int8_t as_1[8]; int16_t as_2[4]; int32_t as_4[2]; #if SIZEOF_VOID_P > 4 int64_t as_8[1]; #endif } dk_indices; #endif }; // Taken from Objects/dictobject.c of CPython 3.6 #if PYTHON_VERSION >= 0x360 #define DK_SIZE(dk) ((dk)->dk_size) #if SIZEOF_VOID_P > 4 #define DK_IXSIZE(dk) \ (DK_SIZE(dk) <= 0xff ? 1 : DK_SIZE(dk) <= 0xffff ? 2 : DK_SIZE(dk) <= 0xffffffff ? 4 : sizeof(int64_t)) #else #define DK_IXSIZE(dk) (DK_SIZE(dk) <= 0xff ? 1 : DK_SIZE(dk) <= 0xffff ? 2 : sizeof(int32_t)) #endif #define DK_ENTRIES(dk) ((PyDictKeyEntry *)(&(dk)->dk_indices.as_1[DK_SIZE(dk) * DK_IXSIZE(dk)])) #define DK_USABLE_FRACTION(n) (((n) << 1) / 3) #endif typedef PyObject **Nuitka_DictEntryHandle; static Nuitka_DictEntryHandle GET_STRING_DICT_ENTRY(PyDictObject *dict, Nuitka_StringObject *key) { assert(PyDict_CheckExact(dict)); assert(Nuitka_String_CheckExact(key)); Py_hash_t hash = key->_base._base.hash; // Only improvement would be to identify how to ensure that the hash is computed // already. Calling hash early on could do that potentially. if (hash == -1) { hash = PyUnicode_Type.tp_hash((PyObject *)key); key->_base._base.hash = hash; } #if PYTHON_VERSION < 0x360 PyObject **value_addr; PyDictKeyEntry *entry = dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value_addr); // The "entry" cannot be NULL, it can only be empty for a string dict lookup, but at // least assert it. assert(entry != NULL); return value_addr; #elif PYTHON_VERSION < 0x370 PyObject **value_addr; // TODO: Find out what the returned Py_ssize_t "ix" might be good for. dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value_addr, NULL // hashpos, TODO: Find out what we could use it for. ); return value_addr; #else PyObject *value; Py_ssize_t ix = dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value); if (value == NULL) { return NULL; } else if (_PyDict_HasSplitTable(dict)) { return &dict->ma_values[ix]; } else { return &DK_ENTRIES(dict->ma_keys)[ix].me_value; } #endif } NUITKA_MAY_BE_UNUSED static PyObject *GET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle) { return *handle; } NUITKA_MAY_BE_UNUSED static void SET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle, PyObject *value) { *handle = value; } NUITKA_MAY_BE_UNUSED static PyObject *GET_STRING_DICT_VALUE(PyDictObject *dict, Nuitka_StringObject *key) { Nuitka_DictEntryHandle handle = GET_STRING_DICT_ENTRY(dict, key); #if PYTHON_VERSION >= 0x360 if (handle == NULL) { return NULL; } #endif return GET_DICT_ENTRY_VALUE(handle); } #endif NUITKA_MAY_BE_UNUSED static bool DICT_SET_ITEM(PyObject *dict, PyObject *key, PyObject *value) { CHECK_OBJECT(dict); CHECK_OBJECT(key); CHECK_OBJECT(value); int status = PyDict_SetItem(dict, key, value); if (unlikely(status != 0)) { return false; } return true; } NUITKA_MAY_BE_UNUSED static bool DICT_REMOVE_ITEM(PyObject *dict, PyObject *key) { int status = PyDict_DelItem(dict, key); if (unlikely(status == -1)) { return false; } return true; } // Get dict lookup for a key, similar to PyDict_GetItemWithError, ref returned extern PyObject *DICT_GET_ITEM_WITH_ERROR(PyObject *dict, PyObject *key); // Get dict lookup for a key, with only hash error, does not create KeyError, 1=ref returned, 0=not extern PyObject *DICT_GET_ITEM_WITH_HASH_ERROR1(PyObject *dict, PyObject *key); extern PyObject *DICT_GET_ITEM_WITH_HASH_ERROR0(PyObject *dict, PyObject *key); // Get dict lookup for a key, similar to PyDict_GetItem, 1=ref returned, 0=not extern PyObject *DICT_GET_ITEM1(PyObject *dict, PyObject *key); extern PyObject *DICT_GET_ITEM0(PyObject *dict, PyObject *key); // Get dict lookup for a key, similar to PyDict_Contains extern int DICT_HAS_ITEM(PyObject *dict, PyObject *key); // Convert to dictionary, helper for built-in "dict" mainly. NUITKA_MAY_BE_UNUSED static PyObject *TO_DICT(PyObject *seq_obj, PyObject *dict_obj) { PyObject *result = PyDict_New(); if (seq_obj != NULL) { int res; if (PyObject_HasAttrString(seq_obj, "keys")) { res = PyDict_Merge(result, seq_obj, 1); } else { res = PyDict_MergeFromSeq2(result, seq_obj, 1); } if (res == -1) { return NULL; } } if (dict_obj != NULL) { int res = PyDict_Merge(result, dict_obj, 1); if (res == -1) { return NULL; } } return result; } NUITKA_MAY_BE_UNUSED static void UPDATE_STRING_DICT0(PyDictObject *dict, Nuitka_StringObject *key, PyObject *value) { CHECK_OBJECT(value); Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key); #if PYTHON_VERSION >= 0x360 if (entry == NULL) { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); return; } #endif PyObject *old = GET_DICT_ENTRY_VALUE(entry); // Values are more likely (more often) set than not set, in that case // speculatively try the quickest access method. if (likely(old != NULL)) { Py_INCREF(value); SET_DICT_ENTRY_VALUE(entry, value); CHECK_OBJECT(old); Py_DECREF(old); } else { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); } } NUITKA_MAY_BE_UNUSED static void UPDATE_STRING_DICT_INPLACE(PyDictObject *dict, Nuitka_StringObject *key, PyObject *value) { CHECK_OBJECT(value); Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key); #if PYTHON_VERSION >= 0x360 if (entry == NULL) { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); Py_DECREF(value); CHECK_OBJECT(value); return; } #endif PyObject *old = GET_DICT_ENTRY_VALUE(entry); // Values are more likely (more often) set than not set, in that case // speculatively try the quickest access method. if (likely(old != NULL)) { SET_DICT_ENTRY_VALUE(entry, value); } else { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); Py_DECREF(value); CHECK_OBJECT(value); } } NUITKA_MAY_BE_UNUSED static void UPDATE_STRING_DICT1(PyDictObject *dict, Nuitka_StringObject *key, PyObject *value) { CHECK_OBJECT(value); Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key); #if PYTHON_VERSION >= 0x360 if (entry == NULL) { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); Py_DECREF(value); CHECK_OBJECT(value); return; } #endif PyObject *old = GET_DICT_ENTRY_VALUE(entry); // Values are more likely (more often) set than not set, in that case // speculatively try the quickest access method. if (likely(old != NULL)) { SET_DICT_ENTRY_VALUE(entry, value); Py_DECREF(old); } else { DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value); Py_DECREF(value); CHECK_OBJECT(value); } } #if PYTHON_VERSION < 0x300 // Python2 dictionary keys, return a list of keys extern PyObject *DICT_KEYS(PyObject *dict); // Python2 dictionary items, return a list of values extern PyObject *DICT_VALUES(PyObject *dict); // Python2 dictionary items, return a list of key/value tuples extern PyObject *DICT_ITEMS(PyObject *dict); #endif // Python3 dictionary keys, Python2 iterkeys returns dictionary keys iterator extern PyObject *DICT_ITERKEYS(PyObject *dict); // Python3 dictionary values, Python2 itervalues returns dictionary values iterator extern PyObject *DICT_ITERVALUES(PyObject *dict); // Python3 dictionary items, Python2 iteritems returns dictionary items iterator extern PyObject *DICT_ITERITEMS(PyObject *dict); // Python dictionary keys view extern PyObject *DICT_VIEWKEYS(PyObject *dict); // Python dictionary values view extern PyObject *DICT_VIEWVALUES(PyObject *dict); // Python dictionary items view extern PyObject *DICT_VIEWITEMS(PyObject *dict); // Python dictionary copy, return a shallow copy of a dictionary. extern PyObject *DICT_COPY(PyObject *dict); // Python dictionary clear, empty a dictionary. extern void DICT_CLEAR(PyObject *dict); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/richcomparisons.h0000600000372100037210000000217214166627112032434 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_RICHCOMPARISONS_H__ #define __NUITKA_HELPER_RICHCOMPARISONS_H__ #include "nuitka/helper/comparisons_eq.h" #include "nuitka/helper/comparisons_ge.h" #include "nuitka/helper/comparisons_gt.h" #include "nuitka/helper/comparisons_le.h" #include "nuitka/helper/comparisons_lt.h" #include "nuitka/helper/comparisons_ne.h" #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/calling2.h0000600000372100037210000002216714166627112030732 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template CodeTemplateCallsPositional.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif extern PyObject *CALL_FUNCTION_NO_ARGS(PyObject *called); extern PyObject *CALL_FUNCTION_WITH_SINGLE_ARG(PyObject *called, PyObject *arg); extern PyObject *CALL_FUNCTION_WITH_POSARGS1(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS2(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS2(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS3(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS3(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS4(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS4(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS5(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS5(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS6(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS6(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS7(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS7(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS8(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS8(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS9(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS9(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_ARGS10(PyObject *called, PyObject *const *args); extern PyObject *CALL_FUNCTION_WITH_POSARGS10(PyObject *called, PyObject *pos_args); extern PyObject *CALL_FUNCTION_WITH_NO_ARGS_KWSPLIT(PyObject *called, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS1_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS1_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS1_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS2_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS2_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS2_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS3_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS3_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS3_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS4_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS4_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS4_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS5_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS5_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS5_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS6_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS6_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS6_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS7_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS7_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS7_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS8_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS8_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS8_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS9_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS9_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS9_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS10_VECTORCALL(PyObject *called, PyObject *const *args, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_ARGS10_KWSPLIT(PyObject *called, PyObject *const *args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_FUNCTION_WITH_POSARGS10_KWSPLIT(PyObject *called, PyObject *pos_args, PyObject *const *kw_values, PyObject *kw_names); extern PyObject *CALL_METHODDESCR_WITH_SINGLE_ARG(PyObject *called, PyObject *arg); extern PyObject *CALL_METHODDESCR_WITH_ARGS2(PyObject *called, PyObject *const *args); extern PyObject *CALL_METHODDESCR_WITH_ARGS3(PyObject *called, PyObject *const *args); extern PyObject *CALL_METHODDESCR_WITH_ARGS4(PyObject *called, PyObject *const *args); extern PyObject *CALL_METHOD_NO_ARGS(PyObject *source, PyObject *attr_name); extern PyObject *CALL_METHOD_WITH_SINGLE_ARG(PyObject *source, PyObject *attr_name, PyObject *arg); extern PyObject *CALL_METHOD_WITH_ARGS2(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS3(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS4(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS5(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS6(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS7(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS8(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS9(PyObject *source, PyObject *attr_name, PyObject *const *args); extern PyObject *CALL_METHOD_WITH_ARGS10(PyObject *source, PyObject *attr_name, PyObject *const *args); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_eq.h0000600000372100037210000003757714166627112032274 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "==" (EQ) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_EQ_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_EQ_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_EQ_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_EQ_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_EQ_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_EQ_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_EQ_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_EQ_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_EQ_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_EQ_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_EQ_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/mappings.h0000600000372100037210000000233014166627112031043 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_MAPPINGS_H__ #define __NUITKA_MAPPINGS_H__ NUITKA_MAY_BE_UNUSED static int MAPPING_HAS_ITEM(PyObject *mapping, PyObject *key) { PyObject *result = PyObject_GetItem(mapping, key); if (result == NULL) { bool had_key_error = CHECK_AND_CLEAR_KEY_ERROR_OCCURRED(); if (had_key_error) { return 0; } else { return -1; } } else { return 1; } } #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/helper/subscripts.h0000600000372100037210000003602514166627112031436 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_SUBSCRIPTS_H__ #define __NUITKA_HELPER_SUBSCRIPTS_H__ extern PyObject *STRING_FROM_CHAR(unsigned char c); NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_SUBSCRIPT_CONST(PyObject *source, PyObject *const_subscript, Py_ssize_t int_subscript) { CHECK_OBJECT(source); CHECK_OBJECT(const_subscript); PyTypeObject *type = Py_TYPE(source); PyMappingMethods *mapping_methods = type->tp_as_mapping; PyObject *result; if (mapping_methods && mapping_methods->mp_subscript) { if (PyList_CheckExact(source)) { Py_ssize_t list_size = PyList_GET_SIZE(source); if (int_subscript < 0) { if (-int_subscript > list_size) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_IndexError, "list index out of range"); return NULL; } int_subscript += list_size; } else { if (int_subscript >= list_size) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_IndexError, "list index out of range"); return NULL; } } result = ((PyListObject *)source)->ob_item[int_subscript]; Py_INCREF(result); return result; } #if PYTHON_VERSION < 0x300 else if (PyString_CheckExact(source)) { Py_ssize_t string_size = PyString_GET_SIZE(source); if (int_subscript < 0) { if (-int_subscript > string_size) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_IndexError, "string index out of range"); return NULL; } int_subscript += string_size; } else { if (int_subscript >= string_size) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_IndexError, "string index out of range"); return NULL; } } unsigned char c = ((PyStringObject *)source)->ob_sval[int_subscript]; return STRING_FROM_CHAR(c); } #else else if (PyUnicode_CheckExact(source)) { if (int_subscript < 0) { int_subscript += PyUnicode_GET_LENGTH(source); } result = type->tp_as_sequence->sq_item(source, int_subscript); } #endif else { result = mapping_methods->mp_subscript(source, const_subscript); } } else if (type->tp_as_sequence) { result = PySequence_GetItem(source, int_subscript); } else { #if PYTHON_VERSION >= 0x370 if (PyType_Check(source)) { #if PYTHON_VERSION >= 0x390 if (source == (PyObject *)&PyType_Type) { PyObject *subscript = PyLong_FromSsize_t(int_subscript); result = Py_GenericAlias(source, subscript); Py_DECREF(subscript); return result; } #endif PyObject *meth = LOOKUP_ATTRIBUTE(source, const_str_plain___class_getitem__); if (meth) { PyObject *subscript = PyLong_FromSsize_t(int_subscript); result = CALL_FUNCTION_WITH_SINGLE_ARG(meth, subscript); Py_DECREF(meth); Py_DECREF(subscript); return result; } } #endif PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x270 "'%s' object is unsubscriptable", #elif PYTHON_VERSION >= 0x300 || PYTHON_VERSION <= 0x272 "'%s' object is not subscriptable", #else "'%s' object has no attribute '__getitem__'", #endif Py_TYPE(source)->tp_name); return NULL; } if (unlikely(result == NULL)) { return NULL; } return result; } NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_SUBSCRIPT(PyObject *source, PyObject *subscript) { CHECK_OBJECT(source); CHECK_OBJECT(subscript); PyTypeObject *type = Py_TYPE(source); PyMappingMethods *mapping = type->tp_as_mapping; if (mapping != NULL && mapping->mp_subscript != NULL) { return mapping->mp_subscript(source, subscript); } else if (type->tp_as_sequence != NULL) { if (PyIndex_Check(subscript)) { Py_ssize_t index = PyNumber_AsSsize_t(subscript, NULL); if (index == -1 && ERROR_OCCURRED()) { return NULL; } return PySequence_GetItem(source, index); } else if (type->tp_as_sequence->sq_item) { PyErr_Format(PyExc_TypeError, "sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name); return NULL; #if PYTHON_VERSION < 0x370 } else { PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x270 "'%s' object is unsubscriptable", #elif PYTHON_VERSION >= 0x300 || PYTHON_VERSION <= 0x272 "'%s' object is not subscriptable", #else "'%s' object has no attribute '__getitem__'", #endif Py_TYPE(source)->tp_name); return NULL; #endif } } #if PYTHON_VERSION >= 0x370 if (PyType_Check(source)) { #if PYTHON_VERSION >= 0x390 if (source == (PyObject *)&PyType_Type) { return Py_GenericAlias(source, subscript); } #endif PyObject *meth = LOOKUP_ATTRIBUTE(source, const_str_plain___class_getitem__); if (meth) { PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(meth, subscript); Py_DECREF(meth); return result; } } #endif PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x270 "'%s' object is unsubscriptable", #elif PYTHON_VERSION >= 0x300 || PYTHON_VERSION <= 0x272 "'%s' object is not subscriptable", #else "'%s' object has no attribute '__getitem__'", #endif Py_TYPE(source)->tp_name); return NULL; } NUITKA_MAY_BE_UNUSED static bool HAS_SUBSCRIPT_CONST(PyObject *source, PyObject *const_subscript, Py_ssize_t int_subscript) { CHECK_OBJECT(source); CHECK_OBJECT(const_subscript); PyTypeObject *type = Py_TYPE(source); PyMappingMethods *mapping_methods = type->tp_as_mapping; if (mapping_methods && mapping_methods->mp_subscript) { if (PyList_CheckExact(source)) { Py_ssize_t list_size = PyList_GET_SIZE(source); if (int_subscript < 0) { if (-int_subscript > list_size) { return false; } int_subscript += list_size; } else { if (int_subscript >= list_size) { return false; } } return true; } #if PYTHON_VERSION < 0x300 else if (PyString_CheckExact(source)) { Py_ssize_t string_size = PyString_GET_SIZE(source); if (int_subscript < 0) { if (-int_subscript > string_size) { return false; } int_subscript += string_size; } else { if (int_subscript >= string_size) { return false; } } return true; } #else else if (PyUnicode_CheckExact(source)) { if (int_subscript < 0) { int_subscript += PyUnicode_GET_LENGTH(source); } PyObject *result = type->tp_as_sequence->sq_item(source, int_subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } #endif else { PyObject *result = mapping_methods->mp_subscript(source, const_subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } } else if (type->tp_as_sequence) { PyObject *result = PySequence_GetItem(source, int_subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } else { #if PYTHON_VERSION >= 0x370 if (PyType_Check(source)) { #if PYTHON_VERSION >= 0x390 if (source == (PyObject *)&PyType_Type) { return true; } #endif PyObject *meth = LOOKUP_ATTRIBUTE(source, const_str_plain___class_getitem__); if (meth) { PyObject *subscript = PyLong_FromSsize_t(int_subscript); PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(meth, subscript); Py_DECREF(meth); Py_DECREF(subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } } #endif return false; } return false; } NUITKA_MAY_BE_UNUSED static bool HAS_SUBSCRIPT(PyObject *source, PyObject *subscript) { CHECK_OBJECT(source); CHECK_OBJECT(subscript); PyTypeObject *type = Py_TYPE(source); PyMappingMethods *mapping = type->tp_as_mapping; if (mapping != NULL && mapping->mp_subscript != NULL) { PyObject *result = mapping->mp_subscript(source, subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } else if (type->tp_as_sequence != NULL) { if (PyIndex_Check(subscript)) { Py_ssize_t index = PyNumber_AsSsize_t(subscript, NULL); if (index == -1 && ERROR_OCCURRED()) { return false; } PyObject *result = PySequence_GetItem(source, index); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } else if (type->tp_as_sequence->sq_item) { return false; #if PYTHON_VERSION < 0x370 } else { return false; #endif } } #if PYTHON_VERSION >= 0x370 if (PyType_Check(source)) { #if PYTHON_VERSION >= 0x390 if (source == (PyObject *)&PyType_Type) { return true; } #endif PyObject *meth = LOOKUP_ATTRIBUTE(source, const_str_plain___class_getitem__); if (meth) { PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(meth, subscript); bool bool_result = !DROP_ERROR_OCCURRED(); Py_XDECREF(result); return bool_result; } } #endif return false; } NUITKA_MAY_BE_UNUSED static bool SET_SUBSCRIPT_CONST(PyObject *target, PyObject *subscript, Py_ssize_t int_subscript, PyObject *value) { CHECK_OBJECT(value); CHECK_OBJECT(target); CHECK_OBJECT(subscript); PyMappingMethods *mapping_methods = Py_TYPE(target)->tp_as_mapping; if (mapping_methods != NULL && mapping_methods->mp_ass_subscript) { if (PyList_CheckExact(target)) { Py_ssize_t list_size = PyList_GET_SIZE(target); if (int_subscript < 0) { if (-int_subscript > list_size) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_IndexError, "list assignment index out of range"); return false; } int_subscript += list_size; } PyListObject *target_list = (PyListObject *)target; PyObject *old_value = target_list->ob_item[int_subscript]; Py_INCREF(value); target_list->ob_item[int_subscript] = value; Py_DECREF(old_value); return true; } else { int res = mapping_methods->mp_ass_subscript(target, subscript, value); if (unlikely(res == -1)) { return false; } return true; } } else if (Py_TYPE(target)->tp_as_sequence) { if (PyIndex_Check(subscript)) { Py_ssize_t key_value = PyNumber_AsSsize_t(subscript, PyExc_IndexError); if (key_value == -1) { if (ERROR_OCCURRED()) { return false; } } return SEQUENCE_SETITEM(target, key_value, value); } else if (Py_TYPE(target)->tp_as_sequence->sq_ass_item) { PyErr_Format(PyExc_TypeError, "sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name); return false; } else { PyErr_Format(PyExc_TypeError, "'%s' object does not support item assignment", Py_TYPE(target)->tp_name); return false; } } else { PyErr_Format(PyExc_TypeError, "'%s' object does not support item assignment", Py_TYPE(target)->tp_name); return false; } } NUITKA_MAY_BE_UNUSED static bool SET_SUBSCRIPT(PyObject *target, PyObject *subscript, PyObject *value) { CHECK_OBJECT(value); CHECK_OBJECT(target); CHECK_OBJECT(subscript); PyMappingMethods *mapping_methods = Py_TYPE(target)->tp_as_mapping; if (mapping_methods != NULL && mapping_methods->mp_ass_subscript) { int res = mapping_methods->mp_ass_subscript(target, subscript, value); if (unlikely(res == -1)) { return false; } } else if (Py_TYPE(target)->tp_as_sequence) { if (PyIndex_Check(subscript)) { Py_ssize_t key_value = PyNumber_AsSsize_t(subscript, PyExc_IndexError); if (key_value == -1) { if (ERROR_OCCURRED()) { return false; } } return SEQUENCE_SETITEM(target, key_value, value); } else if (Py_TYPE(target)->tp_as_sequence->sq_ass_item) { PyErr_Format(PyExc_TypeError, "sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name); return false; } else { PyErr_Format(PyExc_TypeError, "'%s' object does not support item assignment", Py_TYPE(target)->tp_name); return false; } } else { PyErr_Format(PyExc_TypeError, "'%s' object does not support item assignment", Py_TYPE(target)->tp_name); return false; } return true; } NUITKA_MAY_BE_UNUSED static bool DEL_SUBSCRIPT(PyObject *target, PyObject *subscript) { CHECK_OBJECT(target); CHECK_OBJECT(subscript); int status = PyObject_DelItem(target, subscript); if (unlikely(status == -1)) { return false; } return true; } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_mult.h0000600000372100037210000002452314166627112034154 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "*" (MULT) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MULT_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MULT_INT_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MULT_LONG_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_MULT_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_MULT_INT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "UNICODE" to Python2 'unicode', Python3 * 'str'. */ extern bool BINARY_OPERATION_MULT_LONG_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ extern bool BINARY_OPERATION_MULT_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MULT_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_TUPLE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MULT_INT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "TUPLE" corresponds to Python 'tuple' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_TUPLE_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MULT_LONG_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_TUPLE_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MULT_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_LIST_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MULT_INT_LIST_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LIST" corresponds to Python 'list' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_LIST_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MULT_LONG_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_LIST_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_MULT_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_MULT_LONG_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MULT_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MULT_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MULT_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MULT_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_bitor.h0000600000372100037210000000704614166627112034313 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "|" (BITOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_floordiv.h0000600000372100037210000001070214166627112035011 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "//" (FLOORDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_FLOORDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_FLOORDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_FLOORDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_FLOORDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_FLOORDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_FLOORDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_FLOORDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_bitand.h0000600000372100037210000000706314166627112034434 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "&" (BITAND) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITAND_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITAND_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITAND_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITAND_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITAND_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITAND_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITAND_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITAND_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITAND_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITAND_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITAND_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITAND_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_floordiv.h0000600000372100037210000001765214166627112034675 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "//" (FLOORDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_FLOORDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_FLOORDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/complex.h0000600000372100037210000000331714166627112030702 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_COMPLEX_H__ #define __NUITKA_HELPER_COMPLEX_H__ NUITKA_MAY_BE_UNUSED static PyObject *BUILTIN_COMPLEX1(PyObject *real) { CHECK_OBJECT(real); // TODO: Very lazy here, we should create the values ourselves, surely a // a lot of optimization can be had that way. At least use PyComplex_RealAsDouble // where possible. return CALL_FUNCTION_WITH_SINGLE_ARG((PyObject *)&PyComplex_Type, real); } NUITKA_MAY_BE_UNUSED static PyObject *BUILTIN_COMPLEX2(PyObject *real, PyObject *imag) { if (real == NULL) { assert(imag != NULL); real = const_int_0; } CHECK_OBJECT(real); CHECK_OBJECT(imag); // TODO: Very lazy here, we should create the values ourselves, surely a // a lot of optimization can be had that way. At least use PyComplex_FromDoubles PyObject *args[] = {real, imag}; return CALL_FUNCTION_WITH_ARGS2((PyObject *)&PyComplex_Type, args); } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/boolean.h0000600000372100037210000000512714166627112030653 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_BOOLEAN_H__ #define __NUITKA_HELPER_BOOLEAN_H__ // The slot in Python3 got renamed, compensate it like this. #if PYTHON_VERSION >= 0x300 #define nb_nonzero nb_bool #endif NUITKA_MAY_BE_UNUSED static int CHECK_IF_TRUE(PyObject *object) { CHECK_OBJECT(object); if (object == Py_True) { return 1; } else if (object == Py_False || object == Py_None) { return 0; } else { Py_ssize_t result; if (Py_TYPE(object)->tp_as_number != NULL && Py_TYPE(object)->tp_as_number->nb_nonzero != NULL) { result = (*Py_TYPE(object)->tp_as_number->nb_nonzero)(object); } else if (Py_TYPE(object)->tp_as_mapping != NULL && Py_TYPE(object)->tp_as_mapping->mp_length != NULL) { result = (*Py_TYPE(object)->tp_as_mapping->mp_length)(object); } else if (Py_TYPE(object)->tp_as_sequence != NULL && Py_TYPE(object)->tp_as_sequence->sq_length != NULL) { result = (*Py_TYPE(object)->tp_as_sequence->sq_length)(object); } else { return 1; } if (result > 0) { return 1; } else if (result == 0) { return 0; } else { return -1; } } } NUITKA_MAY_BE_UNUSED static int CHECK_IF_FALSE(PyObject *object) { int result = CHECK_IF_TRUE(object); if (result == 0) return 1; if (result == 1) return 0; return -1; } NUITKA_MAY_BE_UNUSED static inline PyObject *BOOL_FROM(bool value) { CHECK_OBJECT(Py_True); CHECK_OBJECT(Py_False); return value ? Py_True : Py_False; } #undef nb_nonzero typedef enum { NUITKA_BOOL_FALSE = 0, NUITKA_BOOL_TRUE = 1, NUITKA_BOOL_UNASSIGNED = 2, NUITKA_BOOL_EXCEPTION = -1 } nuitka_bool; typedef enum { NUITKA_VOID_OK = 0, NUITKA_VOID_EXCEPTION = 1 } nuitka_void; #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/lists.h0000600000372100037210000000376514166627112030400 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_LISTS_H__ #define __NUITKA_HELPER_LISTS_H__ extern PyObject *MAKE_LIST(PyObject *iterable); extern PyObject *LIST_COPY(PyObject *list); extern bool LIST_EXTEND_FROM_LIST(PyObject *list, PyObject *other); // Like PyList_SET_ITEM but takes a reference to the item. #define PyList_SET_ITEM0(tuple, index, value) \ { \ PyObject *tmp = value; \ Py_INCREF(tmp); \ PyList_SET_ITEM(tuple, index, tmp); \ } #endif extern bool LIST_EXTEND(PyObject *list, PyObject *other); extern bool LIST_EXTEND_FOR_UNPACK(PyObject *list, PyObject *other); // Like PyList_Append, but we get to specify the transfer of refcount ownership. extern bool LIST_APPEND1(PyObject *target, PyObject *item); extern bool LIST_APPEND0(PyObject *target, PyObject *item); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/sequences.h0000600000372100037210000000353714166627112031232 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_SEQUENCES_H__ #define __NUITKA_HELPER_SEQUENCES_H__ // TODO: Provide enhanced form of PySequence_Contains with less overhead. NUITKA_MAY_BE_UNUSED static bool SEQUENCE_SETITEM(PyObject *sequence, Py_ssize_t index, PyObject *value) { CHECK_OBJECT(sequence); CHECK_OBJECT(value); PySequenceMethods *sequence_methods = Py_TYPE(sequence)->tp_as_sequence; if (sequence_methods != NULL && sequence_methods->sq_ass_item) { if (index < 0) { if (sequence_methods->sq_length) { Py_ssize_t length = (*sequence_methods->sq_length)(sequence); if (length < 0) { return false; } index += length; } } int res = sequence_methods->sq_ass_item(sequence, index, value); if (unlikely(res == -1)) { return false; } return true; } else { PyErr_Format(PyExc_TypeError, "'%s' object does not support item assignment", Py_TYPE(sequence)->tp_name); return false; } } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_truediv.h0000600000372100037210000001761014166627112034525 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "/" (TRUEDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_TRUEDIV_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_pow.h0000600000372100037210000000704514166627112034000 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "**" (POW) operations */ /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_POW_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_POW_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_POW_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_POW_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_POW_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_POW_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_POW_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_POW_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_POW_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_POW_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_POW_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_POW_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/import_hard.h0000600000372100037210000000436114166627112031543 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperImportHard.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helper for hard import of module "__future__" import. */ extern PyObject *IMPORT_HARD___FUTURE__(void); /* C helper for hard import of module "_frozen_importlib" import. */ #if PYTHON_VERSION >= 0x300 extern PyObject *IMPORT_HARD__FROZEN_IMPORTLIB(void); #endif /* C helper for hard import of module "_frozen_importlib_external" import. */ #if PYTHON_VERSION >= 0x350 extern PyObject *IMPORT_HARD__FROZEN_IMPORTLIB_EXTERNAL(void); #endif /* C helper for hard import of module "functools" import. */ extern PyObject *IMPORT_HARD_FUNCTOOLS(void); /* C helper for hard import of module "importlib" import. */ extern PyObject *IMPORT_HARD_IMPORTLIB(void); /* C helper for hard import of module "os" import. */ extern PyObject *IMPORT_HARD_OS(void); /* C helper for hard import of module "pkgutil" import. */ extern PyObject *IMPORT_HARD_PKGUTIL(void); /* C helper for hard import of module "site" import. */ extern PyObject *IMPORT_HARD_SITE(void); /* C helper for hard import of module "sys" import. */ extern PyObject *IMPORT_HARD_SYS(void); /* C helper for hard import of module "types" import. */ extern PyObject *IMPORT_HARD_TYPES(void); /* C helper for hard import of module "typing" import. */ extern PyObject *IMPORT_HARD_TYPING(void); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_mod.h0000600000372100037210000003576514166627112033635 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "%" (MOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_TUPLE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_LIST(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "DICT" to Python 'dict'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_DICT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_FLOAT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_BYTES(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "DICT" to Python 'dict'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_DICT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_UNICODE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_TUPLE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_LIST(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "DICT" to Python 'dict'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_DICT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "DICT" to Python 'dict'. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_DICT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MOD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_builtin_types.h0000600000372100037210000001743314166627112034374 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif extern PyObject *DICT_POP2(PyObject *dict, PyObject *key); extern PyObject *DICT_POP3(PyObject *dict, PyObject *key, PyObject *default_value); extern PyObject *DICT_SETDEFAULT2(PyObject *dict, PyObject *key); extern PyObject *DICT_SETDEFAULT3(PyObject *dict, PyObject *key, PyObject *default_value); #if PYTHON_VERSION < 0x300 extern PyObject *STR_CAPITALIZE(PyObject *str); extern PyObject *STR_DECODE1(PyObject *str); extern PyObject *STR_DECODE2(PyObject *str, PyObject *encoding); extern PyObject *STR_DECODE3(PyObject *str, PyObject *encoding, PyObject *errors); extern PyObject *STR_ENCODE1(PyObject *str); extern PyObject *STR_ENCODE2(PyObject *str, PyObject *encoding); extern PyObject *STR_ENCODE3(PyObject *str, PyObject *encoding, PyObject *errors); extern PyObject *STR_ENDSWITH2(PyObject *str, PyObject *suffix); extern PyObject *STR_ENDSWITH3(PyObject *str, PyObject *suffix, PyObject *start); extern PyObject *STR_ENDSWITH4(PyObject *str, PyObject *suffix, PyObject *start, PyObject *end); extern PyObject *STR_FIND2(PyObject *str, PyObject *sub); extern PyObject *STR_FIND3(PyObject *str, PyObject *sub, PyObject *start); extern PyObject *STR_FIND4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *STR_INDEX2(PyObject *str, PyObject *sub); extern PyObject *STR_INDEX3(PyObject *str, PyObject *sub, PyObject *start); extern PyObject *STR_INDEX4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *STR_ISALNUM(PyObject *str); extern PyObject *STR_ISALPHA(PyObject *str); extern PyObject *STR_ISDIGIT(PyObject *str); extern PyObject *STR_ISLOWER(PyObject *str); extern PyObject *STR_ISSPACE(PyObject *str); extern PyObject *STR_ISTITLE(PyObject *str); extern PyObject *STR_ISUPPER(PyObject *str); extern PyObject *STR_LOWER(PyObject *str); extern PyObject *STR_LSTRIP1(PyObject *str); extern PyObject *STR_LSTRIP2(PyObject *str, PyObject *chars); extern PyObject *STR_PARTITION(PyObject *str, PyObject *sep); extern PyObject *STR_REPLACE3(PyObject *str, PyObject *old, PyObject *new_value); extern PyObject *STR_REPLACE4(PyObject *str, PyObject *old, PyObject *new_value, PyObject *count); extern PyObject *STR_RFIND2(PyObject *str, PyObject *sub); extern PyObject *STR_RFIND3(PyObject *str, PyObject *sub, PyObject *start); extern PyObject *STR_RFIND4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *STR_RINDEX2(PyObject *str, PyObject *sub); extern PyObject *STR_RINDEX3(PyObject *str, PyObject *sub, PyObject *start); extern PyObject *STR_RINDEX4(PyObject *str, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *STR_RPARTITION(PyObject *str, PyObject *sep); extern PyObject *STR_RSPLIT1(PyObject *str); extern PyObject *STR_RSPLIT2(PyObject *str, PyObject *sep); extern PyObject *STR_RSPLIT3(PyObject *str, PyObject *sep, PyObject *maxsplit); extern PyObject *STR_RSTRIP1(PyObject *str); extern PyObject *STR_RSTRIP2(PyObject *str, PyObject *chars); extern PyObject *STR_SPLIT1(PyObject *str); extern PyObject *STR_SPLIT2(PyObject *str, PyObject *sep); extern PyObject *STR_SPLIT3(PyObject *str, PyObject *sep, PyObject *maxsplit); extern PyObject *STR_STARTSWITH2(PyObject *str, PyObject *prefix); extern PyObject *STR_STARTSWITH3(PyObject *str, PyObject *prefix, PyObject *start); extern PyObject *STR_STARTSWITH4(PyObject *str, PyObject *prefix, PyObject *start, PyObject *end); extern PyObject *STR_STRIP1(PyObject *str); extern PyObject *STR_STRIP2(PyObject *str, PyObject *chars); extern PyObject *STR_SWAPCASE(PyObject *str); extern PyObject *STR_TITLE(PyObject *str); extern PyObject *STR_UPPER(PyObject *str); #endif extern PyObject *UNICODE_CAPITALIZE(PyObject *unicode); extern PyObject *UNICODE_ENCODE1(PyObject *unicode); extern PyObject *UNICODE_ENCODE2(PyObject *unicode, PyObject *encoding); extern PyObject *UNICODE_ENCODE3(PyObject *unicode, PyObject *encoding, PyObject *errors); extern PyObject *UNICODE_ENDSWITH2(PyObject *unicode, PyObject *suffix); extern PyObject *UNICODE_ENDSWITH3(PyObject *unicode, PyObject *suffix, PyObject *start); extern PyObject *UNICODE_ENDSWITH4(PyObject *unicode, PyObject *suffix, PyObject *start, PyObject *end); extern PyObject *UNICODE_FIND2(PyObject *unicode, PyObject *sub); extern PyObject *UNICODE_FIND3(PyObject *unicode, PyObject *sub, PyObject *start); extern PyObject *UNICODE_FIND4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *UNICODE_INDEX2(PyObject *unicode, PyObject *sub); extern PyObject *UNICODE_INDEX3(PyObject *unicode, PyObject *sub, PyObject *start); extern PyObject *UNICODE_INDEX4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *UNICODE_ISALNUM(PyObject *unicode); extern PyObject *UNICODE_ISALPHA(PyObject *unicode); extern PyObject *UNICODE_ISDIGIT(PyObject *unicode); extern PyObject *UNICODE_ISLOWER(PyObject *unicode); extern PyObject *UNICODE_ISSPACE(PyObject *unicode); extern PyObject *UNICODE_ISTITLE(PyObject *unicode); extern PyObject *UNICODE_ISUPPER(PyObject *unicode); extern PyObject *UNICODE_LOWER(PyObject *unicode); extern PyObject *UNICODE_LSTRIP1(PyObject *unicode); extern PyObject *UNICODE_LSTRIP2(PyObject *unicode, PyObject *chars); extern PyObject *UNICODE_REPLACE3(PyObject *unicode, PyObject *old, PyObject *new_value); extern PyObject *UNICODE_REPLACE4(PyObject *unicode, PyObject *old, PyObject *new_value, PyObject *count); extern PyObject *UNICODE_RFIND2(PyObject *unicode, PyObject *sub); extern PyObject *UNICODE_RFIND3(PyObject *unicode, PyObject *sub, PyObject *start); extern PyObject *UNICODE_RFIND4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *UNICODE_RINDEX2(PyObject *unicode, PyObject *sub); extern PyObject *UNICODE_RINDEX3(PyObject *unicode, PyObject *sub, PyObject *start); extern PyObject *UNICODE_RINDEX4(PyObject *unicode, PyObject *sub, PyObject *start, PyObject *end); extern PyObject *UNICODE_RSPLIT1(PyObject *unicode); extern PyObject *UNICODE_RSPLIT2(PyObject *unicode, PyObject *sep); extern PyObject *UNICODE_RSPLIT3(PyObject *unicode, PyObject *sep, PyObject *maxsplit); extern PyObject *UNICODE_RSTRIP1(PyObject *unicode); extern PyObject *UNICODE_RSTRIP2(PyObject *unicode, PyObject *chars); extern PyObject *UNICODE_SPLIT1(PyObject *unicode); extern PyObject *UNICODE_SPLIT2(PyObject *unicode, PyObject *sep); extern PyObject *UNICODE_SPLIT3(PyObject *unicode, PyObject *sep, PyObject *maxsplit); extern PyObject *UNICODE_STARTSWITH2(PyObject *unicode, PyObject *prefix); extern PyObject *UNICODE_STARTSWITH3(PyObject *unicode, PyObject *prefix, PyObject *start); extern PyObject *UNICODE_STARTSWITH4(PyObject *unicode, PyObject *prefix, PyObject *start, PyObject *end); extern PyObject *UNICODE_STRIP1(PyObject *unicode); extern PyObject *UNICODE_STRIP2(PyObject *unicode, PyObject *chars); extern PyObject *UNICODE_SWAPCASE(PyObject *unicode); extern PyObject *UNICODE_TITLE(PyObject *unicode); extern PyObject *UNICODE_UPPER(PyObject *unicode); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations.h0000600000372100037210000001073514166627112031420 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_OPERATIONS_H__ #define __NUITKA_OPERATIONS_H__ #if PYTHON_VERSION >= 0x300 extern PyObject *UNICODE_CONCAT(PyObject *left, PyObject *right); extern bool UNICODE_APPEND(PyObject **p_left, PyObject *right); #else // TODO: Specialize for Python2 too. NUITKA_MAY_BE_UNUSED static PyObject *UNICODE_CONCAT(PyObject *left, PyObject *right) { return PyUnicode_Concat(left, right); } #endif // This macro is necessary for Python2 to determine if the "coerce" slot // will have to be considered or not, and if in-place operations are // allowed to be there or not. #if PYTHON_VERSION < 0x300 #define NEW_STYLE_NUMBER(o) PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_CHECKTYPES) #define NEW_STYLE_NUMBER_TYPE(t) PyType_HasFeature(t, Py_TPFLAGS_CHECKTYPES) #define CAN_HAVE_INPLACE(t) PyType_HasFeature(t, Py_TPFLAGS_HAVE_INPLACEOPS) #else #define NEW_STYLE_NUMBER(o) (true) #define NEW_STYLE_NUMBER_TYPE(t) (true) #define CAN_HAVE_INPLACE(t) (true) #endif typedef PyObject *(unary_api)(PyObject *); NUITKA_MAY_BE_UNUSED static PyObject *UNARY_OPERATION(unary_api api, PyObject *operand) { CHECK_OBJECT(operand); PyObject *result = api(operand); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } // Generated helpers to execute operations on fully or partially known types. #include "nuitka/helper/operations_binary_add.h" #include "nuitka/helper/operations_binary_bitand.h" #include "nuitka/helper/operations_binary_bitor.h" #include "nuitka/helper/operations_binary_bitxor.h" #include "nuitka/helper/operations_binary_divmod.h" #include "nuitka/helper/operations_binary_floordiv.h" #include "nuitka/helper/operations_binary_lshift.h" #include "nuitka/helper/operations_binary_mod.h" #include "nuitka/helper/operations_binary_mult.h" #include "nuitka/helper/operations_binary_pow.h" #include "nuitka/helper/operations_binary_rshift.h" #include "nuitka/helper/operations_binary_sub.h" #include "nuitka/helper/operations_binary_truediv.h" #include "nuitka/helper/operations_inplace_add.h" #include "nuitka/helper/operations_inplace_bitand.h" #include "nuitka/helper/operations_inplace_bitor.h" #include "nuitka/helper/operations_inplace_bitxor.h" #include "nuitka/helper/operations_inplace_floordiv.h" #include "nuitka/helper/operations_inplace_lshift.h" #include "nuitka/helper/operations_inplace_mod.h" #include "nuitka/helper/operations_inplace_mult.h" #include "nuitka/helper/operations_inplace_pow.h" #include "nuitka/helper/operations_inplace_rshift.h" #include "nuitka/helper/operations_inplace_sub.h" #include "nuitka/helper/operations_inplace_truediv.h" #if PYTHON_VERSION < 0x300 // Classical division is Python2 only. #include "nuitka/helper/operations_binary_olddiv.h" #include "nuitka/helper/operations_inplace_olddiv.h" #endif #if PYTHON_VERSION >= 0x350 // Matrix multiplication is Python3.5 or higher only. #include "nuitka/helper/operations_binary_matmult.h" #include "nuitka/helper/operations_inplace_matmult.h" #endif // TODO: Get rid of the need for these, we should inline the abstract // algorithms, for now we have them for easier templating. #define PyNumber_InPlaceSub PyNumber_InPlaceSubtract #define PyNumber_InPlaceMult PyNumber_InPlaceMultiply #define PyNumber_InPlaceOlddiv PyNumber_InPlaceDivide #define PyNumber_InPlacePow(a, b) PyNumber_InPlacePower(a, b, Py_None) #define PyNumber_InPlaceMod PyNumber_InPlaceRemainder #define PyNumber_InPlaceBitor PyNumber_InPlaceOr #define PyNumber_InPlaceBitxor PyNumber_InPlaceXor #define PyNumber_InPlaceBitand PyNumber_InPlaceAnd #define PyNumber_InPlaceTruediv PyNumber_InPlaceTrueDivide #define PyNumber_InPlaceFloordiv PyNumber_InPlaceFloorDivide #define PyNumber_InPlaceMatmult PyNumber_InPlaceMatrixMultiply #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/tuples.h0000600000372100037210000000450714166627112030551 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_TUPLES_H__ #define __NUITKA_HELPER_TUPLES_H__ NUITKA_MAY_BE_UNUSED static PyObject *TUPLE_CONCAT(PyObject *t1, PyObject *t2) { Py_ssize_t size = Py_SIZE(t1) + Py_SIZE(t2); // Ignore MemoryError. if (unlikely(size < 0)) { return PyErr_NoMemory(); } PyTupleObject *result = (PyTupleObject *)PyTuple_New(size); if (unlikely(result == NULL)) { return NULL; } PyObject **src = ((PyTupleObject *)t1)->ob_item; PyObject **dest = result->ob_item; for (Py_ssize_t i = 0; i < Py_SIZE(t1); i++) { PyObject *v = src[i]; Py_INCREF(v); dest[i] = v; } src = ((PyTupleObject *)t2)->ob_item; dest = result->ob_item + Py_SIZE(t1); for (Py_ssize_t i = 0; i < Py_SIZE(t2); i++) { PyObject *v = src[i]; Py_INCREF(v); dest[i] = v; } return (PyObject *)result; } // Like PyTuple_SET_ITEM but takes a reference to the item. #define PyTuple_SET_ITEM0(tuple, index, value) \ { \ PyObject *tmp = value; \ Py_INCREF(tmp); \ PyTuple_SET_ITEM(tuple, index, tmp); \ } #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_bitxor.h0000600000372100037210000001306514166627112034352 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "^" (BITXOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITXOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITXOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_sub.h0000600000372100037210000001055414166627112033763 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "-" (SUB) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_SUB_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_SUB_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_SUB_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_SUB_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_SUB_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_SUB_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_SUB_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_SUB_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_SUB_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_SUB_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_SUB_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_SUB_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_SUB_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_SUB_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_SUB_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_SUB_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_mod.h0000600000372100037210000002677214166627112033762 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "%" (MOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_STR_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_STR_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_STR_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MOD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_MOD_STR_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MOD_STR_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MOD_STR_LIST_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "DICT" to Python 'dict'. */ extern bool BINARY_OPERATION_MOD_STR_DICT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_STR_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_MOD_UNICODE_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ extern bool BINARY_OPERATION_MOD_UNICODE_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_UNICODE_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MOD_UNICODE_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_MOD_UNICODE_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MOD_UNICODE_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MOD_UNICODE_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "DICT" to Python 'dict'. */ extern bool BINARY_OPERATION_MOD_UNICODE_DICT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MOD_BYTES_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MOD_BYTES_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_MOD_BYTES_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MOD_BYTES_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MOD_BYTES_LIST_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "DICT" to Python 'dict'. */ extern bool BINARY_OPERATION_MOD_BYTES_DICT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_BYTES_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool BINARY_OPERATION_MOD_OBJECT_STR_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool BINARY_OPERATION_MOD_OBJECT_BYTES_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool BINARY_OPERATION_MOD_OBJECT_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool BINARY_OPERATION_MOD_OBJECT_TUPLE_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool BINARY_OPERATION_MOD_OBJECT_LIST_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "DICT" to Python 'dict'. */ extern bool BINARY_OPERATION_MOD_OBJECT_DICT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MOD_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_gt.h0000600000372100037210000003757614166627112032300 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">" (GT) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_GT_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_GT_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_GT_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_GT_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_GT_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_GT_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_GT_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_GT_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_GT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_GT_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GT_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GT_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_matmult.h0000600000372100037210000000533014166627112034651 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "@" (MATMULT) operations */ #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MATMULT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_MATMULT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MATMULT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MATMULT_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_MATMULT_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MATMULT_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_MATMULT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_bitxor.h0000600000372100037210000000706314166627112034502 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "^" (BITXOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITXOR_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITXOR_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITXOR_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITXOR_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITXOR_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITXOR_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_BITXOR_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_BITXOR_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITXOR_SET_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern bool BINARY_OPERATION_BITXOR_OBJECT_SET_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITXOR_SET_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_BITXOR_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/raising.h0000600000372100037210000000626114166627112030670 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_RAISING_H__ #define __NUITKA_HELPER_RAISING_H__ #if PYTHON_VERSION >= 0x300 NUITKA_MAY_BE_UNUSED static void CHAIN_EXCEPTION(PyObject *exception_value) { // Implicit chain of exception already existing. PyThreadState *thread_state = PyThreadState_GET(); // Normalize existing exception first. NORMALIZE_EXCEPTION(&EXC_TYPE(thread_state), &EXC_VALUE(thread_state), (PyTracebackObject **)&EXC_TRACEBACK(thread_state)); PyObject *old_exc_value = EXC_VALUE(thread_state); if (old_exc_value != NULL && old_exc_value != Py_None && old_exc_value != exception_value) { PyObject *current = old_exc_value; while (true) { PyObject *context = PyException_GetContext(current); if (!context) break; CHECK_OBJECT(context); Py_DECREF(context); CHECK_OBJECT(context); if (context == exception_value) { PyException_SetContext(current, NULL); break; } current = context; } CHECK_OBJECT(old_exc_value); Py_INCREF(old_exc_value); PyException_SetContext(exception_value, old_exc_value); CHECK_OBJECT(EXC_TRACEBACK(thread_state)); ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(old_exc_value, (PyTracebackObject *)EXC_TRACEBACK(thread_state)); } } #endif extern void RAISE_EXCEPTION_WITH_TYPE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); #if PYTHON_VERSION >= 0x300 extern void RAISE_EXCEPTION_WITH_CAUSE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb, PyObject *exception_cause); #endif extern void RAISE_EXCEPTION_WITH_VALUE(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); extern void RAISE_EXCEPTION_IMPLICIT(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); extern void RAISE_EXCEPTION_WITH_TRACEBACK(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); extern bool RERAISE_EXCEPTION(PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_truediv.h0000600000372100037210000001066014166627112034652 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "/" (TRUEDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_TRUEDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_TRUEDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_TRUEDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_TRUEDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_TRUEDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_TRUEDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_TRUEDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_TRUEDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_TRUEDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_sub.h0000600000372100037210000001740414166627112033635 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "-" (SUB) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_SUB_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_SUB_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_divmod.h0000600000372100037210000000623414166627112034325 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "divmod" (DIVMOD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/rangeobjects.h0000600000372100037210000000420214166627112031673 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_RANGEOBJECTS_H__ #define __NUITKA_HELPER_RANGEOBJECTS_H__ /* For built-in built-in range() functionality. */ extern PyObject *BUILTIN_RANGE3(PyObject *low, PyObject *high, PyObject *step); extern PyObject *BUILTIN_RANGE2(PyObject *low, PyObject *high); extern PyObject *BUILTIN_RANGE(PyObject *boundary); /* For built-in built-in xrange() functionality. */ extern PyObject *BUILTIN_XRANGE1(PyObject *high); extern PyObject *BUILTIN_XRANGE2(PyObject *low, PyObject *high); extern PyObject *BUILTIN_XRANGE3(PyObject *low, PyObject *high, PyObject *step); #if PYTHON_VERSION >= 0x300 /* Python3 range objects */ struct _rangeobject3 { /* Python object folklore: */ PyObject_HEAD PyObject *start; PyObject *stop; PyObject *step; PyObject *length; }; NUITKA_MAY_BE_UNUSED static PyObject *PyRange_Start(PyObject *range) { return ((struct _rangeobject3 *)range)->start; } NUITKA_MAY_BE_UNUSED static PyObject *PyRange_Stop(PyObject *range) { return ((struct _rangeobject3 *)range)->stop; } NUITKA_MAY_BE_UNUSED static PyObject *PyRange_Step(PyObject *range) { return ((struct _rangeobject3 *)range)->step; } #else struct _rangeobject2 { /* Python object folklore: */ PyObject_HEAD long start; long step; long len; }; extern PyObject *MAKE_XRANGE(long start, long stop, long step); #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/iterators.h0000600000372100037210000002311014166627112031240 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_ITERATORS_H__ #define __NUITKA_HELPER_ITERATORS_H__ #if PYTHON_VERSION >= 0x270 // Initialize value for "tp_iternext" to compare with, needed by HAS_ITERNEXT // which emulates "PyCheck_Iter" but is bug free. extern iternextfunc default_iternext; extern void _initSlotIternext(void); #endif // This is like "PyIter_Check" but without bugs due to shared library pointers. NUITKA_MAY_BE_UNUSED static inline bool HAS_ITERNEXT(PyObject *value) { #if PYTHON_VERSION < 0x300 if (!PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HAVE_ITER)) { return false; } #endif iternextfunc tp_iternext = Py_TYPE(value)->tp_iternext; if (tp_iternext == NULL) { return false; } #if PYTHON_VERSION >= 0x270 return tp_iternext != default_iternext; #else return true; #endif } // Taken from CPython implementation, so we can access and create it, needs to match // their definition exactly. typedef struct { PyObject_HEAD #if PYTHON_VERSION < 0x340 long it_index; #else Py_ssize_t it_index; #endif PyObject *it_seq; } seqiterobject; NUITKA_MAY_BE_UNUSED static PyObject *MAKE_ITERATOR_INFALLIBLE(PyObject *iterated) { CHECK_OBJECT(iterated); #if PYTHON_VERSION < 0x300 getiterfunc tp_iter = NULL; if (PyType_HasFeature(Py_TYPE(iterated), Py_TPFLAGS_HAVE_ITER)) { tp_iter = Py_TYPE(iterated)->tp_iter; } #else getiterfunc tp_iter = Py_TYPE(iterated)->tp_iter; #endif if (tp_iter) { PyObject *result = (*tp_iter)(iterated); CHECK_OBJECT(result); assert(HAS_ITERNEXT(result)); return result; } else { assert(PySequence_Check(iterated)); seqiterobject *result = PyObject_GC_New(seqiterobject, &PySeqIter_Type); assert(result); result->it_index = 0; Py_INCREF(iterated); result->it_seq = iterated; Nuitka_GC_Track(result); return (PyObject *)result; } } NUITKA_MAY_BE_UNUSED static PyObject *MAKE_ITERATOR(PyObject *iterated) { CHECK_OBJECT(iterated); #if PYTHON_VERSION < 0x300 getiterfunc tp_iter = NULL; if (PyType_HasFeature(Py_TYPE(iterated), Py_TPFLAGS_HAVE_ITER)) { tp_iter = Py_TYPE(iterated)->tp_iter; } #else getiterfunc tp_iter = Py_TYPE(iterated)->tp_iter; #endif if (tp_iter) { PyObject *result = (*tp_iter)(iterated); if (unlikely(result == NULL)) { return NULL; } else if (unlikely(!HAS_ITERNEXT(result))) { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("iter() returned non-iterator of type '%s'", result); Py_DECREF(result); return NULL; } else { return result; } } else if (PySequence_Check(iterated)) { seqiterobject *result = PyObject_GC_New(seqiterobject, &PySeqIter_Type); assert(result); result->it_index = 0; Py_INCREF(iterated); result->it_seq = iterated; Nuitka_GC_Track(result); return (PyObject *)result; } else { SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' object is not iterable", iterated); return NULL; } } #if PYTHON_VERSION >= 0x370 NUITKA_MAY_BE_UNUSED static PyObject *MAKE_UNPACK_ITERATOR(PyObject *iterated) { CHECK_OBJECT(iterated); getiterfunc tp_iter = Py_TYPE(iterated)->tp_iter; if (tp_iter) { PyObject *result = (*tp_iter)(iterated); if (unlikely(result == NULL)) { return NULL; } else if (unlikely(!HAS_ITERNEXT(result))) { PyErr_Format(PyExc_TypeError, "iter() returned non-iterator of type '%s'", Py_TYPE(result)->tp_name); Py_DECREF(result); return NULL; } else { return result; } } else if (PySequence_Check(iterated)) { seqiterobject *result = PyObject_GC_New(seqiterobject, &PySeqIter_Type); assert(result); result->it_index = 0; Py_INCREF(iterated); result->it_seq = iterated; Nuitka_GC_Track(result); return (PyObject *)result; } else { PyErr_Format(PyExc_TypeError, "cannot unpack non-iterable %s object", Py_TYPE(iterated)->tp_name); return NULL; } } #endif NUITKA_MAY_BE_UNUSED static PyObject *ITERATOR_NEXT(PyObject *iterator) { CHECK_OBJECT(iterator); iternextfunc iternext = Py_TYPE(iterator)->tp_iternext; if (unlikely(iternext == NULL)) { PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x300 && defined(_NUITKA_FULL_COMPAT) "%s object is not an iterator", #else "'%s' object is not an iterator", #endif Py_TYPE(iterator)->tp_name); return NULL; } PyObject *result = (*iternext)(iterator); CHECK_OBJECT_X(result); return result; } NUITKA_MAY_BE_UNUSED static PyObject *BUILTIN_NEXT1(PyObject *iterator) { CHECK_OBJECT(iterator); iternextfunc iternext = Py_TYPE(iterator)->tp_iternext; if (unlikely(iternext == NULL)) { PyErr_Format(PyExc_TypeError, #if PYTHON_VERSION < 0x300 && defined(_NUITKA_FULL_COMPAT) "%s object is not an iterator", #else "'%s' object is not an iterator", #endif Py_TYPE(iterator)->tp_name); return NULL; } PyObject *result = (*iternext)(iterator); if (unlikely(result == NULL)) { // The iteration can return NULL with no error, which means // StopIteration. if (!ERROR_OCCURRED()) { SET_CURRENT_EXCEPTION_TYPE0(PyExc_StopIteration); } return NULL; } else { CHECK_OBJECT(result); } return result; } NUITKA_MAY_BE_UNUSED static PyObject *BUILTIN_NEXT2(PyObject *iterator, PyObject *default_value) { CHECK_OBJECT(iterator); CHECK_OBJECT(default_value); PyObject *result = (*Py_TYPE(iterator)->tp_iternext)(iterator); if (unlikely(result == NULL)) { bool stop_iteration_error = CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(); if (unlikely(stop_iteration_error == false)) { return NULL; } Py_INCREF(default_value); return default_value; } CHECK_OBJECT(result); return result; } // For cases, where no exception raising is needed, because we know it at compile time. NUITKA_MAY_BE_UNUSED static PyObject *UNPACK_NEXT_INFALLIBLE(PyObject *iterator) { CHECK_OBJECT(iterator); assert(HAS_ITERNEXT(iterator)); PyObject *result = (*Py_TYPE(iterator)->tp_iternext)(iterator); CHECK_OBJECT(result); return result; } #if PYTHON_VERSION < 0x350 NUITKA_MAY_BE_UNUSED static PyObject *UNPACK_NEXT(PyObject *iterator, int seq_size_so_far) #else NUITKA_MAY_BE_UNUSED static PyObject *UNPACK_NEXT(PyObject *iterator, int seq_size_so_far, int expected) #endif { CHECK_OBJECT(iterator); assert(HAS_ITERNEXT(iterator)); PyObject *result = (*Py_TYPE(iterator)->tp_iternext)(iterator); if (unlikely(result == NULL)) { #if PYTHON_VERSION < 0x300 if (unlikely(!ERROR_OCCURRED())) #else if (unlikely(!ERROR_OCCURRED() || EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_StopIteration))) #endif { #if PYTHON_VERSION < 0x350 if (seq_size_so_far == 1) { SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "need more than 1 value to unpack"); } else { PyErr_Format(PyExc_ValueError, "need more than %d values to unpack", seq_size_so_far); } #else PyErr_Format(PyExc_ValueError, "not enough values to unpack (expected %d, got %d)", expected, seq_size_so_far); #endif } return NULL; } CHECK_OBJECT(result); return result; } #if PYTHON_VERSION >= 0x350 // Different error message for starred unpacks NUITKA_MAY_BE_UNUSED static PyObject *UNPACK_NEXT_STARRED(PyObject *iterator, int seq_size_so_far, int expected) { CHECK_OBJECT(iterator); assert(HAS_ITERNEXT(iterator)); PyObject *result = (*Py_TYPE(iterator)->tp_iternext)(iterator); if (unlikely(result == NULL)) { if (unlikely(!ERROR_OCCURRED() || EXCEPTION_MATCH_BOOL_SINGLE(GET_ERROR_OCCURRED(), PyExc_StopIteration))) { PyErr_Format(PyExc_ValueError, "not enough values to unpack (expected at least %d, got %d)", expected, seq_size_so_far); } return NULL; } CHECK_OBJECT(result); return result; } #endif NUITKA_MAY_BE_UNUSED static bool UNPACK_ITERATOR_CHECK(PyObject *iterator) { CHECK_OBJECT(iterator); assert(HAS_ITERNEXT(iterator)); PyObject *attempt = (*Py_TYPE(iterator)->tp_iternext)(iterator); if (likely(attempt == NULL)) { return CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(); } else { Py_DECREF(attempt); SET_CURRENT_EXCEPTION_TYPE0_STR(PyExc_ValueError, "too many values to unpack"); return false; } } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/sets.h0000600000372100037210000000200114166627112030176 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_SETS_H__ #define __NUITKA_SETS_H__ // This is not Python headers before 3.10, but we use it in our assertions. #if PYTHON_VERSION < 0x3a0 #define PySet_CheckExact(op) (Py_TYPE(op) == &PySet_Type) #endif #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_bitand.h0000600000372100037210000001306514166627112034304 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "&" (BITAND) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITAND_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITAND_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_olddiv.h0000600000372100037210000001132114166627112034444 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place "/" (OLDDIV) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_OLDDIV_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_OLDDIV_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_OLDDIV_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_OLDDIV_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_OLDDIV_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_OLDDIV_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_OLDDIV_FLOAT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_OLDDIV_OBJECT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_OLDDIV_FLOAT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_OLDDIV_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_OLDDIV_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_OLDDIV_INT_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_OLDDIV_FLOAT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern bool BINARY_OPERATION_OLDDIV_LONG_FLOAT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_OLDDIV_FLOAT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_OLDDIV_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_pow.h0000600000372100037210000001413114166627112033643 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "**" (POW) operations */ /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_POW_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_POW_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_bitor.h0000600000372100037210000001303714166627112034161 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "|" (BITOR) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "SET" corresponds to Python 'set' and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_SET_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "SET" to Python 'set'. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_SET(PyObject *operand1, PyObject *operand2); /* Code referring to "SET" corresponds to Python 'set' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_SET_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_BITOR_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_BITOR_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_matmult.h0000600000372100037210000000535714166627112034533 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "@" (MATMULT) operations */ #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x350 /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_le.h0000600000372100037210000003757714166627112032267 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "<=" (LE) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_LE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_LE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_LE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_LE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_LE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_LE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_LE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_LE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_LE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_LE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_LE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_LE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_LE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_mult.h0000600000372100037210000003472414166627112034031 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "*" (MULT) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "CLONG" corresponds to C platform long value and "CLONG" to C platform long value. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_CLONG_CLONG(long operand1, long operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "CLONG" to C platform long value. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_CLONG(PyObject *operand1, long operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "CLONG" corresponds to C platform long value and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_CLONG_INT(long operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_STR_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_STR_LONG(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_UNICODE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "UNICODE" to Python2 'unicode', Python3 * 'str'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3 * 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_UNICODE_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_TUPLE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "TUPLE" corresponds to Python 'tuple' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_TUPLE_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_LIST(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LIST" corresponds to Python 'list' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LIST_LONG(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_BYTES_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_MULT_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_MULT_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_binary_add.h0000600000372100037210000003062314166627112033572 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized "+" (ADD) operations */ #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_LONG(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_INT_FLOAT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_INT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_LONG_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_FLOAT_LONG(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_STR_UNICODE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_UNICODE_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_STR_UNICODE(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_UNICODE_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *BINARY_OPERATION_ADD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool BINARY_OPERATION_ADD_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/bytearrays.h0000600000372100037210000000223514166627112031416 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_HELPER_BYTEARRAYS_H__ #define __NUITKA_HELPER_BYTEARRAYS_H__ NUITKA_MAY_BE_UNUSED static PyObject *BYTEARRAY_COPY(PyObject *bytearray) { CHECK_OBJECT(bytearray); assert(PyByteArray_CheckExact(bytearray)); PyObject *result = PyByteArray_FromObject(bytearray); if (unlikely(result == NULL)) { return NULL; } return result; } #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/strings.h0000600000372100037210000000233214166627112030720 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_STRINGS_H__ #define __NUITKA_STRINGS_H__ #if PYTHON_VERSION < 0x300 extern PyObject *STR_JOIN(PyObject *str, PyObject *iterable); #endif extern PyObject *UNICODE_JOIN(PyObject *str, PyObject *iterable); extern PyObject *UNICODE_PARTITION(PyObject *str, PyObject *sep); extern PyObject *UNICODE_RPARTITION(PyObject *str, PyObject *sep); extern PyObject *NuitkaUnicode_FromWideChar(const wchar_t *str, Py_ssize_t size); #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/helper/comparisons_ge.h0000600000372100037210000003757714166627112032262 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationComparison.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type specialized ">=" (GE) comparisons */ /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_STR_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern bool RICH_COMPARE_GE_CBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_STR_STR(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_UNICODE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern bool RICH_COMPARE_GE_CBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); /* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode', * Python3 'str'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_UNICODE_UNICODE(PyObject *operand1, PyObject *operand2); #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_BYTES_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern bool RICH_COMPARE_GE_CBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION >= 0x300 /* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_BYTES_BYTES(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_GE_CBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_INT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_INT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_INT_OBJECT(PyObject *operand1, PyObject *operand2); #endif /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_GE_CBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_LONG_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_LONG(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_LONG_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_GE_CBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_GE_CBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_TUPLE_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_TUPLE(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_TUPLE_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_GE_CBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_LIST_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern PyObject *RICH_COMPARE_GE_OBJECT_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern bool RICH_COMPARE_GE_CBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_OBJECT_LIST(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern PyObject *RICH_COMPARE_GE_OBJECT_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern bool RICH_COMPARE_GE_CBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); /* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */ extern nuitka_bool RICH_COMPARE_GE_NBOOL_LIST_OBJECT(PyObject *operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/operations_inplace_rshift.h0000600000372100037210000000600214166627112034462 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif /* C helpers for type in-place ">>" (RSHIFT) operations */ /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_RSHIFT_LONG_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_RSHIFT_OBJECT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_RSHIFT_LONG_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_RSHIFT_INT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_RSHIFT_OBJECT_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_RSHIFT_INT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */ extern bool BINARY_OPERATION_RSHIFT_INT_LONG_INPLACE(PyObject **operand1, PyObject *operand2); #endif #if PYTHON_VERSION < 0x300 /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */ extern bool BINARY_OPERATION_RSHIFT_LONG_INT_INPLACE(PyObject **operand1, PyObject *operand2); #endif /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */ extern bool BINARY_OPERATION_RSHIFT_OBJECT_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2); Nuitka-0.6.19.1/nuitka/build/include/nuitka/helper/printing.h0000600000372100037210000000503514166627112031064 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_PRINTING_H__ #define __NUITKA_PRINTING_H__ // Helper functions for print. Need to play nice with Python softspace // behavior. extern bool PRINT_NEW_LINE(void); extern bool PRINT_ITEM(PyObject *object); extern bool PRINT_STRING(char const *str); extern bool PRINT_FORMAT(char const *fmt, ...); extern bool PRINT_ITEM_TO(PyObject *file, PyObject *object); extern bool PRINT_NEW_LINE_TO(PyObject *file); extern PyObject *GET_STDOUT(); extern PyObject *GET_STDERR(); // ----------------------------------------------------------------------- // Helper functions to debug the run time operation of the compiled binary // manually or in debug modes. // Print the reference count of the object. extern void PRINT_REFCOUNT(PyObject *object); // Print the full traceback stack. // TODO: Could be ported, the "printf" stuff would need to be split. On Python3 // the normal C print output gets lost. #if PYTHON_VERSION < 0x300 extern void PRINT_TRACEBACK(PyTracebackObject *traceback); #endif // Print the exception state, including NULL values. #define PRINT_EXCEPTION(exception_type, exception_value, exception_tb) \ _PRINT_EXCEPTION(exception_type, exception_value, (PyObject *)exception_tb) extern void _PRINT_EXCEPTION(PyObject *exception_type, PyObject *exception_value, PyObject *exception_tb); // Print the current exception state, including NULL values. extern void PRINT_CURRENT_EXCEPTION(void); // Print the current exception state, including NULL values. extern void PRINT_PUBLISHED_EXCEPTION(void); // Print the representation of the object, or "" if it's not set. extern bool PRINT_REPR(PyObject *object); // Print the word , as an alternative to pointers. extern bool PRINT_NULL(void); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/prelude.h0000600000372100037210000004117014166627112027413 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_PRELUDE_H__ #define __NUITKA_PRELUDE_H__ #ifdef __NUITKA_NO_ASSERT__ #define NDEBUG #endif /* Include the CPython version numbers, and define our own take of what version * numbers should be. */ #include /* Use a hex version of our own to compare for versions. We do not care about pre-releases */ #if PY_MICRO_VERSION < 16 #define PYTHON_VERSION (PY_MAJOR_VERSION * 256 + PY_MINOR_VERSION * 16 + PY_MICRO_VERSION) #else #define PYTHON_VERSION (PY_MAJOR_VERSION * 256 + PY_MINOR_VERSION * 16 + 15) #endif /* This is needed or else we can't create modules name "proc" or "func". For * Python3, the name collision can't happen, so we can limit it to Python2. */ #define initproc python_initproc #define initfunc python_initfunc #define initstate python_initstate /* Include the relevant Python C-API header files. */ #include "Python.h" #include "frameobject.h" #include "marshal.h" #include "methodobject.h" #if PYTHON_VERSION < 0x3a0 #include "pydebug.h" #endif // We are not following the 3.10 change to an inline function. At least // not immediately. #if PYTHON_VERSION >= 0x3a0 #undef Py_REFCNT #define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt) #endif #if defined(_WIN32) // Windows is too difficult for API redefines. #define MIN_PYCORE_PYTHON_VERSION 0x380 #else #define MIN_PYCORE_PYTHON_VERSION 0x371 #endif #if PYTHON_VERSION >= MIN_PYCORE_PYTHON_VERSION #define NUITKA_USE_PYCORE_THREADSTATE #endif #ifdef NUITKA_USE_PYCORE_THREADSTATE #undef Py_BUILD_CORE #define Py_BUILD_CORE #undef _PyGC_FINALIZED #if PYTHON_VERSION < 0x380 #undef Py_ATOMIC_H #include "pyatomic.h" #undef Py_INTERNAL_PYSTATE_H #include "internal/pystate.h" #undef Py_STATE_H #include "pystate.h" extern _PyRuntimeState _PyRuntime; #else #include "internal/pycore_pystate.h" #endif #if PYTHON_VERSION >= 0x390 #include #include #include #endif #if PYTHON_VERSION >= 0x3a0 #include #endif // TODO: Might be useful too, allows access to Python configuration. // #include #undef PyThreadState_GET #define _PyThreadState_Current _PyRuntime.gilstate.tstate_current #define PyThreadState_GET() ((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) #undef Py_BUILD_CORE #endif /* See above. */ #if PYTHON_VERSION < 0x300 #undef initproc #undef initfunc #undef initstate #endif /* Type bool */ #ifndef __cplusplus #include "stdbool.h" #endif /* Include the C header files most often used. */ #include #include "hedley.h" /* Use annotations for branch prediction. They still make sense as the L1 * cache space is saved. */ #define likely(x) HEDLEY_LIKELY(x) #define unlikely(x) HEDLEY_UNLIKELY(x) /* A way to indicate that a specific function won't return, so the C compiler * can create better code. */ #define NUITKA_NO_RETURN HEDLEY_NO_RETURN /* A way to not give warnings about things that are declared, but might not * be used like in-line helper functions in headers or static per module * variables from headers. */ #ifdef __GNUC__ #define NUITKA_MAY_BE_UNUSED __attribute__((__unused__)) #else #define NUITKA_MAY_BE_UNUSED #endif /* This is used to indicate code control flows we know cannot happen. */ #ifndef __NUITKA_NO_ASSERT__ #define NUITKA_CANNOT_GET_HERE(NAME) \ PRINT_FORMAT("%s : %s\n", __FUNCTION__, #NAME); \ assert(false); \ abort(); #else #define NUITKA_CANNOT_GET_HERE(NAME) abort(); #endif #ifdef _MSC_VER /* Using "_alloca" extension due to MSVC restrictions for array variables * on the local stack. */ #include #define NUITKA_DYNAMIC_ARRAY_DECL(VARIABLE_NAME, ELEMENT_TYPE, COUNT) \ ELEMENT_TYPE *VARIABLE_NAME = (ELEMENT_TYPE *)_alloca(sizeof(ELEMENT_TYPE) * (COUNT)); #else #define NUITKA_DYNAMIC_ARRAY_DECL(VARIABLE_NAME, ELEMENT_TYPE, COUNT) ELEMENT_TYPE VARIABLE_NAME[COUNT]; #endif // Stringizing, to make strings out of defines use XSTRINGIZED(SOME_DEFINE) needs // to level of defines to work. #define _STRINGIZED(ARG) #ARG #define STRINGIZED(ARG) _STRINGIZED(ARG) /* Python3 removed PyInt instead of renaming PyLong, and PyObject_Str instead * of renaming PyObject_Unicode. Define this to be easily portable. */ #if PYTHON_VERSION >= 0x300 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyNumber_Int PyNumber_Long #define PyObject_Unicode PyObject_Str #endif /* String handling that uses the proper version of strings for Python3 or not, * which makes it easier to write portable code. */ #if PYTHON_VERSION < 0x300 #define Nuitka_String_AsString PyString_AsString #define Nuitka_String_AsString_Unchecked PyString_AS_STRING #define Nuitka_String_Check PyString_Check #define Nuitka_String_CheckExact PyString_CheckExact #define Nuitka_StringObject PyStringObject #define Nuitka_String_FromString PyString_FromString #define Nuitka_String_FromStringAndSize PyString_FromStringAndSize #define Nuitka_String_FromFormat PyString_FromFormat #define PyUnicode_CHECK_INTERNED (0) #else #define Nuitka_String_AsString _PyUnicode_AsString /* Note: This is from unicodeobject.c */ #define _PyUnicode_UTF8(op) (((PyCompactUnicodeObject *)(op))->utf8) #define PyUnicode_UTF8(op) \ (assert(PyUnicode_IS_READY(op)), \ PyUnicode_IS_COMPACT_ASCII(op) ? ((char *)((PyASCIIObject *)(op) + 1)) : _PyUnicode_UTF8(op)) #define Nuitka_String_AsString_Unchecked PyUnicode_UTF8 #define Nuitka_String_Check PyUnicode_Check #define Nuitka_String_CheckExact PyUnicode_CheckExact #define Nuitka_StringObject PyUnicodeObject #define Nuitka_String_FromString PyUnicode_FromString #define Nuitka_String_FromStringAndSize PyUnicode_FromStringAndSize #define Nuitka_String_FromFormat PyUnicode_FromFormat #endif #if PYTHON_VERSION < 0x300 #define PyUnicode_GET_LENGTH(x) (PyUnicode_GET_SIZE(x)) #endif // Wrap the type lookup for debug mode, to identify errors, and potentially // to make our own enhancement later on. For now only verify it is not being // called with an error set, which 3.9 asserts against in core code. #ifdef __NUITKA_NO_ASSERT__ #define Nuitka_TypeLookup(x, y) _PyType_Lookup(x, y) #else NUITKA_MAY_BE_UNUSED static inline bool ERROR_OCCURRED(void); NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_TypeLookup(PyTypeObject *type, PyObject *name) { assert(!ERROR_OCCURRED()); return _PyType_Lookup(type, name); } #endif /* With the idea to reduce the amount of exported symbols in the DLLs, make it * clear that the module "init" function should of course be exported, but not * for executable, where we call it ourselves from the main code. */ #if PYTHON_VERSION < 0x300 #define NUITKA_MODULE_ENTRY_FUNCTION void #else #define NUITKA_MODULE_ENTRY_FUNCTION PyObject * #endif /* Avoid gcc warnings about using an integer as a bool. This is a cherry-pick. * * This might apply to more versions. I am seeing this on 3.3.2, and it was * fixed for Python 2.x only later. We could include more versions. This is * only a problem with debug mode and therefore not too important maybe. */ #if PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x340 #undef PyMem_MALLOC #define PyMem_MALLOC(n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL : malloc(((n) != 0) ? (n) : 1)) #undef PyMem_REALLOC #define PyMem_REALLOC(p, n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL : realloc((p), ((n) != 0) ? (n) : 1)) #endif #if PYTHON_VERSION < 0x300 typedef long Py_hash_t; #endif /* These two express if a directly called function should be exported (C level) * or if it can be local to the file. */ #define NUITKA_CROSS_MODULE #define NUITKA_LOCAL_MODULE static /* Due to ABI issues, it seems that on Windows the symbols used by * "_PyObject_GC_TRACK" are not exported and we need to use a function that does * it instead. * * TODO: Make it work for 3.7 too. */ #if defined(_WIN32) || defined(__MSYS__) || PYTHON_VERSION >= 0x370 #define Nuitka_GC_Track PyObject_GC_Track #define Nuitka_GC_UnTrack PyObject_GC_UnTrack #else #define Nuitka_GC_Track _PyObject_GC_TRACK #define Nuitka_GC_UnTrack _PyObject_GC_UNTRACK #endif #if _NUITKA_EXPERIMENTAL_FAST_THREAD_GET && PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x370 // We are careful, access without locking under the assumption that we hold // the GIL over uses of this or the same thread continues to execute code of // ours. #undef PyThreadState_GET extern PyThreadState *_PyThreadState_Current; #define PyThreadState_GET() (_PyThreadState_Current) #endif #ifndef _NUITKA_FULL_COMPAT // Remove useless recursion control guards, we have no need for them or we // are achieving deeper recursion anyway. #undef Py_EnterRecursiveCall #define Py_EnterRecursiveCall(arg) (0) #undef Py_LeaveRecursiveCall #define Py_LeaveRecursiveCall() #endif #if PYTHON_VERSION < 0x300 #define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) ? (t)->tp_richcompare : NULL) #else #define RICHCOMPARE(t) ((t)->tp_richcompare) #endif // For older Python we need to define this ourselves. #ifndef Py_ABS #define Py_ABS(x) ((x) < 0 ? -(x) : (x)) #endif #ifndef Py_MIN #define Py_MIN(x, y) (((x) > (y)) ? (y) : (x)) #endif #ifndef Py_MAX #define Py_MAX(x, y) (((x) > (y)) ? (x) : (y)) #endif // For older Python, we don't have a feature "CLASS" anymore, that's implied now. #if PYTHON_VERSION < 0x300 #define NuitkaType_HasFeatureClass(descr) (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) #else #define NuitkaType_HasFeatureClass(descr) (1) #endif // Generated. // TODO: Move generated ones to separate file. #ifdef __IDE_ONLY__ extern PyObject **global_constants; // () #define const_tuple_empty global_constants[1] // {} #define const_dict_empty global_constants[2] // 0 #define const_int_0 global_constants[3] // 1 #define const_int_pos_1 global_constants[4] // -1 #define const_int_neg_1 global_constants[5] // 0.0 #define const_float_0_0 global_constants[6] // -0.0 #define const_float_minus_0_0 global_constants[7] // 1.0 #define const_float_1_0 global_constants[8] // -1.0 #define const_float_minus_1_0 global_constants[9] // '' #define const_str_empty global_constants[10] // b'' #define const_bytes_empty global_constants[10] // '__module__' #define const_str_plain___module__ global_constants[11] // '__class__' #define const_str_plain___class__ global_constants[12] // '__class_getitem__' #define const_str_plain___class_getitem__ global_constants[12] // '__name__' #define const_str_plain___name__ global_constants[13] // '__main__' #define const_str_plain___main__ global_constants[13] // '__package__' #define const_str_plain___package__ global_constants[14] // '__metaclass__' #define const_str_plain___metaclass__ global_constants[15] // '__abstractmethods__' #define const_str_plain___abstractmethods__ global_constants[15] // '__dict__' #define const_str_plain___dict__ global_constants[16] // '__doc__' #define const_str_plain___doc__ global_constants[17] // '__file__' #define const_str_plain___file__ global_constants[18] // '__path__' #define const_str_plain___path__ global_constants[19] // '__enter__' #define const_str_plain___enter__ global_constants[20] // '__exit__' #define const_str_plain___exit__ global_constants[21] // '__builtins__' #define const_str_plain___builtins__ global_constants[22] // '__all__' #define const_str_plain___all__ global_constants[23] // '__cmp__' #define const_str_plain___cmp__ global_constants[24] // '__init__' #define const_str_plain___init__ global_constants[24] // '__iter__' #define const_str_plain___iter__ global_constants[25] // '__compiled__' #define const_str_plain___compiled__ global_constants[26] // 'inspect' #define const_str_plain_inspect global_constants[27] // 'compile' #define const_str_plain_compile global_constants[28] // 'getattr' #define const_str_plain_getattr global_constants[28] // 'range' #define const_str_plain_range global_constants[29] // 'open' #define const_str_plain_open global_constants[30] // 'close' #define const_str_plain_close global_constants[30] // 'throw' #define const_str_plain_throw global_constants[30] // 'throw' #define const_str_plain_send global_constants[30] // 'sum' #define const_str_plain_sum global_constants[31] // 'format' #define const_str_plain_format global_constants[32] // '__import__' #define const_str_plain___import__ global_constants[33] // 'bytearray' #define const_str_plain_bytearray global_constants[34] // 'staticmethod' #define const_str_plain_staticmethod global_constants[35] // 'classmethod' #define const_str_plain_classmethod global_constants[36] // 'name' #define const_str_plain_name global_constants[37] // 'globals' #define const_str_plain_globals global_constants[38] // 'locals' #define const_str_plain_locals global_constants[39] // 'fromlist' #define const_str_plain_fromlist global_constants[40] // 'level' #define const_str_plain_level global_constants[41] // 'read' #define const_str_plain_read global_constants[42] // 'rb' #define const_str_plain_rb global_constants[43] // '__newobj__' #define const_str_plain___newobj__ global_constants[44] // '.' #define const_str_dot global_constants[45] // '__getattr__' #define const_str_plain___getattr__ global_constants[46] // '__setattr__' #define const_str_plain___setattr__ global_constants[47] // '__delattr__' #define const_str_plain___delattr__ global_constants[48] // 'exc_type' #define const_str_plain_exc_type global_constants[49] // 'exc_value' #define const_str_plain_exc_value global_constants[50] // 'exc_traceback' #define const_str_plain_exc_traceback global_constants[51] // 'xrange' #define const_str_plain_xrange global_constants[52] // 'site' #define const_str_plain_site global_constants[53] // 'type' #define const_str_plain_type global_constants[54] // 'len' #define const_str_plain_len global_constants[55] // 'range' #define const_str_plain_range global_constants[29] // 'repr' #define const_str_plain_repr global_constants[56] // 'int' #define const_str_plain_int global_constants[57] // 'iter' #define const_str_plain_iter global_constants[58] // 'long' #define const_str_plain_long global_constants[59] // 'end' #define const_str_plain_end global_constants[60] // 'file' #define const_str_plain_file global_constants[61] // 'print' #define const_str_plain_print global_constants[62] // '__spec__' #define const_str_plain___spec__ global_constants[63] // '_initializing' #define const_str_plain__initializing global_constants[64] // parent #define const_str_plain_parent global_constants[65] // types #define const_str_plain_types global_constants[66] // '__loader__' #define const_str_plain___loader__ global_constants[67] #define _NUITKA_CONSTANTS_SIZE 27 #define _NUITKA_CONSTANTS_HASH 0x27272727 #else #include "__constants.h" #endif #include "nuitka/helpers.h" #include "nuitka/compiled_frame.h" #include "nuitka/compiled_cell.h" #include "nuitka/compiled_function.h" /* Sentinel PyObject to be used for all our call iterator endings. */ extern PyObject *_sentinel_value; /* Value to use for __compiled__ value of all modules. */ extern PyObject *Nuitka_dunder_compiled_value; #include "nuitka/compiled_generator.h" #include "nuitka/compiled_method.h" #if PYTHON_VERSION >= 0x350 #include "nuitka/compiled_coroutine.h" #endif #if PYTHON_VERSION >= 0x360 #include "nuitka/compiled_asyncgen.h" #endif #include "nuitka/safe_string_ops.h" #if _NUITKA_EXPERIMENTAL_WRITEABLE_CONSTANTS #include "nuitka_data_decoder.h" #else #define DECODE(x) assert(x) #define UNTRANSLATE(x) (x) #endif #if _NUITKA_EXPERIMENTAL_INIT_PROGRAM #include "nuitka_init_program.h" #else #define NUITKA_INIT_PROGRAM_EARLY(argc, argv) #define NUITKA_INIT_PROGRAM_LATE(module_name) #endif #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/python_pgo.h0000600000372100037210000000333114166627112030136 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_PYTHON_PGO_H__ #define __NUITKA_PYTHON_PGO_H__ // In Visual Code, evaluate the code for PGO so we see errors of it sooner. #ifdef __IDE_ONLY__ #define _NUITKA_PGO_PYTHON 1 #include "nuitka/prelude.h" #endif #if _NUITKA_PGO_PYTHON // Initialize PGO data collection. extern void PGO_Initialize(); // At end of program, write tables. extern void PGO_Finalize(); // When a module is entered. extern void PGO_onModuleEntered(char const *module_name); // When a module is exited. extern void PGO_onModuleExit(char const *module_name, bool had_error); extern void PGO_onProbePassed(char const *module_name, char const *probe_id, uint32_t probe_arg); extern void PGO_onTechnicalModule(char const *module_name); #else #define PGO_Initialize() #define PGO_Finalize() #define PGO_onModuleEntered(module_name) ; #define PGO_onModuleExit(module_name, had_error) ; #define PGO_onProbePassed(module_name, probe_id, probe_arg) ; #endif #endifNuitka-0.6.19.1/nuitka/build/include/nuitka/incbin.h0000600000372100037210000003126314166627112027217 0ustar nuitka-buildslavenuitka-buildslave00000000000000/** This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to * @file incbin.h * @author Dale Weiler * @brief Utility for including binary files * * Facilities for including binary files into the current translation unit and * making use from them externally in other translation units. */ #ifndef INCBIN_HDR #define INCBIN_HDR #include #if defined(__AVX512BW__) || \ defined(__AVX512CD__) || \ defined(__AVX512DQ__) || \ defined(__AVX512ER__) || \ defined(__AVX512PF__) || \ defined(__AVX512VL__) || \ defined(__AVX512F__) # define INCBIN_ALIGNMENT_INDEX 6 #elif defined(__AVX__) || \ defined(__AVX2__) # define INCBIN_ALIGNMENT_INDEX 5 #elif defined(__SSE__) || \ defined(__SSE2__) || \ defined(__SSE3__) || \ defined(__SSSE3__) || \ defined(__SSE4_1__) || \ defined(__SSE4_2__) || \ defined(__neon__) # define INCBIN_ALIGNMENT_INDEX 4 #elif ULONG_MAX != 0xffffffffu # define INCBIN_ALIGNMENT_INDEX 3 # else # define INCBIN_ALIGNMENT_INDEX 2 #endif /* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */ #define INCBIN_ALIGN_SHIFT_0 1 #define INCBIN_ALIGN_SHIFT_1 2 #define INCBIN_ALIGN_SHIFT_2 4 #define INCBIN_ALIGN_SHIFT_3 8 #define INCBIN_ALIGN_SHIFT_4 16 #define INCBIN_ALIGN_SHIFT_5 32 #define INCBIN_ALIGN_SHIFT_6 64 /* Actual alignment value */ #define INCBIN_ALIGNMENT \ INCBIN_CONCATENATE( \ INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \ INCBIN_ALIGNMENT_INDEX) /* Stringize */ #define INCBIN_STR(X) \ #X #define INCBIN_STRINGIZE(X) \ INCBIN_STR(X) /* Concatenate */ #define INCBIN_CAT(X, Y) \ X ## Y #define INCBIN_CONCATENATE(X, Y) \ INCBIN_CAT(X, Y) /* Deferred macro expansion */ #define INCBIN_EVAL(X) \ X #define INCBIN_INVOKE(N, ...) \ INCBIN_EVAL(N(__VA_ARGS__)) /* Green Hills uses a different directive for including binary data */ #if defined(__ghs__) # if (__ghs_asm == 2) # define INCBIN_MACRO ".file" /* Or consider the ".myrawdata" entry in the ld file */ # else # define INCBIN_MACRO "\tINCBIN" # endif #else # define INCBIN_MACRO ".incbin" #endif #ifndef _MSC_VER # define INCBIN_ALIGN \ __attribute__((aligned(INCBIN_ALIGNMENT))) #else # define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT)) #endif #if defined(__arm__) || /* GNU C and RealView */ \ defined(__arm) || /* Diab */ \ defined(_ARM) /* ImageCraft */ # define INCBIN_ARM #endif #ifdef __GNUC__ /* Utilize .balign where supported */ # define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n" # define INCBIN_ALIGN_BYTE ".balign 1\n" #elif defined(INCBIN_ARM) /* * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is * the shift count. This is the value passed to `.align' */ # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n" # define INCBIN_ALIGN_BYTE ".align 0\n" #else /* We assume other inline assembler's treat `.align' as `.balign' */ # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n" # define INCBIN_ALIGN_BYTE ".align 1\n" #endif /* INCBIN_CONST is used by incbin.c generated files */ #if defined(__cplusplus) # define INCBIN_EXTERNAL extern "C" # define INCBIN_CONST extern const #else # define INCBIN_EXTERNAL extern # define INCBIN_CONST const #endif /** * @brief Optionally override the linker section into which data is emitted. * * @warning If you use this facility, you'll have to deal with platform-specific linker output * section naming on your own * * Overriding the default linker output section, e.g for esp8266/Arduino: * @code * #define INCBIN_OUTPUT_SECTION ".irom.text" * #include "incbin.h" * INCBIN(Foo, "foo.txt"); * // Data is emitted into program memory that never gets copied to RAM * @endcode */ #if !defined(INCBIN_OUTPUT_SECTION) # if defined(__APPLE__) # define INCBIN_OUTPUT_SECTION ".const_data" # else # define INCBIN_OUTPUT_SECTION ".rodata" # endif #endif #if defined(__APPLE__) /* The directives are different for Apple branded compilers */ # define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n" # ifndef INCBIN_LOCAL # define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n" # else # define INCBIN_GLOBAL(NAME) # endif # define INCBIN_INT ".long " # define INCBIN_MANGLE "_" # define INCBIN_BYTE ".byte " # define INCBIN_TYPE(...) #else # define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n" # ifndef INCBIN_LOCAL # define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n" # else # define INCBIN_GLOBAL(NAME) # endif # if defined(__ghs__) # define INCBIN_INT ".word " # else # define INCBIN_INT ".int " # endif # if defined(__USER_LABEL_PREFIX__) # define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__) # else # define INCBIN_MANGLE "" # endif # if defined(INCBIN_ARM) /* On arm assemblers, `@' is used as a line comment token */ # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n" # elif defined(__MINGW32__) || defined(__MINGW64__) /* Mingw doesn't support this directive either */ # define INCBIN_TYPE(NAME) # else /* It's safe to use `@' on other architectures */ # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n" # endif # define INCBIN_BYTE ".byte " #endif /* List of style types used for symbol names */ #define INCBIN_STYLE_CAMEL 0 #define INCBIN_STYLE_SNAKE 1 /** * @brief Specify the prefix to use for symbol names. * * By default this is `g', producing symbols of the form: * @code * #include "incbin.h" * INCBIN(Foo, "foo.txt"); * * // Now you have the following symbols: * // const unsigned char gFooData[]; * // const unsigned char *const gFooEnd; * // const unsigned int gFooSize; * @endcode * * If however you specify a prefix before including: e.g: * @code * #define INCBIN_PREFIX incbin * #include "incbin.h" * INCBIN(Foo, "foo.txt"); * * // Now you have the following symbols instead: * // const unsigned char incbinFooData[]; * // const unsigned char *const incbinFooEnd; * // const unsigned int incbinFooSize; * @endcode */ #if !defined(INCBIN_PREFIX) # define INCBIN_PREFIX g #endif /** * @brief Specify the style used for symbol names. * * Possible options are * - INCBIN_STYLE_CAMEL "CamelCase" * - INCBIN_STYLE_SNAKE "snake_case" * * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form: * @code * #include "incbin.h" * INCBIN(Foo, "foo.txt"); * * // Now you have the following symbols: * // const unsigned char FooData[]; * // const unsigned char *const FooEnd; * // const unsigned int FooSize; * @endcode * * If however you specify a style before including: e.g: * @code * #define INCBIN_STYLE INCBIN_STYLE_SNAKE * #include "incbin.h" * INCBIN(foo, "foo.txt"); * * // Now you have the following symbols: * // const unsigned char foo_data[]; * // const unsigned char *const foo_end; * // const unsigned int foo_size; * @endcode */ #if !defined(INCBIN_STYLE) # define INCBIN_STYLE INCBIN_STYLE_CAMEL #endif /* Style lookup tables */ #define INCBIN_STYLE_0_DATA Data #define INCBIN_STYLE_0_END End #define INCBIN_STYLE_0_SIZE Size #define INCBIN_STYLE_1_DATA _data #define INCBIN_STYLE_1_END _end #define INCBIN_STYLE_1_SIZE _size /* Style lookup: returning identifier */ #define INCBIN_STYLE_IDENT(TYPE) \ INCBIN_CONCATENATE( \ INCBIN_STYLE_, \ INCBIN_CONCATENATE( \ INCBIN_EVAL(INCBIN_STYLE), \ INCBIN_CONCATENATE(_, TYPE))) /* Style lookup: returning string literal */ #define INCBIN_STYLE_STRING(TYPE) \ INCBIN_STRINGIZE( \ INCBIN_STYLE_IDENT(TYPE)) \ /* Generate the global labels by indirectly invoking the macro with our style * type and concatenating the name against them. */ #define INCBIN_GLOBAL_LABELS(NAME, TYPE) \ INCBIN_INVOKE( \ INCBIN_GLOBAL, \ INCBIN_CONCATENATE( \ NAME, \ INCBIN_INVOKE( \ INCBIN_STYLE_IDENT, \ TYPE))) \ INCBIN_INVOKE( \ INCBIN_TYPE, \ INCBIN_CONCATENATE( \ NAME, \ INCBIN_INVOKE( \ INCBIN_STYLE_IDENT, \ TYPE))) /** * @brief Externally reference binary data included in another translation unit. * * Produces three external symbols that reference the binary data included in * another translation unit. * * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with * "Data", as well as "End" and "Size" after. An example is provided below. * * @param NAME The name given for the binary data * * @code * INCBIN_EXTERN(Foo); * * // Now you have the following symbols: * // extern const unsigned char FooData[]; * // extern const unsigned char *const FooEnd; * // extern const unsigned int FooSize; * @endcode */ #define INCBIN_EXTERN(NAME) \ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \ INCBIN_CONCATENATE( \ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \ INCBIN_STYLE_IDENT(DATA))[]; \ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \ INCBIN_CONCATENATE( \ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \ INCBIN_STYLE_IDENT(END)); \ INCBIN_EXTERNAL const unsigned int \ INCBIN_CONCATENATE( \ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \ INCBIN_STYLE_IDENT(SIZE)) /** * @brief Include a binary file into the current translation unit. * * Includes a binary file into the current translation unit, producing three symbols * for objects that encode the data and size respectively. * * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with * "Data", as well as "End" and "Size" after. An example is provided below. * * @param NAME The name to associate with this binary data (as an identifier.) * @param FILENAME The file to include (as a string literal.) * * @code * INCBIN(Icon, "icon.png"); * * // Now you have the following symbols: * // const unsigned char IconData[]; * // const unsigned char *const IconEnd; * // const unsigned int IconSize; * @endcode * * @warning This must be used in global scope * @warning The identifiers may be different if INCBIN_STYLE is not default * * To externally reference the data included by this in another translation unit * please @see INCBIN_EXTERN. */ #ifdef _MSC_VER #define INCBIN(NAME, FILENAME) \ INCBIN_EXTERN(NAME) #else #define INCBIN(NAME, FILENAME) \ __asm__(INCBIN_SECTION \ INCBIN_GLOBAL_LABELS(NAME, DATA) \ INCBIN_ALIGN_HOST \ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \ INCBIN_MACRO " \"" FILENAME "\"\n" \ INCBIN_GLOBAL_LABELS(NAME, END) \ INCBIN_ALIGN_BYTE \ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \ INCBIN_BYTE "1\n" \ INCBIN_GLOBAL_LABELS(NAME, SIZE) \ INCBIN_ALIGN_HOST \ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \ INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \ INCBIN_ALIGN_HOST \ ".text\n" \ ); \ INCBIN_EXTERN(NAME) #endif #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/compiled_function.h0000600000372100037210000001347114166627112031457 0ustar nuitka-buildslavenuitka-buildslave00000000000000// Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com // // Part of "Nuitka", an optimizing Python compiler that is compatible and // integrates with CPython, but also works on its own. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef __NUITKA_COMPILED_FUNCTION_H__ #define __NUITKA_COMPILED_FUNCTION_H__ #include "Python.h" #include "frameobject.h" // Compiled function type. // The backbone of the integration into CPython. Try to behave as well as normal // functions and built-in functions, or even better. struct Nuitka_FunctionObject; // The actual function code with arguments as an array. typedef PyObject *(*function_impl_code)(struct Nuitka_FunctionObject const *, PyObject **); // The Nuitka_FunctionObject is the storage associated with a compiled function // instance of which there can be many for each code. struct Nuitka_FunctionObject { /* Python object folklore: */ PyObject_VAR_HEAD PyObject *m_name; PyObject *m_module; PyObject *m_doc; PyCodeObject *m_code_object; Py_ssize_t m_args_overall_count; Py_ssize_t m_args_positional_count; Py_ssize_t m_args_keywords_count; bool m_args_simple; Py_ssize_t m_args_star_list_index; Py_ssize_t m_args_star_dict_index; #if PYTHON_VERSION >= 0x380 Py_ssize_t m_args_pos_only_count; #endif // Same as code_object->co_varnames PyObject **m_varnames; // C implementation of the function function_impl_code m_c_code; #if PYTHON_VERSION >= 0x380 vectorcallfunc m_vectorcall; #endif PyObject *m_dict; PyObject *m_weakrefs; // Tuple of defaults, for use in __defaults__ and parameter parsing. PyObject *m_defaults; Py_ssize_t m_defaults_given; #if PYTHON_VERSION >= 0x300 // List of keyword only defaults, for use in __kwdefaults__ and parameter // parsing. PyObject *m_kwdefaults; // Annotations to the function arguments and return value. PyObject *m_annotations; #endif #if PYTHON_VERSION >= 0x300 PyObject *m_qualname; #endif // Constant return value to use. PyObject *m_constant_return_value; // A kind of uuid for the function object, used in comparisons. long m_counter; // Closure taken objects, for use in __closure__ and for accessing it. Py_ssize_t m_closure_given; struct Nuitka_CellObject *m_closure[1]; }; extern PyTypeObject Nuitka_Function_Type; // Make a function with context. #if PYTHON_VERSION < 0x300 extern struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name, PyCodeObject *code_object, PyObject *defaults, PyObject *module, PyObject *doc, struct Nuitka_CellObject **closure, Py_ssize_t closure_given); #else extern struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name, PyObject *qualname, PyCodeObject *code_object, PyObject *defaults, PyObject *kwdefaults, PyObject *annotations, PyObject *module, PyObject *doc, struct Nuitka_CellObject **closure, Py_ssize_t closure_given); #endif extern void Nuitka_Function_EnableConstReturnTrue(struct Nuitka_FunctionObject *function); extern void Nuitka_Function_EnableConstReturnFalse(struct Nuitka_FunctionObject *function); extern void Nuitka_Function_EnableConstReturnGeneric(struct Nuitka_FunctionObject *function, PyObject *value); static inline bool Nuitka_Function_Check(PyObject *object) { return Py_TYPE(object) == &Nuitka_Function_Type; } static inline PyObject *Nuitka_Function_GetName(PyObject *object) { return ((struct Nuitka_FunctionObject *)object)->m_name; } PyObject *Nuitka_CallFunctionNoArgs(struct Nuitka_FunctionObject const *function); PyObject *Nuitka_CallFunctionPosArgs(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size); PyObject *Nuitka_CallFunctionVectorcall(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_names, Py_ssize_t kw_size); PyObject *Nuitka_CallFunctionPosArgsKwArgs(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *kw); PyObject *Nuitka_CallFunctionPosArgsKwSplit(struct Nuitka_FunctionObject const *function, PyObject *const *args, Py_ssize_t args_size, PyObject *const *kw_values, PyObject *kw_names); PyObject *Nuitka_CallMethodFunctionNoArgs(struct Nuitka_FunctionObject const *function, PyObject *object); PyObject *Nuitka_CallMethodFunctionPosArgs(struct Nuitka_FunctionObject const *function, PyObject *object, PyObject *const *args, Py_ssize_t args_size); PyObject *Nuitka_CallMethodFunctionPosArgsKwArgs(struct Nuitka_FunctionObject const *function, PyObject *object, PyObject *const *args, Py_ssize_t args_size, PyObject *kw); #endif Nuitka-0.6.19.1/nuitka/build/include/nuitka/hedley.h0000600000372100037210000025046614166627112027237 0ustar nuitka-buildslavenuitka-buildslave00000000000000/* Hedley - https://nemequ.github.io/hedley * Created by Evan Nemerson * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to * the public domain worldwide. This software is distributed without * any warranty. * * For details, see . * SPDX-License-Identifier: CC0-1.0 */ #if !defined(HEDLEY_VERSION) || (HEDLEY_VERSION < 14) #if defined(HEDLEY_VERSION) #undef HEDLEY_VERSION #endif #define HEDLEY_VERSION 14 #if defined(HEDLEY_STRINGIFY_EX) #undef HEDLEY_STRINGIFY_EX #endif #define HEDLEY_STRINGIFY_EX(x) #x #if defined(HEDLEY_STRINGIFY) #undef HEDLEY_STRINGIFY #endif #define HEDLEY_STRINGIFY(x) HEDLEY_STRINGIFY_EX(x) #if defined(HEDLEY_CONCAT_EX) #undef HEDLEY_CONCAT_EX #endif #define HEDLEY_CONCAT_EX(a, b) a##b #if defined(HEDLEY_CONCAT) #undef HEDLEY_CONCAT #endif #define HEDLEY_CONCAT(a, b) HEDLEY_CONCAT_EX(a, b) #if defined(HEDLEY_CONCAT3_EX) #undef HEDLEY_CONCAT3_EX #endif #define HEDLEY_CONCAT3_EX(a, b, c) a##b##c #if defined(HEDLEY_CONCAT3) #undef HEDLEY_CONCAT3 #endif #define HEDLEY_CONCAT3(a, b, c) HEDLEY_CONCAT3_EX(a, b, c) #if defined(HEDLEY_VERSION_ENCODE) #undef HEDLEY_VERSION_ENCODE #endif #define HEDLEY_VERSION_ENCODE(major, minor, revision) (((major)*1000000) + ((minor)*1000) + (revision)) #if defined(HEDLEY_VERSION_DECODE_MAJOR) #undef HEDLEY_VERSION_DECODE_MAJOR #endif #define HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) #if defined(HEDLEY_VERSION_DECODE_MINOR) #undef HEDLEY_VERSION_DECODE_MINOR #endif #define HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) #if defined(HEDLEY_VERSION_DECODE_REVISION) #undef HEDLEY_VERSION_DECODE_REVISION #endif #define HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) #if defined(HEDLEY_GNUC_VERSION) #undef HEDLEY_GNUC_VERSION #endif #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) #define HEDLEY_GNUC_VERSION HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #elif defined(__GNUC__) #define HEDLEY_GNUC_VERSION HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) #endif #if defined(HEDLEY_GNUC_VERSION_CHECK) #undef HEDLEY_GNUC_VERSION_CHECK #endif #if defined(HEDLEY_GNUC_VERSION) #define HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) \ (HEDLEY_GNUC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_MSVC_VERSION) #undef HEDLEY_MSVC_VERSION #endif #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) #define HEDLEY_MSVC_VERSION \ HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) #elif defined(_MSC_FULL_VER) && !defined(__ICL) #define HEDLEY_MSVC_VERSION \ HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) #elif defined(_MSC_VER) && !defined(__ICL) #define HEDLEY_MSVC_VERSION HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) #endif #if defined(HEDLEY_MSVC_VERSION_CHECK) #undef HEDLEY_MSVC_VERSION_CHECK #endif #if !defined(HEDLEY_MSVC_VERSION) #define HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (0) #elif defined(_MSC_VER) && (_MSC_VER >= 1400) #define HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \ (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) #elif defined(_MSC_VER) && (_MSC_VER >= 1200) #define HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \ (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) #else #define HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (_MSC_VER >= ((major * 100) + (minor))) #endif #if defined(HEDLEY_INTEL_VERSION) #undef HEDLEY_INTEL_VERSION #endif #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) #define HEDLEY_INTEL_VERSION \ HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) #elif defined(__INTEL_COMPILER) && !defined(__ICL) #define HEDLEY_INTEL_VERSION HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) #endif #if defined(HEDLEY_INTEL_VERSION_CHECK) #undef HEDLEY_INTEL_VERSION_CHECK #endif #if defined(HEDLEY_INTEL_VERSION) #define HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) \ (HEDLEY_INTEL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_INTEL_CL_VERSION) #undef HEDLEY_INTEL_CL_VERSION #endif #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) #define HEDLEY_INTEL_CL_VERSION HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) #endif #if defined(HEDLEY_INTEL_CL_VERSION_CHECK) #undef HEDLEY_INTEL_CL_VERSION_CHECK #endif #if defined(HEDLEY_INTEL_CL_VERSION) #define HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) \ (HEDLEY_INTEL_CL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_PGI_VERSION) #undef HEDLEY_PGI_VERSION #endif #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) #define HEDLEY_PGI_VERSION HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) #endif #if defined(HEDLEY_PGI_VERSION_CHECK) #undef HEDLEY_PGI_VERSION_CHECK #endif #if defined(HEDLEY_PGI_VERSION) #define HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (HEDLEY_PGI_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_SUNPRO_VERSION) #undef HEDLEY_SUNPRO_VERSION #endif #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) #define HEDLEY_SUNPRO_VERSION \ HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \ (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) #elif defined(__SUNPRO_C) #define HEDLEY_SUNPRO_VERSION HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C)&0xf) #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) #define HEDLEY_SUNPRO_VERSION \ HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \ (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) #elif defined(__SUNPRO_CC) #define HEDLEY_SUNPRO_VERSION \ HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC)&0xf) #endif #if defined(HEDLEY_SUNPRO_VERSION_CHECK) #undef HEDLEY_SUNPRO_VERSION_CHECK #endif #if defined(HEDLEY_SUNPRO_VERSION) #define HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) \ (HEDLEY_SUNPRO_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_EMSCRIPTEN_VERSION) #undef HEDLEY_EMSCRIPTEN_VERSION #endif #if defined(__EMSCRIPTEN__) #define HEDLEY_EMSCRIPTEN_VERSION HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) #endif #if defined(HEDLEY_EMSCRIPTEN_VERSION_CHECK) #undef HEDLEY_EMSCRIPTEN_VERSION_CHECK #endif #if defined(HEDLEY_EMSCRIPTEN_VERSION) #define HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) \ (HEDLEY_EMSCRIPTEN_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_ARM_VERSION) #undef HEDLEY_ARM_VERSION #endif #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) #define HEDLEY_ARM_VERSION \ HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, \ (__ARMCOMPILER_VERSION % 10000) / 100) #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) #define HEDLEY_ARM_VERSION \ HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, \ (__ARMCC_VERSION % 10000) / 100) #endif #if defined(HEDLEY_ARM_VERSION_CHECK) #undef HEDLEY_ARM_VERSION_CHECK #endif #if defined(HEDLEY_ARM_VERSION) #define HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (HEDLEY_ARM_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_IBM_VERSION) #undef HEDLEY_IBM_VERSION #endif #if defined(__ibmxl__) #define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) #elif defined(__xlC__) && defined(__xlC_ver__) #define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) #elif defined(__xlC__) #define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) #endif #if defined(HEDLEY_IBM_VERSION_CHECK) #undef HEDLEY_IBM_VERSION_CHECK #endif #if defined(HEDLEY_IBM_VERSION) #define HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (HEDLEY_IBM_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_VERSION) #undef HEDLEY_TI_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && \ (defined(__TMS470__) || defined(__TI_ARM__) || defined(__MSP430__) || defined(__TMS320C2000__)) #if (__TI_COMPILER_VERSION__ >= 16000000) #define HEDLEY_TI_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #endif #if defined(HEDLEY_TI_VERSION_CHECK) #undef HEDLEY_TI_VERSION_CHECK #endif #if defined(HEDLEY_TI_VERSION) #define HEDLEY_TI_VERSION_CHECK(major, minor, patch) (HEDLEY_TI_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_CL2000_VERSION) #undef HEDLEY_TI_CL2000_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) #define HEDLEY_TI_CL2000_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_CL2000_VERSION_CHECK) #undef HEDLEY_TI_CL2000_VERSION_CHECK #endif #if defined(HEDLEY_TI_CL2000_VERSION) #define HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_CL2000_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_CL430_VERSION) #undef HEDLEY_TI_CL430_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) #define HEDLEY_TI_CL430_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_CL430_VERSION_CHECK) #undef HEDLEY_TI_CL430_VERSION_CHECK #endif #if defined(HEDLEY_TI_CL430_VERSION) #define HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_CL430_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_ARMCL_VERSION) #undef HEDLEY_TI_ARMCL_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) #define HEDLEY_TI_ARMCL_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_ARMCL_VERSION_CHECK) #undef HEDLEY_TI_ARMCL_VERSION_CHECK #endif #if defined(HEDLEY_TI_ARMCL_VERSION) #define HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_ARMCL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_CL6X_VERSION) #undef HEDLEY_TI_CL6X_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) #define HEDLEY_TI_CL6X_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_CL6X_VERSION_CHECK) #undef HEDLEY_TI_CL6X_VERSION_CHECK #endif #if defined(HEDLEY_TI_CL6X_VERSION) #define HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_CL6X_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_CL7X_VERSION) #undef HEDLEY_TI_CL7X_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) #define HEDLEY_TI_CL7X_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_CL7X_VERSION_CHECK) #undef HEDLEY_TI_CL7X_VERSION_CHECK #endif #if defined(HEDLEY_TI_CL7X_VERSION) #define HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_CL7X_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TI_CLPRU_VERSION) #undef HEDLEY_TI_CLPRU_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) #define HEDLEY_TI_CLPRU_VERSION \ HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(HEDLEY_TI_CLPRU_VERSION_CHECK) #undef HEDLEY_TI_CLPRU_VERSION_CHECK #endif #if defined(HEDLEY_TI_CLPRU_VERSION) #define HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TI_CLPRU_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_CRAY_VERSION) #undef HEDLEY_CRAY_VERSION #endif #if defined(_CRAYC) #if defined(_RELEASE_PATCHLEVEL) #define HEDLEY_CRAY_VERSION HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) #else #define HEDLEY_CRAY_VERSION HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) #endif #endif #if defined(HEDLEY_CRAY_VERSION_CHECK) #undef HEDLEY_CRAY_VERSION_CHECK #endif #if defined(HEDLEY_CRAY_VERSION) #define HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) \ (HEDLEY_CRAY_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_IAR_VERSION) #undef HEDLEY_IAR_VERSION #endif #if defined(__IAR_SYSTEMS_ICC__) #if __VER__ > 1000 #define HEDLEY_IAR_VERSION HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) #else #define HEDLEY_IAR_VERSION HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) #endif #endif #if defined(HEDLEY_IAR_VERSION_CHECK) #undef HEDLEY_IAR_VERSION_CHECK #endif #if defined(HEDLEY_IAR_VERSION) #define HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (HEDLEY_IAR_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_TINYC_VERSION) #undef HEDLEY_TINYC_VERSION #endif #if defined(__TINYC__) #define HEDLEY_TINYC_VERSION HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) #endif #if defined(HEDLEY_TINYC_VERSION_CHECK) #undef HEDLEY_TINYC_VERSION_CHECK #endif #if defined(HEDLEY_TINYC_VERSION) #define HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) \ (HEDLEY_TINYC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_DMC_VERSION) #undef HEDLEY_DMC_VERSION #endif #if defined(__DMC__) #define HEDLEY_DMC_VERSION HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) #endif #if defined(HEDLEY_DMC_VERSION_CHECK) #undef HEDLEY_DMC_VERSION_CHECK #endif #if defined(HEDLEY_DMC_VERSION) #define HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (HEDLEY_DMC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_COMPCERT_VERSION) #undef HEDLEY_COMPCERT_VERSION #endif #if defined(__COMPCERT_VERSION__) #define HEDLEY_COMPCERT_VERSION \ HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) #endif #if defined(HEDLEY_COMPCERT_VERSION_CHECK) #undef HEDLEY_COMPCERT_VERSION_CHECK #endif #if defined(HEDLEY_COMPCERT_VERSION) #define HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) \ (HEDLEY_COMPCERT_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_PELLES_VERSION) #undef HEDLEY_PELLES_VERSION #endif #if defined(__POCC__) #define HEDLEY_PELLES_VERSION HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) #endif #if defined(HEDLEY_PELLES_VERSION_CHECK) #undef HEDLEY_PELLES_VERSION_CHECK #endif #if defined(HEDLEY_PELLES_VERSION) #define HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) \ (HEDLEY_PELLES_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_GCC_VERSION) #undef HEDLEY_GCC_VERSION #endif #if defined(HEDLEY_GNUC_VERSION) && !defined(__clang__) && !defined(HEDLEY_INTEL_VERSION) && \ !defined(HEDLEY_PGI_VERSION) && !defined(HEDLEY_ARM_VERSION) && !defined(HEDLEY_TI_VERSION) && \ !defined(HEDLEY_TI_ARMCL_VERSION) && !defined(HEDLEY_TI_CL430_VERSION) && !defined(HEDLEY_TI_CL2000_VERSION) && \ !defined(HEDLEY_TI_CL6X_VERSION) && !defined(HEDLEY_TI_CL7X_VERSION) && !defined(HEDLEY_TI_CLPRU_VERSION) && \ !defined(__COMPCERT__) #define HEDLEY_GCC_VERSION HEDLEY_GNUC_VERSION #endif #if defined(HEDLEY_GCC_VERSION_CHECK) #undef HEDLEY_GCC_VERSION_CHECK #endif #if defined(HEDLEY_GCC_VERSION) #define HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (HEDLEY_GCC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) #else #define HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(HEDLEY_HAS_ATTRIBUTE) #undef HEDLEY_HAS_ATTRIBUTE #endif #if defined(__has_attribute) #define HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) #else #define HEDLEY_HAS_ATTRIBUTE(attribute) (0) #endif #if defined(HEDLEY_GNUC_HAS_ATTRIBUTE) #undef HEDLEY_GNUC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) #define HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) __has_attribute(attribute) #else #define HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_ATTRIBUTE) #undef HEDLEY_GCC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) #define HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) __has_attribute(attribute) #else #define HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_CPP_ATTRIBUTE) #undef HEDLEY_HAS_CPP_ATTRIBUTE #endif #if defined(__has_cpp_attribute) && defined(__cplusplus) && \ (!defined(HEDLEY_SUNPRO_VERSION) || HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) #define HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) #else #define HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) #endif #if defined(HEDLEY_HAS_CPP_ATTRIBUTE_NS) #undef HEDLEY_HAS_CPP_ATTRIBUTE_NS #endif #if !defined(__cplusplus) || !defined(__has_cpp_attribute) #define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0) #elif !defined(HEDLEY_PGI_VERSION) && !defined(HEDLEY_IAR_VERSION) && \ (!defined(HEDLEY_SUNPRO_VERSION) || HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) && \ (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19, 20, 0)) #define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) #else #define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0) #endif #if defined(HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) #undef HEDLEY_GNUC_HAS_CPP_ATTRIBUTE #endif #if defined(__has_cpp_attribute) && defined(__cplusplus) #define HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute) #else #define HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_CPP_ATTRIBUTE) #undef HEDLEY_GCC_HAS_CPP_ATTRIBUTE #endif #if defined(__has_cpp_attribute) && defined(__cplusplus) #define HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute) #else #define HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_BUILTIN) #undef HEDLEY_HAS_BUILTIN #endif #if defined(__has_builtin) #define HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) #else #define HEDLEY_HAS_BUILTIN(builtin) (0) #endif #if defined(HEDLEY_GNUC_HAS_BUILTIN) #undef HEDLEY_GNUC_HAS_BUILTIN #endif #if defined(__has_builtin) #define HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin) #else #define HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_BUILTIN) #undef HEDLEY_GCC_HAS_BUILTIN #endif #if defined(__has_builtin) #define HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin) #else #define HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_FEATURE) #undef HEDLEY_HAS_FEATURE #endif #if defined(__has_feature) #define HEDLEY_HAS_FEATURE(feature) __has_feature(feature) #else #define HEDLEY_HAS_FEATURE(feature) (0) #endif #if defined(HEDLEY_GNUC_HAS_FEATURE) #undef HEDLEY_GNUC_HAS_FEATURE #endif #if defined(__has_feature) #define HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature) #else #define HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_FEATURE) #undef HEDLEY_GCC_HAS_FEATURE #endif #if defined(__has_feature) #define HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature) #else #define HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_EXTENSION) #undef HEDLEY_HAS_EXTENSION #endif #if defined(__has_extension) #define HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) #else #define HEDLEY_HAS_EXTENSION(extension) (0) #endif #if defined(HEDLEY_GNUC_HAS_EXTENSION) #undef HEDLEY_GNUC_HAS_EXTENSION #endif #if defined(__has_extension) #define HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension) #else #define HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_EXTENSION) #undef HEDLEY_GCC_HAS_EXTENSION #endif #if defined(__has_extension) #define HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension) #else #define HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_DECLSPEC_ATTRIBUTE) #undef HEDLEY_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) #define HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) #else #define HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) #endif #if defined(HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) #undef HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) #define HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) __has_declspec_attribute(attribute) #else #define HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \ HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) #undef HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) #define HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) __has_declspec_attribute(attribute) #else #define HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_HAS_WARNING) #undef HEDLEY_HAS_WARNING #endif #if defined(__has_warning) #define HEDLEY_HAS_WARNING(warning) __has_warning(warning) #else #define HEDLEY_HAS_WARNING(warning) (0) #endif #if defined(HEDLEY_GNUC_HAS_WARNING) #undef HEDLEY_GNUC_HAS_WARNING #endif #if defined(__has_warning) #define HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning) #else #define HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_GCC_HAS_WARNING) #undef HEDLEY_GCC_HAS_WARNING #endif #if defined(__has_warning) #define HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning) #else #define HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__clang__) || \ HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || \ HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(7, 0, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) || HEDLEY_TINYC_VERSION_CHECK(0, 9, 17) || \ HEDLEY_SUNPRO_VERSION_CHECK(8, 0, 0) || (HEDLEY_IBM_VERSION_CHECK(10, 1, 0) && defined(__C99_PRAGMA_OPERATOR)) #define HEDLEY_PRAGMA(value) _Pragma(#value) #elif HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) #define HEDLEY_PRAGMA(value) __pragma(value) #else #define HEDLEY_PRAGMA(value) #endif #if defined(HEDLEY_DIAGNOSTIC_PUSH) #undef HEDLEY_DIAGNOSTIC_PUSH #endif #if defined(HEDLEY_DIAGNOSTIC_POP) #undef HEDLEY_DIAGNOSTIC_POP #endif #if defined(__clang__) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") #define HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") #define HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") #elif HEDLEY_GCC_VERSION_CHECK(4, 6, 0) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") #define HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") #elif HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) #define HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) #elif HEDLEY_ARM_VERSION_CHECK(5, 6, 0) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") #define HEDLEY_DIAGNOSTIC_POP _Pragma("pop") #elif HEDLEY_TI_VERSION_CHECK(15, 12, 0) || HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 4, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") #define HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") #elif HEDLEY_PELLES_VERSION_CHECK(2, 90, 0) #define HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") #define HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") #else #define HEDLEY_DIAGNOSTIC_PUSH #define HEDLEY_DIAGNOSTIC_POP #endif /* HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ #if defined(HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) #undef HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ #endif #if defined(__cplusplus) #if HEDLEY_HAS_WARNING("-Wc++98-compat") #if HEDLEY_HAS_WARNING("-Wc++17-extensions") #if HEDLEY_HAS_WARNING("-Wc++1z-extensions") #define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") xpr HEDLEY_DIAGNOSTIC_POP #else #define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ xpr HEDLEY_DIAGNOSTIC_POP #endif #else #define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") xpr HEDLEY_DIAGNOSTIC_POP #endif #endif #endif #if !defined(HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) #define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x #endif #if defined(HEDLEY_CONST_CAST) #undef HEDLEY_CONST_CAST #endif #if defined(__cplusplus) #define HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) #elif HEDLEY_HAS_WARNING("-Wcast-qual") || HEDLEY_GCC_VERSION_CHECK(4, 6, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_CONST_CAST(T, expr) \ (__extension__({ \ HEDLEY_DIAGNOSTIC_PUSH \ HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL((T)(expr)); \ HEDLEY_DIAGNOSTIC_POP \ })) #else #define HEDLEY_CONST_CAST(T, expr) ((T)(expr)) #endif #if defined(HEDLEY_REINTERPRET_CAST) #undef HEDLEY_REINTERPRET_CAST #endif #if defined(__cplusplus) #define HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) #else #define HEDLEY_REINTERPRET_CAST(T, expr) ((T)(expr)) #endif #if defined(HEDLEY_STATIC_CAST) #undef HEDLEY_STATIC_CAST #endif #if defined(__cplusplus) #define HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) #else #define HEDLEY_STATIC_CAST(T, expr) ((T)(expr)) #endif #if defined(HEDLEY_CPP_CAST) #undef HEDLEY_CPP_CAST #endif #if defined(__cplusplus) #if HEDLEY_HAS_WARNING("-Wold-style-cast") #define HEDLEY_CPP_CAST(T, expr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wold-style-cast\"")((T)(expr)) HEDLEY_DIAGNOSTIC_POP #elif HEDLEY_IAR_VERSION_CHECK(8, 3, 0) #define HEDLEY_CPP_CAST(T, expr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("diag_suppress=Pe137") HEDLEY_DIAGNOSTIC_POP #else #define HEDLEY_CPP_CAST(T, expr) ((T)(expr)) #endif #else #define HEDLEY_CPP_CAST(T, expr) (expr) #endif #if defined(HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) #undef HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED #endif #if HEDLEY_HAS_WARNING("-Wdeprecated-declarations") #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") #elif HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 1478 1786)) #elif HEDLEY_PGI_VERSION_CHECK(20, 7, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") #elif HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") #elif HEDLEY_GCC_VERSION_CHECK(4, 3, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #elif HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 4996)) #elif HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && !defined(__cplusplus) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && defined(__cplusplus) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") #elif HEDLEY_PELLES_VERSION_CHECK(2, 90, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") #else #define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED #endif #if defined(HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) #undef HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif #if HEDLEY_HAS_WARNING("-Wunknown-pragmas") #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") #elif HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 161)) #elif HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") #elif HEDLEY_GCC_VERSION_CHECK(4, 3, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") #elif HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 4068)) #elif HEDLEY_TI_VERSION_CHECK(16, 9, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") #elif HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") #else #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif #if defined(HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) #undef HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #endif #if HEDLEY_HAS_WARNING("-Wunknown-attributes") #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") #elif HEDLEY_GCC_VERSION_CHECK(4, 6, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #elif HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") #elif HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 1292)) #elif HEDLEY_MSVC_VERSION_CHECK(19, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 5030)) #elif HEDLEY_PGI_VERSION_CHECK(20, 7, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") #elif HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") #elif HEDLEY_TI_VERSION_CHECK(18, 1, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") #else #define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #endif #if defined(HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) #undef HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif #if HEDLEY_HAS_WARNING("-Wcast-qual") #define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") #elif HEDLEY_GCC_VERSION_CHECK(3, 0, 0) #define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") #else #define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif #if defined(HEDLEY_DEPRECATED) #undef HEDLEY_DEPRECATED #endif #if defined(HEDLEY_DEPRECATED_FOR) #undef HEDLEY_DEPRECATED_FOR #endif #if HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " #since)) #define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) #elif HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) || HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ HEDLEY_TI_VERSION_CHECK(18, 1, 0) || HEDLEY_TI_ARMCL_VERSION_CHECK(18, 1, 0) || \ HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) #define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) #define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) #elif defined(__cplusplus) && (__cplusplus >= 201402L) #define HEDLEY_DEPRECATED(since) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) #define HEDLEY_DEPRECATED_FOR(since, replacement) \ HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif HEDLEY_HAS_ATTRIBUTE(deprecated) || HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) #define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) #elif HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || HEDLEY_PELLES_VERSION_CHECK(6, 50, 0) || \ HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_DEPRECATED(since) __declspec(deprecated) #define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_DEPRECATED(since) _Pragma("deprecated") #define HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") #else #define HEDLEY_DEPRECATED(since) #define HEDLEY_DEPRECATED_FOR(since, replacement) #endif #if defined(HEDLEY_UNAVAILABLE) #undef HEDLEY_UNAVAILABLE #endif #if HEDLEY_HAS_ATTRIBUTE(warning) || HEDLEY_GCC_VERSION_CHECK(4, 3, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) #else #define HEDLEY_UNAVAILABLE(available_since) #endif #if defined(HEDLEY_WARN_UNUSED_RESULT) #undef HEDLEY_WARN_UNUSED_RESULT #endif #if defined(HEDLEY_WARN_UNUSED_RESULT_MSG) #undef HEDLEY_WARN_UNUSED_RESULT_MSG #endif #if HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || (HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \ HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) #elif (HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) #define HEDLEY_WARN_UNUSED_RESULT HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) #elif HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) #define HEDLEY_WARN_UNUSED_RESULT HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif defined(_Check_return_) /* SAL */ #define HEDLEY_WARN_UNUSED_RESULT _Check_return_ #define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ #else #define HEDLEY_WARN_UNUSED_RESULT #define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) #endif #if defined(HEDLEY_SENTINEL) #undef HEDLEY_SENTINEL #endif #if HEDLEY_HAS_ATTRIBUTE(sentinel) || HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_ARM_VERSION_CHECK(5, 4, 0) #define HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) #else #define HEDLEY_SENTINEL(position) #endif #if defined(HEDLEY_NO_RETURN) #undef HEDLEY_NO_RETURN #endif #if HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_NO_RETURN __noreturn #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define HEDLEY_NO_RETURN _Noreturn #elif defined(__cplusplus) && (__cplusplus >= 201103L) #define HEDLEY_NO_RETURN HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) #elif HEDLEY_HAS_ATTRIBUTE(noreturn) || HEDLEY_GCC_VERSION_CHECK(3, 2, 0) || HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) #define HEDLEY_NO_RETURN _Pragma("does_not_return") #elif HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_NO_RETURN __declspec(noreturn) #elif HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) #define HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") #elif HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0) #define HEDLEY_NO_RETURN __attribute((noreturn)) #elif HEDLEY_PELLES_VERSION_CHECK(9, 0, 0) #define HEDLEY_NO_RETURN __declspec(noreturn) #else #define HEDLEY_NO_RETURN #endif #if defined(HEDLEY_NO_ESCAPE) #undef HEDLEY_NO_ESCAPE #endif #if HEDLEY_HAS_ATTRIBUTE(noescape) #define HEDLEY_NO_ESCAPE __attribute__((__noescape__)) #else #define HEDLEY_NO_ESCAPE #endif #if defined(HEDLEY_UNREACHABLE) #undef HEDLEY_UNREACHABLE #endif #if defined(HEDLEY_UNREACHABLE_RETURN) #undef HEDLEY_UNREACHABLE_RETURN #endif #if defined(HEDLEY_ASSUME) #undef HEDLEY_ASSUME #endif #if HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_ASSUME(expr) __assume(expr) #elif HEDLEY_HAS_BUILTIN(__builtin_assume) #define HEDLEY_ASSUME(expr) __builtin_assume(expr) #elif HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) #if defined(__cplusplus) #define HEDLEY_ASSUME(expr) std::_nassert(expr) #else #define HEDLEY_ASSUME(expr) _nassert(expr) #endif #endif #if (HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(HEDLEY_ARM_VERSION))) || \ HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || HEDLEY_PGI_VERSION_CHECK(18, 10, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_IBM_VERSION_CHECK(13, 1, 5) #define HEDLEY_UNREACHABLE() __builtin_unreachable() #elif defined(HEDLEY_ASSUME) #define HEDLEY_UNREACHABLE() HEDLEY_ASSUME(0) #endif #if !defined(HEDLEY_ASSUME) #if defined(HEDLEY_UNREACHABLE) #define HEDLEY_ASSUME(expr) HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (HEDLEY_UNREACHABLE(), 1))) #else #define HEDLEY_ASSUME(expr) HEDLEY_STATIC_CAST(void, expr) #endif #endif #if defined(HEDLEY_UNREACHABLE) #if HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) #define HEDLEY_UNREACHABLE_RETURN(value) return (HEDLEY_STATIC_CAST(void, HEDLEY_ASSUME(0)), (value)) #else #define HEDLEY_UNREACHABLE_RETURN(value) HEDLEY_UNREACHABLE() #endif #else #define HEDLEY_UNREACHABLE_RETURN(value) return (value) #endif #if !defined(HEDLEY_UNREACHABLE) #define HEDLEY_UNREACHABLE() HEDLEY_ASSUME(0) #endif HEDLEY_DIAGNOSTIC_PUSH #if HEDLEY_HAS_WARNING("-Wpedantic") #pragma clang diagnostic ignored "-Wpedantic" #endif #if HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif #if HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros", 4, 0, 0) #if defined(__clang__) #pragma clang diagnostic ignored "-Wvariadic-macros" #elif defined(HEDLEY_GCC_VERSION) #pragma GCC diagnostic ignored "-Wvariadic-macros" #endif #endif #if defined(HEDLEY_NON_NULL) #undef HEDLEY_NON_NULL #endif #if HEDLEY_HAS_ATTRIBUTE(nonnull) || HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) #define HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) #else #define HEDLEY_NON_NULL(...) #endif HEDLEY_DIAGNOSTIC_POP #if defined(HEDLEY_PRINTF_FORMAT) #undef HEDLEY_PRINTF_FORMAT #endif #if defined(__MINGW32__) && HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && !defined(__USE_MINGW_ANSI_STDIO) #define HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ __attribute__((__format__(ms_printf, string_idx, first_to_check))) #elif defined(__MINGW32__) && HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && defined(__USE_MINGW_ANSI_STDIO) #define HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ __attribute__((__format__(gnu_printf, string_idx, first_to_check))) #elif HEDLEY_HAS_ATTRIBUTE(format) || HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ __attribute__((__format__(__printf__, string_idx, first_to_check))) #elif HEDLEY_PELLES_VERSION_CHECK(6, 0, 0) #define HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) __declspec(vaformat(printf, string_idx, first_to_check)) #else #define HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) #endif #if defined(HEDLEY_CONSTEXPR) #undef HEDLEY_CONSTEXPR #endif #if defined(__cplusplus) #if __cplusplus >= 201103L #define HEDLEY_CONSTEXPR HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) #endif #endif #if !defined(HEDLEY_CONSTEXPR) #define HEDLEY_CONSTEXPR #endif #if defined(HEDLEY_PREDICT) #undef HEDLEY_PREDICT #endif #if defined(HEDLEY_LIKELY) #undef HEDLEY_LIKELY #endif #if defined(HEDLEY_UNLIKELY) #undef HEDLEY_UNLIKELY #endif #if defined(HEDLEY_UNPREDICTABLE) #undef HEDLEY_UNPREDICTABLE #endif #if HEDLEY_HAS_BUILTIN(__builtin_unpredictable) #define HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) #endif #if (HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(HEDLEY_PGI_VERSION)) || \ HEDLEY_GCC_VERSION_CHECK(9, 0, 0) #define HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability((expr), (value), (probability)) #define HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, (probability)) #define HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, (probability)) #define HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) #define HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) #elif (HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(HEDLEY_INTEL_CL_VERSION)) || \ HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ (HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ HEDLEY_TINYC_VERSION_CHECK(0, 9, 27) || HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) #define HEDLEY_PREDICT(expr, expected, probability) \ (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (HEDLEY_STATIC_CAST(void, expected), (expr))) #define HEDLEY_PREDICT_TRUE(expr, probability) \ (__extension__({ \ double hedley_probability_ = (probability); \ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) \ : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ })) #define HEDLEY_PREDICT_FALSE(expr, probability) \ (__extension__({ \ double hedley_probability_ = (probability); \ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) \ : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ })) #define HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) #define HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) #else #define HEDLEY_PREDICT(expr, expected, probability) (HEDLEY_STATIC_CAST(void, expected), (expr)) #define HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) #define HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) #define HEDLEY_LIKELY(expr) (!!(expr)) #define HEDLEY_UNLIKELY(expr) (!!(expr)) #endif #if !defined(HEDLEY_UNPREDICTABLE) #define HEDLEY_UNPREDICTABLE(expr) HEDLEY_PREDICT(expr, 1, 0.5) #endif #if defined(HEDLEY_MALLOC) #undef HEDLEY_MALLOC #endif #if HEDLEY_HAS_ATTRIBUTE(malloc) || HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_MALLOC __attribute__((__malloc__)) #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) #define HEDLEY_MALLOC _Pragma("returns_new_memory") #elif HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_MALLOC __declspec(restrict) #else #define HEDLEY_MALLOC #endif #if defined(HEDLEY_PURE) #undef HEDLEY_PURE #endif #if HEDLEY_HAS_ATTRIBUTE(pure) || HEDLEY_GCC_VERSION_CHECK(2, 96, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_PURE __attribute__((__pure__)) #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) #define HEDLEY_PURE _Pragma("does_not_write_global_data") #elif defined(__cplusplus) && (HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0)) #define HEDLEY_PURE _Pragma("FUNC_IS_PURE;") #else #define HEDLEY_PURE #endif #if defined(HEDLEY_CONST) #undef HEDLEY_CONST #endif #if HEDLEY_HAS_ATTRIBUTE(const) || HEDLEY_GCC_VERSION_CHECK(2, 5, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || HEDLEY_PGI_VERSION_CHECK(17, 10, 0) #define HEDLEY_CONST __attribute__((__const__)) #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) #define HEDLEY_CONST _Pragma("no_side_effect") #else #define HEDLEY_CONST HEDLEY_PURE #endif #if defined(HEDLEY_RESTRICT) #undef HEDLEY_RESTRICT #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) #define HEDLEY_RESTRICT restrict #elif HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 4) || \ HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ (HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) || HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || \ defined(__clang__) #define HEDLEY_RESTRICT __restrict #elif HEDLEY_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) #define HEDLEY_RESTRICT _Restrict #else #define HEDLEY_RESTRICT #endif #if defined(HEDLEY_INLINE) #undef HEDLEY_INLINE #endif #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) #define HEDLEY_INLINE inline #elif defined(HEDLEY_GCC_VERSION) || HEDLEY_ARM_VERSION_CHECK(6, 2, 0) #define HEDLEY_INLINE __inline__ #elif HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_TI_ARMCL_VERSION_CHECK(5, 1, 0) || \ HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_INLINE __inline #else #define HEDLEY_INLINE #endif #if defined(HEDLEY_ALWAYS_INLINE) #undef HEDLEY_ALWAYS_INLINE #endif #if HEDLEY_HAS_ATTRIBUTE(always_inline) || HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) HEDLEY_INLINE #elif HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_ALWAYS_INLINE __forceinline #elif defined(__cplusplus) && (HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)) #define HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") #else #define HEDLEY_ALWAYS_INLINE HEDLEY_INLINE #endif #if defined(HEDLEY_NEVER_INLINE) #undef HEDLEY_NEVER_INLINE #endif #if HEDLEY_HAS_ATTRIBUTE(noinline) || HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ (HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ (HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ (HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ (HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) #define HEDLEY_NEVER_INLINE __attribute__((__noinline__)) #elif HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_NEVER_INLINE __declspec(noinline) #elif HEDLEY_PGI_VERSION_CHECK(10, 2, 0) #define HEDLEY_NEVER_INLINE _Pragma("noinline") #elif HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) #define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_NEVER_INLINE _Pragma("inline=never") #elif HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0) #define HEDLEY_NEVER_INLINE __attribute((noinline)) #elif HEDLEY_PELLES_VERSION_CHECK(9, 0, 0) #define HEDLEY_NEVER_INLINE __declspec(noinline) #else #define HEDLEY_NEVER_INLINE #endif #if defined(HEDLEY_PRIVATE) #undef HEDLEY_PRIVATE #endif #if defined(HEDLEY_PUBLIC) #undef HEDLEY_PUBLIC #endif #if defined(HEDLEY_IMPORT) #undef HEDLEY_IMPORT #endif #if defined(_WIN32) || defined(__CYGWIN__) #define HEDLEY_PRIVATE #define HEDLEY_PUBLIC __declspec(dllexport) #define HEDLEY_IMPORT __declspec(dllimport) #else #if HEDLEY_HAS_ATTRIBUTE(visibility) || HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ (defined(__TI_EABI__) && ((HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0))) #define HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) #define HEDLEY_PUBLIC __attribute__((__visibility__("default"))) #else #define HEDLEY_PRIVATE #define HEDLEY_PUBLIC #endif #define HEDLEY_IMPORT extern #endif #if defined(HEDLEY_NO_THROW) #undef HEDLEY_NO_THROW #endif #if HEDLEY_HAS_ATTRIBUTE(nothrow) || HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_NO_THROW __attribute__((__nothrow__)) #elif HEDLEY_MSVC_VERSION_CHECK(13, 1, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) #define HEDLEY_NO_THROW __declspec(nothrow) #else #define HEDLEY_NO_THROW #endif #if defined(HEDLEY_FALL_THROUGH) #undef HEDLEY_FALL_THROUGH #endif #if HEDLEY_HAS_ATTRIBUTE(fallthrough) || HEDLEY_GCC_VERSION_CHECK(7, 0, 0) #define HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) #elif HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang, fallthrough) #define HEDLEY_FALL_THROUGH HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) #elif HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) #define HEDLEY_FALL_THROUGH HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) #elif defined(__fallthrough) /* SAL */ #define HEDLEY_FALL_THROUGH __fallthrough #else #define HEDLEY_FALL_THROUGH #endif #if defined(HEDLEY_RETURNS_NON_NULL) #undef HEDLEY_RETURNS_NON_NULL #endif #if HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || HEDLEY_GCC_VERSION_CHECK(4, 9, 0) #define HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) #elif defined(_Ret_notnull_) /* SAL */ #define HEDLEY_RETURNS_NON_NULL _Ret_notnull_ #else #define HEDLEY_RETURNS_NON_NULL #endif #if defined(HEDLEY_ARRAY_PARAM) #undef HEDLEY_ARRAY_PARAM #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__STDC_NO_VLA__) && \ !defined(__cplusplus) && !defined(HEDLEY_PGI_VERSION) && !defined(HEDLEY_TINYC_VERSION) #define HEDLEY_ARRAY_PARAM(name) (name) #else #define HEDLEY_ARRAY_PARAM(name) #endif #if defined(HEDLEY_IS_CONSTANT) #undef HEDLEY_IS_CONSTANT #endif #if defined(HEDLEY_REQUIRE_CONSTEXPR) #undef HEDLEY_REQUIRE_CONSTEXPR #endif /* HEDLEY_IS_CONSTEXPR_ is for HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ #if defined(HEDLEY_IS_CONSTEXPR_) #undef HEDLEY_IS_CONSTEXPR_ #endif #if HEDLEY_HAS_BUILTIN(__builtin_constant_p) || HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_TINYC_VERSION_CHECK(0, 9, 19) || \ HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || (HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) && !defined(__cplusplus)) || \ HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) #define HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif #if !defined(__cplusplus) #if HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || HEDLEY_ARM_VERSION_CHECK(5, 4, 0) || HEDLEY_TINYC_VERSION_CHECK(0, 9, 24) #if defined(__INTPTR_TYPE__) #define HEDLEY_IS_CONSTEXPR_(expr) \ __builtin_types_compatible_p(__typeof__((1 ? (void *)((__INTPTR_TYPE__)((expr)*0)) : (int *)0)), int *) #else #include #define HEDLEY_IS_CONSTEXPR_(expr) \ __builtin_types_compatible_p(__typeof__((1 ? (void *)((intptr_t)((expr)*0)) : (int *)0)), int *) #endif #elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(HEDLEY_SUNPRO_VERSION) && \ !defined(HEDLEY_PGI_VERSION) && !defined(HEDLEY_IAR_VERSION)) || \ HEDLEY_HAS_EXTENSION(c_generic_selections) || HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || \ HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) || HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || HEDLEY_ARM_VERSION_CHECK(5, 3, 0) #if defined(__INTPTR_TYPE__) #define HEDLEY_IS_CONSTEXPR_(expr) \ _Generic((1 ? (void *)((__INTPTR_TYPE__)((expr)*0)) : (int *)0), int * : 1, void * : 0) #else #include #define HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void *)((intptr_t)*0) : (int *)0), int * : 1, void * : 0) #endif #elif defined(HEDLEY_GCC_VERSION) || defined(HEDLEY_INTEL_VERSION) || defined(HEDLEY_TINYC_VERSION) || \ defined(HEDLEY_TI_ARMCL_VERSION) || HEDLEY_TI_CL430_VERSION_CHECK(18, 12, 0) || \ defined(HEDLEY_TI_CL2000_VERSION) || defined(HEDLEY_TI_CL6X_VERSION) || defined(HEDLEY_TI_CL7X_VERSION) || \ defined(HEDLEY_TI_CLPRU_VERSION) || defined(__clang__) #define HEDLEY_IS_CONSTEXPR_(expr) \ (sizeof(void) != sizeof(*(1 ? ((void *)((expr)*0L)) : ((struct { char v[sizeof(void) * 2]; } *)1)))) #endif #endif #if defined(HEDLEY_IS_CONSTEXPR_) #if !defined(HEDLEY_IS_CONSTANT) #define HEDLEY_IS_CONSTANT(expr) HEDLEY_IS_CONSTEXPR_(expr) #endif #define HEDLEY_REQUIRE_CONSTEXPR(expr) (HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) #else #if !defined(HEDLEY_IS_CONSTANT) #define HEDLEY_IS_CONSTANT(expr) (0) #endif #define HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) #endif #if defined(HEDLEY_BEGIN_C_DECLS) #undef HEDLEY_BEGIN_C_DECLS #endif #if defined(HEDLEY_END_C_DECLS) #undef HEDLEY_END_C_DECLS #endif #if defined(HEDLEY_C_DECL) #undef HEDLEY_C_DECL #endif #if defined(__cplusplus) #define HEDLEY_BEGIN_C_DECLS extern "C" { #define HEDLEY_END_C_DECLS } #define HEDLEY_C_DECL extern "C" #else #define HEDLEY_BEGIN_C_DECLS #define HEDLEY_END_C_DECLS #define HEDLEY_C_DECL #endif #if defined(HEDLEY_STATIC_ASSERT) #undef HEDLEY_STATIC_ASSERT #endif #if !defined(__cplusplus) && \ ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ (HEDLEY_HAS_FEATURE(c_static_assert) && !defined(HEDLEY_INTEL_CL_VERSION)) || \ HEDLEY_GCC_VERSION_CHECK(6, 0, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || defined(_Static_assert)) #define HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) #elif (defined(__cplusplus) && (__cplusplus >= 201103L)) || HEDLEY_MSVC_VERSION_CHECK(16, 0, 0) || \ HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_STATIC_ASSERT(expr, message) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else #define HEDLEY_STATIC_ASSERT(expr, message) #endif #if defined(HEDLEY_NULL) #undef HEDLEY_NULL #endif #if defined(__cplusplus) #if __cplusplus >= 201103L #define HEDLEY_NULL HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) #elif defined(NULL) #define HEDLEY_NULL NULL #else #define HEDLEY_NULL HEDLEY_STATIC_CAST(void *, 0) #endif #elif defined(NULL) #define HEDLEY_NULL NULL #else #define HEDLEY_NULL ((void *)0) #endif #if defined(HEDLEY_MESSAGE) #undef HEDLEY_MESSAGE #endif #if HEDLEY_HAS_WARNING("-Wunknown-pragmas") #define HEDLEY_MESSAGE(msg) \ HEDLEY_DIAGNOSTIC_PUSH \ HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ HEDLEY_PRAGMA(message msg) \ HEDLEY_DIAGNOSTIC_POP #elif HEDLEY_GCC_VERSION_CHECK(4, 4, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message msg) #elif HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) #define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(_CRI message msg) #elif HEDLEY_IAR_VERSION_CHECK(8, 0, 0) #define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message(msg)) #elif HEDLEY_PELLES_VERSION_CHECK(2, 0, 0) #define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message(msg)) #else #define HEDLEY_MESSAGE(msg) #endif #if defined(HEDLEY_WARNING) #undef HEDLEY_WARNING #endif #if HEDLEY_HAS_WARNING("-Wunknown-pragmas") #define HEDLEY_WARNING(msg) \ HEDLEY_DIAGNOSTIC_PUSH \ HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ HEDLEY_PRAGMA(clang warning msg) \ HEDLEY_DIAGNOSTIC_POP #elif HEDLEY_GCC_VERSION_CHECK(4, 8, 0) || HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) #define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(GCC warning msg) #elif HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(message(msg)) #else #define HEDLEY_WARNING(msg) HEDLEY_MESSAGE(msg) #endif #if defined(HEDLEY_REQUIRE) #undef HEDLEY_REQUIRE #endif #if defined(HEDLEY_REQUIRE_MSG) #undef HEDLEY_REQUIRE_MSG #endif #if HEDLEY_HAS_ATTRIBUTE(diagnose_if) #if HEDLEY_HAS_WARNING("-Wgcc-compat") #define HEDLEY_REQUIRE(expr) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") __attribute__((diagnose_if(!(expr), #expr, "error"))) \ HEDLEY_DIAGNOSTIC_POP #define HEDLEY_REQUIRE_MSG(expr, msg) \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") __attribute__((diagnose_if(!(expr), msg, "error"))) \ HEDLEY_DIAGNOSTIC_POP #else #define HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) #define HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((diagnose_if(!(expr), msg, "error"))) #endif #else #define HEDLEY_REQUIRE(expr) #define HEDLEY_REQUIRE_MSG(expr, msg) #endif #if defined(HEDLEY_FLAGS) #undef HEDLEY_FLAGS #endif #if HEDLEY_HAS_ATTRIBUTE(flag_enum) #define HEDLEY_FLAGS __attribute__((__flag_enum__)) #else #define HEDLEY_FLAGS #endif #if defined(HEDLEY_FLAGS_CAST) #undef HEDLEY_FLAGS_CAST #endif #if HEDLEY_INTEL_VERSION_CHECK(19, 0, 0) #define HEDLEY_FLAGS_CAST(T, expr) \ (__extension__({ \ HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("warning(disable:188)")((T)(expr)); \ HEDLEY_DIAGNOSTIC_POP \ })) #else #define HEDLEY_FLAGS_CAST(T, expr) HEDLEY_STATIC_CAST(T, expr) #endif #if defined(HEDLEY_EMPTY_BASES) #undef HEDLEY_EMPTY_BASES #endif #if (HEDLEY_MSVC_VERSION_CHECK(19, 0, 23918) && !HEDLEY_MSVC_VERSION_CHECK(20, 0, 0)) || \ HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) #define HEDLEY_EMPTY_BASES __declspec(empty_bases) #else #define HEDLEY_EMPTY_BASES #endif /* Remaining macros are deprecated. */ #if defined(HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) #undef HEDLEY_GCC_NOT_CLANG_VERSION_CHECK #endif #if defined(__clang__) #define HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) (0) #else #define HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) HEDLEY_GCC_VERSION_CHECK(major, minor, patch) #endif #if defined(HEDLEY_CLANG_HAS_ATTRIBUTE) #undef HEDLEY_CLANG_HAS_ATTRIBUTE #endif #define HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) HEDLEY_HAS_ATTRIBUTE(attribute) #if defined(HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) #undef HEDLEY_CLANG_HAS_CPP_ATTRIBUTE #endif #define HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) HEDLEY_HAS_CPP_ATTRIBUTE(attribute) #if defined(HEDLEY_CLANG_HAS_BUILTIN) #undef HEDLEY_CLANG_HAS_BUILTIN #endif #define HEDLEY_CLANG_HAS_BUILTIN(builtin) HEDLEY_HAS_BUILTIN(builtin) #if defined(HEDLEY_CLANG_HAS_FEATURE) #undef HEDLEY_CLANG_HAS_FEATURE #endif #define HEDLEY_CLANG_HAS_FEATURE(feature) HEDLEY_HAS_FEATURE(feature) #if defined(HEDLEY_CLANG_HAS_EXTENSION) #undef HEDLEY_CLANG_HAS_EXTENSION #endif #define HEDLEY_CLANG_HAS_EXTENSION(extension) HEDLEY_HAS_EXTENSION(extension) #if defined(HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) #undef HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE #endif #define HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) #if defined(HEDLEY_CLANG_HAS_WARNING) #undef HEDLEY_CLANG_HAS_WARNING #endif #define HEDLEY_CLANG_HAS_WARNING(warning) HEDLEY_HAS_WARNING(warning) #endif /* !defined(HEDLEY_VERSION) || (HEDLEY_VERSION < X) */ Nuitka-0.6.19.1/nuitka/build/SconsUtils.py0000600000372100037210000004346314167275603025360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Helper functions for the scons file. """ from __future__ import print_function import os import shutil import signal import sys from nuitka.__past__ import basestring, unicode from nuitka.Tracing import scons_details_logger, scons_logger from nuitka.utils.Execution import executeProcess from nuitka.utils.FileOperations import getFileContentByLine, openTextFile def initScons(): # Avoid localized outputs. os.environ["LANG"] = "C" def nosync(self): # That's a noop, pylint: disable=unused-argument pass # Avoid scons writing the scons file at all. import SCons.dblite # pylint: disable=I0021,import-error SCons.dblite.dblite.sync = nosync def setupScons(env, source_dir): env["BUILD_DIR"] = source_dir # Store the file signatures database with the rest of the source files # and make it version dependent on the Python version of Scons, as its # pickle is being used. sconsign_dir = os.path.abspath( os.path.join( source_dir, ".sconsign-%d%s" % (sys.version_info[0], sys.version_info[1]) ) ) env.SConsignFile(sconsign_dir) scons_arguments = {} def setArguments(arguments): """Decode command line arguments.""" arg_encoding = arguments.get("argument_encoding") for key, value in arguments.items(): if arg_encoding is not None: value = decodeData(value) scons_arguments[key] = value def getArgumentRequired(name): """Helper for string options without default value.""" return scons_arguments[name] def getArgumentDefaulted(name, default): """Helper for string options with default value.""" return scons_arguments.get(name, default) def getArgumentInt(option_name, default=None): """Small helper for boolean mode flags.""" if default is None: value = scons_arguments[option_name] else: value = int(scons_arguments.get(option_name, default)) return value def getArgumentBool(option_name, default=None): """Small helper for boolean mode flags.""" if default is None: value = scons_arguments[option_name] else: value = scons_arguments.get(option_name, "True" if default else "False") return value.lower() in ("yes", "true", "1") def getArgumentList(option_name, default=None): """Small helper for list mode options, default should be command separated str.""" if default is None: value = scons_arguments[option_name] else: value = scons_arguments.get(option_name, default) if value: return value.split(",") else: return [] def _enableExperimentalSettings(env, experimental_flags): for experimental_flag in experimental_flags: if experimental_flag: if "=" in experimental_flag: experiment, value = experimental_flag.split("=", 1) else: experiment = experimental_flag value = None # Allowing for nice names on command line, but using identifiers for C. experiment = experiment.upper().replace("-", "_") if value: env.Append(CPPDEFINES=[("_NUITKA_EXPERIMENTAL_%s" % experiment, value)]) else: env.Append(CPPDEFINES=["_NUITKA_EXPERIMENTAL_%s" % experiment]) env.experimental_flags = experimental_flags def createEnvironment(mingw_mode, msvc_version, target_arch, experimental): from SCons.Script import Environment # pylint: disable=I0021,import-error args = {} # If we are on Windows, and MinGW is not enforced, lets see if we can # find "cl.exe", and if we do, disable automatic scan. if ( os.name == "nt" and not mingw_mode and msvc_version is None and msvc_version != "latest" and (getExecutablePath("cl", env=None) is not None) ): args["MSVC_USE_SCRIPT"] = False if mingw_mode: # Force usage of MinGW64, not using MSVC tools. tools = ["mingw"] # This code would be running anyway, make it do not thing by monkey patching. import SCons.Tool.MSCommon.vc # pylint: disable=I0021,import-error SCons.Tool.MSCommon.vc.msvc_setup_env = lambda *args: None else: # Everything else should use default, that is MSVC tools, but not MinGW64. tools = ["default"] env = Environment( # We want the outside environment to be passed through. ENV=os.environ, # Extra tools configuration for scons. tools=tools, # The shared libraries should not be named "lib...", because CPython # requires the filename "module_name.so" to load it. SHLIBPREFIX="", # Under windows, specify the target architecture is needed for Scons # to pick up MSVC. TARGET_ARCH=target_arch, # The MSVC version might be fixed by the user. MSVC_VERSION=msvc_version if msvc_version != "latest" else None, **args ) _enableExperimentalSettings(env, experimental) return env def decodeData(data): """Our own decode tries to workaround MSVC misbehavior.""" try: return data.decode(sys.stdout.encoding) except UnicodeDecodeError: import locale try: return data.decode(locale.getpreferredencoding()) except UnicodeDecodeError: return data.decode("utf8", "backslashreplace") # Windows target mode: Compile for Windows. Used to be an option, but we # no longer cross compile this way. win_target = os.name == "nt" def getExecutablePath(filename, env): """Find an execute in either normal PATH, or Scons detected PATH.""" if os.path.exists(filename): return filename # Variable substitution from environment is needed, because this can contain # "$CC" which should be looked up too. while filename.startswith("$"): filename = env[filename[1:]] # Append ".exe" suffix on Windows if not already present. if win_target and not filename.lower().endswith(".exe"): filename += ".exe" # Either look at the initial "PATH" as given from the outside or look at the # current environment. if env is None: search_path = os.environ["PATH"] else: search_path = env._dict["ENV"]["PATH"] # pylint: disable=protected-access # Now check in each path element, much like the shell will. path_elements = search_path.split(os.pathsep) for path_element in path_elements: path_element = path_element.strip('"') full = os.path.join(path_element, filename) if os.path.exists(full): return full return None def changeKeyboardInteruptToErrorExit(): def signalHandler( signal, frame ): # pylint: disable=redefined-outer-name,unused-argument sys.exit(2) signal.signal(signal.SIGINT, signalHandler) def setEnvironmentVariable(env, key, value): os.environ[key] = value if env is not None: env._dict["ENV"][key] = value # pylint: disable=protected-access def addToPATH(env, dirname, prefix): # Otherwise subprocess will complain in Python2 if str is bytes and type(dirname) is unicode: dirname = dirname.encode("utf8") path_value = os.environ["PATH"].split(os.pathsep) if prefix: path_value.insert(0, dirname) else: path_value.append(dirname) setEnvironmentVariable(env, "PATH", os.pathsep.join(path_value)) def writeSconsReport(env, source_dir): with openTextFile(os.path.join(source_dir, "scons-report.txt"), "w") as report_file: # We are friends to get at this debug info, pylint: disable=protected-access for key, value in sorted(env._dict.items()): if type(value) is list and all(isinstance(v, basestring) for v in value): value = repr(value) if not isinstance(value, basestring): continue if key.startswith(("_", "CONFIGURE")): continue if key in ("MSVSSCONS", "BUILD_DIR", "IDLSUFFIXES", "DSUFFIXES"): continue # TODO: For these kinds of prints, maybe have our own method of doing them # rather than print, or maybe just json or something similar. print(key + "=" + value, file=report_file) print("gcc_mode=%s" % env.gcc_mode, file=report_file) print("clang_mode=%s" % env.clang_mode, file=report_file) print("msvc_mode=%s" % env.msvc_mode, file=report_file) print("mingw_mode=%s" % env.mingw_mode, file=report_file) print("clangcl_mode=%s" % env.clangcl_mode, file=report_file) print("PATH=%s" % os.environ["PATH"], file=report_file) _scons_reports = {} def flushSconsReports(): _scons_reports.clear() def readSconsReport(source_dir): if source_dir not in _scons_reports: scons_report = {} for line in getFileContentByLine(os.path.join(source_dir, "scons-report.txt")): if "=" not in line: continue key, value = line.strip().split("=", 1) scons_report[key] = value _scons_reports[source_dir] = scons_report return _scons_reports[source_dir] def getSconsReportValue(source_dir, key): return readSconsReport(source_dir).get(key) def addClangClPathFromMSVC(env, target_arch): cl_exe = getExecutablePath("cl", env=env) if cl_exe is None: scons_logger.sysexit( "Error, Visual Studio required for using ClangCL on Windows." ) clang_dir = cl_exe = os.path.join(cl_exe[: cl_exe.lower().rfind("msvc")], "Llvm") if target_arch == "x86_64": clang_dir = os.path.join(clang_dir, "x64", "bin") else: clang_dir = os.path.join(clang_dir, "bin") if not os.path.exists(clang_dir): scons_details_logger.sysexit( "Visual Studio has no Clang component found at '%s'." % clang_dir ) scons_details_logger.info( "Adding Visual Studio directory '%s' for Clang to PATH." % clang_dir ) addToPATH(env, clang_dir, prefix=True) clangcl_path = getExecutablePath("clang-cl", env=env) if clangcl_path is None: scons_details_logger.sysexit( "Visual Studio has no Clang component found at '%s'." % clang_dir ) env["CC"] = "clang-cl" env["LINK"] = "lld-link" env["CCVERSION"] = None def isGccName(cc_name): return "gcc" in cc_name or "g++" in cc_name or "gnu-cc" in cc_name def cheapCopyFile(src, dst): dirname = os.path.dirname(dst) if not os.path.exists(dirname): os.makedirs(dirname) if win_target: # Windows has symlinks these days, but they do not integrate well # with Python2 at least. So make a copy in any case. if os.path.exists(dst): os.unlink(dst) shutil.copy(src, dst) else: # Relative paths work badly for links. Creating them relative is # not worth the effort. src = os.path.abspath(src) try: link_target = os.readlink(dst) # If it's already a proper link, do nothing then. if link_target == src: return os.unlink(dst) except OSError as _e: # Broken links work like that, remove them, so we can replace # them. try: os.unlink(dst) except OSError: pass try: os.symlink(src, dst) except OSError: shutil.copy(src, dst) def provideStaticSourceFile(sub_path, nuitka_src, source_dir, c11_mode): source_filename = os.path.join(nuitka_src, "static_src", sub_path) target_filename = os.path.join(source_dir, "static_src", os.path.basename(sub_path)) if target_filename.endswith(".c") and not c11_mode: target_filename += "pp" # .cpp suffix then. cheapCopyFile(source_filename, target_filename) return target_filename def scanSourceDir(env, dirname, plugins): if not os.path.exists(dirname): return # If we use C11 capable compiler, all good. Otherwise use C++, which Scons # needs to derive from filenames, so make copies (or links) with a different # name. added_path = False for filename in sorted(os.listdir(dirname)): if filename.endswith(".h") and plugins and not added_path: env.Append(CPPPATH=[dirname]) added_path = True # Only C files are of interest here. if not filename.endswith((".c", "cpp")) or not filename.startswith( ("module.", "__", "plugin.") ): continue filename = os.path.join(dirname, filename) target_file = filename # We pretend to use C++ if no C11 compiler is present. if env.c11_mode: yield filename else: if filename.endswith(".c"): target_file += "pp" # .cpp" suffix then os.rename(filename, target_file) yield target_file def makeCLiteral(value): value = value.replace("\\", r"\\") value = value.replace('"', r"\"") return '"' + value + '"' def createDefinitionsFile(source_dir, filename, definitions): build_definitions_filename = os.path.join(source_dir, filename) with openTextFile(build_definitions_filename, "w") as f: for key, value in sorted(definitions.items()): if type(value) is int: f.write("#define %s %s\n" % (key, value)) else: f.write("#define %s %s\n" % (key, makeCLiteral(value))) def getMsvcVersionString(env): import SCons.Tool.MSCommon.vc # pylint: disable=I0021,import-error return SCons.Tool.MSCommon.vc.get_default_version(env) def getMsvcVersion(env): value = getMsvcVersionString(env) value = value.replace("exp", "") return float(value) def _getBinaryArch(binary, mingw_mode): if "linux" in sys.platform or mingw_mode: assert os.path.exists(binary), binary command = ["objdump", "-f", binary] try: data, _err, rv = executeProcess(command) except OSError: return None if rv != 0: return None if str is not bytes: data = decodeData(data) for line in data.splitlines(): if " file format " in line: return line.split(" file format ")[-1] else: # TODO: Missing for macOS, FreeBSD, other Linux return None _linker_arch_determined = False _linker_arch = None def getLinkerArch(target_arch, mingw_mode): # Singleton, pylint: disable=global-statement global _linker_arch_determined, _linker_arch if not _linker_arch_determined: if win_target: if target_arch == "x86_64": _linker_arch = "pei-x86-64" else: _linker_arch = "pei-i386" else: _linker_arch = _getBinaryArch( binary=os.environ["NUITKA_PYTHON_EXE_PATH"], mingw_mode=mingw_mode ) _linker_arch_determined = True return _linker_arch _compiler_arch = {} def getCompilerArch(mingw_mode, msvc_mode, the_cc_name, compiler_path): if mingw_mode: if compiler_path not in _compiler_arch: _compiler_arch[compiler_path] = _getBinaryArch( binary=compiler_path, mingw_mode=mingw_mode ) elif msvc_mode: cmdline = [compiler_path] if "-cl" in the_cc_name: cmdline.append("--version") # The cl.exe without further args will give error stdout, stderr, _rv = executeProcess( command=cmdline, ) # The MSVC will output on error, while clang outputs in stdout and they # use different names for arches. if b"x86" in stderr or b"i686" in stdout: _compiler_arch[compiler_path] = "pei-i386" elif b"x64" in stderr or b"x86_64" in stdout: _compiler_arch[compiler_path] = "pei-x86-64" else: assert False, (stdout, stderr) else: assert False, compiler_path return _compiler_arch[compiler_path] def decideArchMismatch(target_arch, mingw_mode, msvc_mode, the_cc_name, compiler_path): linker_arch = getLinkerArch(target_arch=target_arch, mingw_mode=mingw_mode) compiler_arch = getCompilerArch( mingw_mode=mingw_mode, msvc_mode=msvc_mode, the_cc_name=the_cc_name, compiler_path=compiler_path, ) return linker_arch != compiler_arch, linker_arch, compiler_arch def raiseNoCompilerFoundErrorExit(): if os.name == "nt": scons_logger.sysexit( """\ Error, cannot locate suitable C compiler. You have the following options: a) If a suitable Visual Studio version is installed, it will be located automatically via registry. But not if you activate the wrong prompt. b) Using --mingw64 lets Nuitka download MinGW64 for you. Note: Only MinGW64 will work! MinGW64 does *not* mean 64 bits, just better Windows compatibility, it is available for 32 and 64 bits. Cygwin based gcc will not work. MSYS2 based gcc will only work if you know what you are doing. Note: The clang-cl will only work if Visual Studio already works for you. """ ) else: scons_logger.sysexit("Error, cannot locate suitable C compiler.") Nuitka-0.6.19.1/nuitka/build/SconsCompilerSettings.py0000600000372100037210000006002214167275603027541 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This contains the tuning of the compilers towards defined goals. """ import os import re from nuitka.Tracing import scons_details_logger, scons_logger from nuitka.utils.Download import getCachedDownloadedMinGW64 from nuitka.utils.FileOperations import openTextFile, putTextFileContents from nuitka.utils.Utils import isMacOS, isWin32Windows from .DataComposerInterface import getConstantBlobFilename from .SconsHacks import myDetectVersion from .SconsUtils import ( addToPATH, createEnvironment, decideArchMismatch, getExecutablePath, getLinkerArch, getMsvcVersion, getMsvcVersionString, isGccName, raiseNoCompilerFoundErrorExit, setEnvironmentVariable, ) def _detectWindowsSDK(env): # Check if there is a WindowsSDK installed. if env.msvc_mode or env.clangcl_mode: if "WindowsSDKVersion" not in env: if "WindowsSDKVersion" in os.environ: windows_sdk_version = os.environ["WindowsSDKVersion"].rstrip("\\") else: windows_sdk_version = None else: windows_sdk_version = env["WindowsSDKVersion"] if not windows_sdk_version: scons_logger.sysexit( "Error, the Windows SDK must be installed in Visual Studio." ) scons_details_logger.info("Using Windows SDK '%s'." % windows_sdk_version) env.windows_sdk_version = tuple(int(x) for x in windows_sdk_version.split(".")) def _enableC11Settings(env): """Decide if C11 mode can be used and enable the C compile flags for it. Args: env - scons environment with compiler information Returns: bool - c11_mode flag """ if env.clangcl_mode: c11_mode = True elif env.msvc_mode: # TODO: Make this experimental mode the default. c11_mode = ( env.windows_sdk_version >= (10, 0, 19041, 0) and "msvc_c11" in env.experimental_flags ) elif env.clang_mode: c11_mode = True elif env.gcc_mode and env.gcc_version >= (5,): c11_mode = True else: c11_mode = False if c11_mode: if env.gcc_mode: env.Append(CCFLAGS=["-std=c11"]) elif env.msvc_mode: env.Append(CCFLAGS=["/std:c11"]) if env.msvc_mode and c11_mode: # Windows SDK shows this even in non-debug mode in C11 mode. env.Append(CCFLAGS=["/wd5105"]) scons_details_logger.info("Using C11 mode: %s" % c11_mode) env.c11_mode = c11_mode def _enableLtoSettings( env, lto_mode, pgo_mode, job_count, ): # This is driven by branches on purpose and pylint: disable=too-many-branches,too-many-statements orig_lto_mode = lto_mode if lto_mode == "no": lto_mode = False reason = "disabled" elif lto_mode == "yes": lto_mode = True reason = "enabled" elif pgo_mode in ("use", "generate"): lto_mode = True reason = "PGO implies LTO" elif env.msvc_mode and getMsvcVersion(env) >= 14: lto_mode = True reason = "known to be supported" elif env.nuitka_python: lto_mode = True reason = "known to be supported (Nuitka-Python)" elif ( env.debian_python and env.gcc_mode and not env.clang_mode and env.gcc_version >= (6,) ): lto_mode = True reason = "known to be supported (Debian)" elif env.gcc_mode and env.the_cc_name == "gnu-cc": lto_mode = True reason = "known to be supported (CondaCC)" elif env.mingw_mode and env.clang_mode: lto_mode = False reason = "known to not be supported (new MinGW64 Clang)" elif env.gcc_mode and env.mingw_mode and env.gcc_version >= (11, 2): lto_mode = True reason = "known to be supported (new MinGW64)" else: lto_mode = False reason = "not known to be supported" if lto_mode and env.gcc_mode and not env.clang_mode and env.gcc_version < (4, 6): scons_logger.warning( """\ The gcc compiler %s (version %s) doesn't have the sufficient \ version for lto mode (>= 4.6). Disabled.""" % (env["CXX"], env["CXXVERSION"]) ) lto_mode = False reason = "gcc 4.6 is doesn't have good enough LTO support" if env.gcc_mode and lto_mode: env.Append(CCFLAGS=["-flto"]) if env.clang_mode: env.Append(LINKFLAGS=["-flto"]) else: env.Append(CCFLAGS=["-fuse-linker-plugin", "-fno-fat-lto-objects"]) env.Append(LINKFLAGS=["-fuse-linker-plugin"]) env.Append(LINKFLAGS=["-flto=%d" % job_count]) # Need to tell the linker these things are OK. env.Append(LINKFLAGS=["-fpartial-inlining", "-freorder-functions"]) # Tell compiler to use link time optimization for MSVC if env.msvc_mode and lto_mode: env.Append(CCFLAGS=["/GL"]) if not env.clangcl_mode: env.Append(LINKFLAGS=["/LTCG"]) if orig_lto_mode == "auto": scons_details_logger.info( "LTO mode auto was resolved to mode: '%s' (%s)." % ("yes" if lto_mode else "no", reason) ) env.lto_mode = lto_mode # PGO configuration _enablePgoSettings(env, pgo_mode) def checkWindowsCompilerFound( env, target_arch, clang_mode, msvc_version, assume_yes_for_downloads ): """Remove compiler of wrong arch or too old gcc and replace with downloaded winlibs gcc.""" if os.name == "nt": # On Windows, in case MSVC was not found and not previously forced, use the # winlibs MinGW64 as a download, and use it as a fallback. compiler_path = getExecutablePath(env["CC"], env=env) scons_details_logger.info( "Checking usability of %r from %r" % (compiler_path, env["CC"]) ) # Drop wrong arch compiler, most often found by scans. There might be wrong gcc or cl on the PATH. if compiler_path is not None: the_cc_name = os.path.basename(compiler_path) decision, linker_arch, compiler_arch = decideArchMismatch( target_arch=target_arch, mingw_mode=isGccName(the_cc_name), msvc_mode=not isGccName(the_cc_name), the_cc_name=the_cc_name, compiler_path=compiler_path, ) if decision: scons_logger.info( "Mismatch between Python binary (%r -> %r) and C compiler (%r -> %r) arches, ignored!" % ( os.environ["NUITKA_PYTHON_EXE_PATH"], linker_arch, compiler_path, compiler_arch, ) ) # This will trigger using it to use our own gcc in branch below. compiler_path = None env["CC"] = None if compiler_path is not None and msvc_version is not None: if msvc_version == "latest": scons_logger.info( "MSVC version resolved to %s." % getMsvcVersionString(env) ) # Requested a specific MSVC version, check if that worked. elif msvc_version != getMsvcVersionString(env): scons_logger.info( "Failed to find requested MSVC version (%r != %r)." % (msvc_version, getMsvcVersionString(env)) ) # This will trigger error exit in branch below. compiler_path = None env["CC"] = None if compiler_path is not None: the_cc_name = os.path.basename(compiler_path) if isGccName(the_cc_name): gcc_version = myDetectVersion(env, compiler_path) min_version = (11, 2) if gcc_version is not None and ( gcc_version < min_version or "force-winlibs-gcc" in env.experimental_flags ): scons_logger.info( "Too old gcc %r (%r < %r) ignored!" % (compiler_path, gcc_version, min_version) ) # This also will trigger using it to use our own gcc in branch below. compiler_path = None env["CC"] = None if compiler_path is None and msvc_version is None: scons_details_logger.info( "No usable C compiler, attempt fallback to winlibs gcc." ) # This will download "gcc.exe" (and "clang.exe") when all others have been # rejected and MSVC is not enforced. compiler_path = getCachedDownloadedMinGW64( target_arch=target_arch, assume_yes_for_downloads=assume_yes_for_downloads, ) addToPATH(env, os.path.dirname(compiler_path), prefix=True) env = createEnvironment( mingw_mode=True, msvc_version=None, target_arch=target_arch, experimental=env.experimental_flags, ) if clang_mode: env["CC"] = os.path.join(os.path.dirname(compiler_path), "clang.exe") if env["CC"] is None: raiseNoCompilerFoundErrorExit() return env def decideConstantsBlobResourceMode(env, module_mode): if "NUITKA_RESOURCE_MODE" in os.environ: resource_mode = os.environ["NUITKA_RESOURCE_MODE"] reason = "user provided" elif os.name == "nt": resource_mode = "win_resource" reason = "default for Windows" elif env.lto_mode and env.gcc_mode and not env.clang_mode: if module_mode: resource_mode = "code" else: resource_mode = "linker" reason = "default for lto gcc with --lto bugs for incbin" else: # All is done already, this is for most platforms. resource_mode = "incbin" reason = "default" return resource_mode, reason def addConstantBlobFile(env, resource_desc, source_dir, target_arch): resource_mode, reason = resource_desc constants_bin_filename = getConstantBlobFilename(source_dir) scons_details_logger.info( "Using resource mode: '%s' (%s)." % (resource_mode, reason) ) if resource_mode == "win_resource": # On Windows constants can be accessed as a resource by Nuitka runtime afterwards. env.Append(CPPDEFINES=["_NUITKA_CONSTANTS_FROM_RESOURCE"]) elif resource_mode == "incbin": env.Append(CPPDEFINES=["_NUITKA_CONSTANTS_FROM_INCBIN"]) constants_generated_filename = os.path.join(source_dir, "__constants_data.c") putTextFileContents( constants_generated_filename, contents="""\ #define INCBIN_PREFIX #define INCBIN_STYLE INCBIN_STYLE_SNAKE #define INCBIN_LOCAL #ifdef _NUITKA_EXPERIMENTAL_WRITEABLE_CONSTANTS #define INCBIN_OUTPUT_SECTION ".data" #endif #include "nuitka/incbin.h" INCBIN(constant_bin, "__constants.bin"); unsigned char const *getConstantsBlobData() { return constant_bin_data; } """, ) elif resource_mode == "linker": # Indicate "linker" resource mode. env.Append(CPPDEFINES=["_NUITKA_CONSTANTS_FROM_LINKER"]) env.Append( LINKFLAGS=[ "-Wl,-b", "-Wl,binary", "-Wl,%s" % constants_bin_filename, "-Wl,-b", "-Wl,%s" % getLinkerArch(target_arch=target_arch, mingw_mode=env.mingw_mode), "-Wl,-defsym", "-Wl,%sconstant_bin_data=_binary_%s___constants_bin_start" % ( "_" if env.mingw_mode else "", "".join(re.sub("[^a-zA-Z0-9_]", "_", c) for c in source_dir), ), ] ) elif resource_mode == "code": # Indicate "code" resource mode. env.Append(CPPDEFINES=["_NUITKA_CONSTANTS_FROM_CODE"]) constants_generated_filename = os.path.join(source_dir, "__constants_data.c") def writeConstantsDataSource(): with openTextFile(constants_generated_filename, "w") as output: if not env.c11_mode: output.write('extern "C" {') output.write( """ // Constant data for the program. #if !defined(_NUITKA_EXPERIMENTAL_WRITEABLE_CONSTANTS) const #endif unsigned char constant_bin_data[] =\n{\n """ ) with open(constants_bin_filename, "rb") as f: content = f.read() for count, stream_byte in enumerate(content): if count % 16 == 0: if count > 0: output.write("\n") output.write(" ") if str is bytes: stream_byte = ord(stream_byte) output.write(" 0x%02x," % stream_byte) output.write("\n};\n") if not env.c11_mode: output.write("}") writeConstantsDataSource() else: scons_logger.sysexit( "Error, illegal resource mode %r specified" % resource_mode ) def enableWindowsStackSize(env, target_arch): # Stack size 4MB or 8MB, we might need more than the default 1MB. if target_arch == "x86_64": stack_size = 1024 * 1204 * 8 else: stack_size = 1024 * 1204 * 4 if env.msvc_mode: env.Append(LINKFLAGS=["/STACK:%d" % stack_size]) if env.mingw_mode: env.Append(LINKFLAGS=["-Wl,--stack,%d" % stack_size]) def setupCCompiler(env, lto_mode, pgo_mode, job_count): # This is driven by many branches on purpose and has a lot of things # to deal with for LTO checks and flags, pylint: disable=too-many-branches,too-many-statements # Enable LTO for compiler. _enableLtoSettings( env=env, lto_mode=lto_mode, pgo_mode=pgo_mode, job_count=job_count, ) _detectWindowsSDK(env) _enableC11Settings(env) if env.gcc_mode: # Support for gcc and clang, restricting visibility as much as possible. env.Append(CCFLAGS=["-fvisibility=hidden"]) if not env.c11_mode: env.Append(CXXFLAGS=["-fvisibility-inlines-hidden"]) if isWin32Windows(): # On Windows, exporting to DLL need to be controlled. env.Append(LINKFLAGS=["-Wl,--exclude-all-symbols"]) # Make sure we handle import library on our own and put it into the # build directory. env.Append( LINKFLAGS=[ "-Wl,--out-implib,%s" % os.path.join(env.source_dir, "import.lib") ] ) # Make it clear how to handle integer overflows, namely by wrapping around # to negative values. env.Append(CCFLAGS=["-fwrapv"]) if not env.low_memory: # Avoid IO for compilation as much as possible, this should make the # compilation more memory hungry, but also faster. env.Append(CCFLAGS="-pipe") # Support for clang. if "clang" in env.the_cc_name: env.Append(CCFLAGS=["-w"]) env.Append(CPPDEFINES=["_XOPEN_SOURCE"]) # Don't export anything by default, this should create smaller executables. env.Append(CCFLAGS=["-fvisibility=hidden", "-fvisibility-inlines-hidden"]) if env.debug_mode: env.Append(CCFLAGS=["-Wunused-but-set-variable"]) # Support for macOS standalone backporting. if isMacOS() and env.macos_minversion: setEnvironmentVariable(env, "MACOSX_DEPLOYMENT_TARGET", env.macos_minversion) # The 32 bits MinGW does not default for API level properly, so help it. if env.mingw_mode: # Windows XP env.Append(CPPDEFINES=["_WIN32_WINNT=0x0501"]) # Unicode entry points for programs. if env.mingw_mode: env.Append(LINKFLAGS=["-municode"]) # Detect the gcc version if env.gcc_mode and not env.clang_mode: env.gcc_version = myDetectVersion(env, env.the_compiler) else: env.gcc_version = None # Older g++ complains about aliasing with Py_True and Py_False, but we don't # care. if env.gcc_mode and not env.clang_mode and env.gcc_version < (4, 5): env.Append(CCFLAGS=["-fno-strict-aliasing"]) # For gcc 4.6 or higher, there are some new interesting functions. if env.gcc_mode and not env.clang_mode and env.gcc_version >= (4, 6): env.Append(CCFLAGS=["-fpartial-inlining"]) if env.debug_mode: env.Append(CCFLAGS=["-Wunused-but-set-variable"]) # Save some memory for gcc by not tracing macro code locations at all. if ( not env.debug_mode and env.gcc_mode and not env.clang_mode and env.gcc_version >= (5,) ): env.Append(CCFLAGS=["-ftrack-macro-expansion=0"]) # We don't care about deprecations. if env.gcc_mode and not env.clang_mode: env.Append(CCFLAGS=["-Wno-deprecated-declarations"]) # The var-tracking does not scale, disable it. Should we really need it, we # can enable it. TODO: Does this cause a performance loss? if env.gcc_mode and not env.clang_mode: env.Append(CCFLAGS=["-fno-var-tracking"]) # For large files, these can issue warnings about disabling # itself, while we do not need it really. if env.gcc_mode and not env.clang_mode and env.gcc_version >= (6,): env.Append(CCFLAGS=["-Wno-misleading-indentation"]) # Disable output of notes, e.g. on struct alignment layout changes for # some arches, we don't care. if env.gcc_mode and not env.clang_mode: env.Append(CCFLAGS=["-fcompare-debug-second"]) # Prevent using LTO when told not to use it, causes errors with some # static link libraries. if ( env.gcc_mode and not env.clang_mode and env.static_libpython and not env.lto_mode ): env.Append(CCFLAGS=["-fno-lto"]) env.Append(LINKFLAGS=["-fno-lto"]) # Set optimization level for gcc and clang in LTO mode if env.gcc_mode and env.lto_mode: if env.debug_mode: env.Append(LINKFLAGS=["-Og"]) else: # For LTO with static libpython combined, there are crashes with Python core # being inlined, so we must refrain from that. On Windows there is no such # thing, and Nuitka-Python is not affected. env.Append( LINKFLAGS=[ "-O3" if env.nuitka_python or os.name == "nt" or not env.static_libpython else "-O2" ] ) # When debugging, optimize less than when optimizing, when not remove # assertions. if env.debug_mode: if env.clang_mode or (env.gcc_mode and env.gcc_version >= (4, 8)): env.Append(CCFLAGS=["-Og"]) elif env.gcc_mode: env.Append(CCFLAGS=["-O1"]) elif env.msvc_mode: env.Append(CCFLAGS=["-O2"]) else: if env.gcc_mode: env.Append( CCFLAGS=[ "-O3" if env.nuitka_python or os.name == "nt" or not env.static_libpython else "-O2" ] ) elif env.msvc_mode: env.Append( CCFLAGS=[ "/Ox", # Enable most speed optimization "/GF", # Eliminate duplicate strings. "/Gy", # Function level object storage, to allow removing unused ones ] ) env.Append(CPPDEFINES=["__NUITKA_NO_ASSERT__"]) def _enablePgoSettings(env, pgo_mode): if pgo_mode == "no": env.progressbar_name = "Backend" elif pgo_mode == "python": env.progressbar_name = "Python Profile" env.Append(CPPDEFINES=["_NUITKA_PGO_PYTHON"]) elif pgo_mode == "generate": env.progressbar_name = "Profile" env.Append(CPPDEFINES=["_NUITKA_PGO_GENERATE"]) if env.gcc_mode: env.Append(CCFLAGS=["-fprofile-generate"]) env.Append(LINKFLAGS=["-fprofile-generate"]) elif env.msvc_mode: env.Append(CCFLAGS=["/GL"]) env.Append(LINKFLAGS=["/GENPROFILE:EXACT"]) if not env.clangcl_mode: env.Append(LINKFLAGS=["/LTCG"]) else: scons_logger.sysexit( "Error, PGO not supported for '%s' compiler." % env.the_cc_name ) elif pgo_mode == "use": env.progressbar_name = "Backend" env.Append(CPPDEFINES=["_NUITKA_PGO_USE"]) if env.gcc_mode: env.Append(CCFLAGS=["-fprofile-use"]) env.Append(LINKFLAGS=["-fprofile-use"]) elif env.msvc_mode: env.Append(CCFLAGS=["/GL"]) env.Append( LINKFLAGS=[ "/USEPROFILE", ] ) else: scons_logger.sysexit( "Error, PGO not supported for '%s' compiler." % env.the_cc_name ) else: assert False, env.pgo_mode env.pgo_mode = pgo_mode def switchFromGccToGpp(env): if not env.gcc_mode or env.clang_mode: env.gcc_version = None return env.gcc_version = myDetectVersion(env, env.the_compiler) if env.gcc_version is None: scons_logger.sysexit( """\ Error, failed to detect gcc version of backend compiler %r. """ % env.the_compiler ) if "++" in env.the_cc_name: scons_logger.sysexit( """\ Error, compiler %s is apparently a C++ compiler, specify a C compiler instead. """ % env.the_cc_name ) # Enforce the minimum version, selecting a potentially existing g++-4.5 # binary if it's not high enough. This is esp. useful under Debian which # allows all compiler to exist next to each other and where g++ might not be # good enough, but g++-4.5 would be. if env.gcc_version < (4, 4): scons_logger.sysexit( """\ The gcc compiler %s (version %s) doesn't have the sufficient \ version (>= 4.4).""" % (env.the_compiler, env.gcc_version) ) # CondaCC or newer. if env.mingw_mode and env.gcc_version < (5, 3): scons_logger.sysexit( """\ The MinGW64 compiler %s (version %s) doesn't have the sufficient \ version (>= 5.3).""" % (env.the_compiler, env.gcc_version) ) if env.gcc_version < (5,): scons_logger.info("The provided gcc is too old, switching to its g++ instead.") # Switch to g++ from gcc then if possible, when C11 mode is false. the_gpp_compiler = os.path.join( os.path.dirname(env.the_compiler), os.path.basename(env.the_compiler).replace("gcc", "g++"), ) if getExecutablePath(the_gpp_compiler, env=env): env.the_compiler = the_gpp_compiler env.the_cc_name = env.the_cc_name.replace("gcc", "g++") else: scons_logger.sysexit( "Error, your gcc is too old for C11 support, and no related g++ to workaround that is found." ) def reportCCompiler(env, context): cc_output = env.the_cc_name if env.the_cc_name == "cl": cc_output = "%s %s" % (env.the_cc_name, getMsvcVersionString(env)) else: cc_output = env.the_cc_name scons_logger.info( "%s C compiler: %s (%s)." % (context, env.the_compiler, cc_output) ) Nuitka-0.6.19.1/nuitka/build/SconsInterface.py0000600000372100037210000003162214166627112026145 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Scons interface. Interaction with scons. Find the binary, and run it with a set of given options. """ import contextlib import copy import os import subprocess import sys from nuitka import Options, Tracing from nuitka.__past__ import unicode from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import getTargetPythonDLLPath, python_version from nuitka.utils import Execution, Utils from nuitka.utils.FileOperations import ( deleteFile, getExternalUsePath, getWindowsShortPathName, hasFilenameExtension, listDir, ) from nuitka.utils.SharedLibraries import detectBinaryMinMacOS from .SconsCaching import checkCachingSuccess from .SconsUtils import flushSconsReports def getSconsDataPath(): """Return path to where data for scons lives, e.g. static C source files.""" return os.path.dirname(__file__) def _getSconsInlinePath(): """Return path to inline copy of scons.""" return os.path.join(getSconsDataPath(), "inline_copy") def _getSconsBinaryCall(): """Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows, there it is mandatory. """ inline_path = os.path.join(_getSconsInlinePath(), "bin", "scons.py") if os.path.exists(inline_path): return [ _getPythonForSconsExePath(), "-W", "ignore", # Disable Python warnings in case of debug Python. getExternalUsePath(inline_path), ] else: scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] else: Tracing.scons_logger.sysexit( "Error, the inline copy of scons is not present, nor a scons binary in the PATH." ) def _getPythonSconsExePathWindows(): """Find Python for Scons on Windows. Only 3.5 or higher will do. """ # Ordered in the list of preference. python_dir = Execution.getPythonInstallPathWindows( supported=("3.5", "3.6", "3.7", "3.8", "3.9", "3.10") ) if python_dir is not None: return os.path.join(python_dir, "python.exe") else: return None def _getPythonForSconsExePath(): """Find a way to call any Python that works for Scons. Scons needs it as it doesn't support all Python versions. """ python_exe = Options.getPythonPathForScons() if python_exe is not None: return python_exe if python_version < 0x300 and not Utils.isWin32Windows(): # Python 2.6 and 2.7 are fine for scons on all platforms, but not # on Windows due to clcache usage. return sys.executable elif python_version >= 0x350: # Python 3.5 or higher work on all platforms. return sys.executable elif Utils.isWin32Windows(): python_exe = _getPythonSconsExePathWindows() if python_exe is not None: return python_exe else: Tracing.scons_logger.sysexit( """\ Error, while Nuitka works with older Python, Scons does not, and therefore Nuitka needs to find a Python 3.5 or higher executable, so please install it. You may provide it using option "--python-for-scons=path_to_python.exe" in case it is not visible in registry, e.g. due to using uninstalled Anaconda Python. """ ) for version_candidate in ("2.7", "2.6", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10"): candidate = Execution.getExecutablePath("python" + version_candidate) if candidate is not None: return candidate # Lets be optimistic, this is most often going to be new enough or a # Python2 variant. return "python" @contextlib.contextmanager def _setupSconsEnvironment(): """Setup the scons execution environment. For the target Python we provide "NUITKA_PYTHON_DLL_PATH" to see where the Python DLL lives, in case it needs to be copied, and then also the "NUITKA_PYTHON_EXE_PATH" to find the Python binary itself. We also need to preserve PYTHONPATH and PYTHONHOME, but remove it potentially as well, so not to confuse the other Python binary used to run scons. """ # For Python2, avoid unicode working directory. if Utils.isWin32Windows() and python_version < 0x300: if os.getcwd() != os.getcwdu(): os.chdir(getWindowsShortPathName(os.getcwdu())) if Utils.isWin32Windows() and not Options.shallUseStaticLibPython(): # On Win32, we use the Python.DLL path for some things. We pass it # via environment variable os.environ["NUITKA_PYTHON_DLL_PATH"] = getTargetPythonDLLPath() os.environ["NUITKA_PYTHON_EXE_PATH"] = sys.executable # Remove environment variables that can only harm if we have to switch # major Python versions, these cannot help Python2 to execute scons, this # is a bit of noise, but helpful. old_pythonpath = None old_pythonhome = None if python_version >= 0x300: if "PYTHONPATH" in os.environ: old_pythonpath = os.environ["PYTHONPATH"] del os.environ["PYTHONPATH"] if "PYTHONHOME" in os.environ: old_pythonhome = os.environ["PYTHONHOME"] del os.environ["PYTHONHOME"] import nuitka os.environ["NUITKA_PACKAGE_DIR"] = os.path.abspath(nuitka.__path__[0]) yield if old_pythonpath is not None: os.environ["PYTHONPATH"] = old_pythonpath if old_pythonhome is not None: os.environ["PYTHONHOME"] = old_pythonhome if "NUITKA_PYTHON_DLL_PATH" in os.environ: del os.environ["NUITKA_PYTHON_DLL_PATH"] del os.environ["NUITKA_PYTHON_EXE_PATH"] del os.environ["NUITKA_PACKAGE_DIR"] def _buildSconsCommand(quiet, options, scons_filename): """Build the scons command to run. The options are a dictionary to be passed to scons as a command line, and other scons stuff is set. """ scons_command = _getSconsBinaryCall() if quiet: scons_command.append("--quiet") scons_command += [ # The scons file "-f", getExternalUsePath(os.path.join(getSconsDataPath(), scons_filename)), # Parallel compilation. "--jobs", str(Options.getJobLimit()), # Do not warn about deprecation from Scons "--warn=no-deprecated", # Don't load "site_scons" at all. "--no-site-dir", ] if Options.isShowScons(): scons_command.append("--debug=stacktrace") # Python2, encoding unicode values def encode(value): if str is bytes and type(value) is unicode: return value.encode("utf8") else: return value # Option values to provide to scons. Find these in the caller. for key, value in options.items(): if value is None: Tracing.scons_logger.sysexit( "Error, failure to provide argument for '%s', please report bug." % key ) scons_command.append(key + "=" + encode(value)) # Python2, make argument encoding recognizable. if str is bytes: scons_command.append("arg_encoding=utf8") return scons_command def runScons(options, quiet, scons_filename): with _setupSconsEnvironment(): if Options.shallCompileWithoutBuildDirectory(): # Make sure we become non-local, by changing all paths to be # absolute, but ones that can be resolved by any program # externally, as the Python of Scons may not be good at unicode. options = copy.deepcopy(options) source_dir = options["source_dir"] options["source_dir"] = "." options["result_name"] = getExternalUsePath( options["result_name"], only_dirname=True ) options["nuitka_src"] = getExternalUsePath(options["nuitka_src"]) if "result_exe" in options: options["result_exe"] = getExternalUsePath( options["result_exe"], only_dirname=True ) if "compiled_exe" in options: options["compiled_exe"] = getExternalUsePath( options["compiled_exe"], only_dirname=True ) else: source_dir = None scons_command = _buildSconsCommand( quiet=quiet, options=options, scons_filename=scons_filename ) if Options.isShowScons(): Tracing.printLine("Scons command:", " ".join(scons_command)) Tracing.flushStandardOutputs() # Call scons, make sure to pass on quiet setting. with Execution.withEnvironmentVarOverriden( "NUITKA_QUIET", "1" if Tracing.is_quiet else "0" ): result = subprocess.call(scons_command, shell=False, cwd=source_dir) flushSconsReports() if result == 0: checkCachingSuccess(source_dir or options["source_dir"]) return result == 0 def asBoolStr(value): """Encode booleans for transfer via command line.""" return "true" if value else "false" def cleanSconsDirectory(source_dir): """Clean scons build directory.""" extensions = ( ".bin", ".c", ".cpp", ".exp", ".h", ".lib", ".manifest", ".o", ".obj", ".os", ".rc", ".res", ".S", ".txt", ".const", ".gcda", ".pgd", ".pgc", ) def check(path): if hasFilenameExtension(path, extensions): deleteFile(path, must_exist=True) if os.path.isdir(source_dir): for path, _filename in listDir(source_dir): check(path) static_dir = os.path.join(source_dir, "static_src") if os.path.exists(static_dir): for path, _filename in listDir(static_dir): check(path) plugins_dir = os.path.join(source_dir, "plugins") if os.path.exists(plugins_dir): for path, _filename in listDir(plugins_dir): check(path) def setCommonOptions(options): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches if Options.shallRunInDebugger(): options["full_names"] = "true" if Options.assumeYesForDownloads(): options["assume_yes_for_downloads"] = asBoolStr(True) if not Options.shallUseProgressBar(): options["progress_bar"] = "false" if Options.isClang(): options["clang_mode"] = "true" if Options.isShowScons(): options["show_scons"] = "true" if Options.isMingw64(): options["mingw_mode"] = "true" if Options.getMsvcVersion(): msvc_version = Options.getMsvcVersion() msvc_version = msvc_version.replace("exp", "Exp") if "." not in msvc_version and msvc_version != "latest": msvc_version += ".0" options["msvc_version"] = msvc_version if Options.shallDisableCCacheUsage(): options["disable_ccache"] = asBoolStr(True) if Options.shallDisableConsoleWindow(): options["disable_console"] = asBoolStr(True) if Options.getLtoMode() != "auto": options["lto_mode"] = Options.getLtoMode() cpp_defines = Plugins.getPreprocessorSymbols() if cpp_defines: options["cpp_defines"] = ",".join( "%s%s%s" % (key, "=" if value else "", value or "") for key, value in cpp_defines.items() ) link_dirs = Plugins.getExtraLinkDirectories() if link_dirs: options["link_dirs"] = ",".join(link_dirs) link_libraries = Plugins.getExtraLinkLibraries() if link_libraries: options["link_libraries"] = ",".join(link_libraries) if Utils.isMacOS() and Options.isStandaloneMode(): macos_minversion = os.environ.get("MACOSX_DEPLOYMENT_TARGET") if macos_minversion is None: macos_minversion = detectBinaryMinMacOS(sys.executable) if macos_minversion is None: Tracing.general.warning( "Could not detect minimum macOS version for %r." % sys.executable ) # Default, but not a good idea. macos_minversion = "10.9" options["macos_minversion"] = macos_minversion Nuitka-0.6.19.1/nuitka/build/SconsSpawn.py0000600000372100037210000002426114166627112025336 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Spawning processes. This is to replace the standard spawn implementation with one that tracks the progress, and gives warnings about things taking very long. """ import os import sys import threading from nuitka.Tracing import my_print, scons_logger from nuitka.utils.Execution import executeProcess from nuitka.utils.Timing import TimerReport from .SconsCaching import runClCache from .SconsProgress import closeSconsProgressBar, updateSconsProgressBar from .SconsUtils import decodeData # Thread class to run a command class SubprocessThread(threading.Thread): def __init__(self, cmdline, env): threading.Thread.__init__(self) self.cmdline = cmdline self.env = env self.data = None self.err = None self.exit_code = None self.exception = None self.timer_report = TimerReport( message="Running %s took %%.2f seconds" % repr(self.cmdline).replace("%", "%%"), min_report_time=60, logger=scons_logger, ) def run(self): try: # execute the command, queue the result with self.timer_report: self.data, self.err, self.exit_code = executeProcess( command=self.cmdline, env=self.env ) except Exception as e: # will rethrow all, pylint: disable=broad-except self.exception = e def getProcessResult(self): return self.data, self.err, self.exit_code, self.exception def runProcessMonitored(cmdline, env): thread = SubprocessThread(cmdline, env) thread.start() # Allow a minute before warning for long compile time. thread.join(60) if thread.is_alive(): scons_logger.info( "Slow C compilation detected, used %.0fs so far, this might indicate scalability problems." % thread.timer_report.getTimer().getDelta() ) thread.join() updateSconsProgressBar() return thread.getProcessResult() def _filterMsvcLinkOutput(env, module_mode, data, exit_code): # Training newline in some cases, esp. LTO it seems. data = data.rstrip() if module_mode: data = b"\r\n".join( line for line in data.split(b"\r\n") if b" Creating library" not in line # On localized compilers, the message to ignore is not as clear. if not (module_mode and b".exp" in line) ) # The linker will say generating code at the end, due to localization # we don't know. if env.lto_mode and exit_code == 0: if len(data.split(b"\r\n")) == 2: data = b"" if env.pgo_mode == "use" and exit_code == 0: # Very spammy, partially in native language for PGO link. data = b"" return data # To work around Windows not supporting command lines of greater than 10K by # default: def getWindowsSpawnFunction(env, module_mode, source_files): def spawnWindowsCommand( sh, escape, cmd, args, os_env ): # pylint: disable=unused-argument # The "del" appears to not work reliably, but is used with large amounts of # files to link. So, lets do this ourselves, plus it avoids a process # spawn. if cmd == "del": assert len(args) == 2 os.unlink(args[1]) return 0 # For quoted arguments that end in a backslash, things don't work well # this is a workaround for it. def removeTrailingSlashQuote(arg): if arg.endswith(r"\""): return arg[:-1] + '\\"' else: return arg newargs = " ".join(removeTrailingSlashQuote(arg) for arg in args[1:]) cmdline = cmd + " " + newargs # Special hook for clcache inline copy if cmd == "": data, err, rv = runClCache(args, os_env) else: data, err, rv, exception = runProcessMonitored(cmdline, os_env) if exception: closeSconsProgressBar() raise exception if cmd == "link": data = _filterMsvcLinkOutput( env=env, module_mode=module_mode, data=data, exit_code=rv ) elif cmd in ("cl", ""): # Skip forced output from cl.exe data = data[data.find(b"\r\n") + 2 :] source_basenames = [ os.path.basename(source_file) for source_file in source_files ] def check(line): return line in (b"", b"Generating Code...") or line in source_basenames data = ( b"\r\n".join(line for line in data.split(b"\r\n") if not check(line)) + b"\r\n" ) if data is not None and data.rstrip(): my_print("Unexpected output from this command:", style="yellow") my_print(cmdline, style="yellow") if str is not bytes: data = decodeData(data) my_print(data, style="yellow", end="") if err: if str is not bytes: err = decodeData(err) my_print(err, style="yellow", end="") return rv return spawnWindowsCommand def _unescape(arg): # Undo the damage that scons did to pass it to "sh" arg = arg.strip('"') slash = "\\" special = '"$()' arg = arg.replace(slash + slash, slash) for c in special: arg = arg.replace(slash + c, c) return arg def isIgnoredError(line): # Many cases, pylint: disable=too-many-return-statements # Debian Python2 static libpython lto warnings: if b"function `posix_tmpnam':" in line: return True if b"function `posix_tempnam':" in line: return True # Self compiled Python2 static libpython lot warnings: if b"the use of `tmpnam_r' is dangerous" in line: return True if b"the use of `tempnam' is dangerous" in line: return True if line.startswith((b"Objects/structseq.c:", b"Python/import.c:")): return True if line == b"In function 'load_next',": return True if b"at Python/import.c" in line: return True # Bullseys when compiling in directory with spaces: if b"overriding recipe for target" in line: return True if b"ignoring old recipe for target" in line: return True if b"Error 1 (ignored)" in line: return True # Trusty has buggy toolchain that does this with LTO. if ( line == b"""\ bytearrayobject.o (symbol from plugin): warning: memset used with constant zero \ length parameter; this could be due to transposed parameters""" ): return True # The gcc LTO with debug information is deeply buggy with many messages: if b"Dwarf Error:" in line: return True return False def subprocess_spawn(args): sh, _cmd, args, env = args _stdout, stderr, exit_code = executeProcess( command=[sh, "-c", " ".join(args)], env=env ) ignore_next = False for line in stderr.splitlines(): if ignore_next: ignore_next = False continue if isIgnoredError(line): ignore_next = True continue if str is not bytes: line = decodeData(line) my_print(line, style="yellow", file=sys.stderr) return exit_code class SpawnThread(threading.Thread): def __init__(self, *args): threading.Thread.__init__(self) self.args = args self.timer_report = TimerReport( message="Running %s took %%.2f seconds" % (" ".join(_unescape(arg) for arg in self.args[2]).replace("%", "%%"),), min_report_time=60, logger=scons_logger, ) self.result = None self.exception = None def run(self): try: # execute the command, queue the result with self.timer_report: self.result = subprocess_spawn(self.args) except Exception as e: # will rethrow all, pylint: disable=broad-except self.exception = e def getSpawnResult(self): return self.result, self.exception def runSpawnMonitored(sh, cmd, args, env): thread = SpawnThread(sh, cmd, args, env) thread.start() # Allow a minute before warning for long compile time. thread.join(60) if thread.is_alive(): scons_logger.info( "Slow C compilation detected, used %.0fs so far, this might indicate scalability problems." % thread.timer_report.getTimer().getDelta() ) thread.join() updateSconsProgressBar() return thread.getSpawnResult() def getWrappedSpawnFunction(): def spawnCommand(sh, escape, cmd, args, env): # signature needed towards Scons core, pylint: disable=unused-argument # Avoid using ccache on binary constants blob, not useful and not working # with old ccache. if '"__constants_data.o"' in args or '"__constants_data.os"' in args: env = dict(env) env["CCACHE_DISABLE"] = "1" result, exception = runSpawnMonitored(sh, cmd, args, env) if exception: closeSconsProgressBar() raise exception return result return spawnCommand def enableSpawnMonitoring(env, win_target, module_mode, source_files): if win_target: env["SPAWN"] = getWindowsSpawnFunction( env=env, module_mode=module_mode, source_files=source_files ) else: env["SPAWN"] = getWrappedSpawnFunction() Nuitka-0.6.19.1/nuitka/build/DataComposerInterface.py0000600000372100037210000000414614166627112027442 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Interface to data composer """ import os import subprocess import sys from nuitka.Options import isExperimental from nuitka.utils.Execution import withEnvironmentVarsOverriden def runDataComposer(source_dir): data_composer_path = os.path.normpath( os.path.join(os.path.dirname(__file__), "..", "tools", "data_composer") ) mapping = { "NUITKA_PACKAGE_HOME": os.path.dirname( os.path.abspath(sys.modules["nuitka"].__path__[0]) ) } if isExperimental("debug-constants"): mapping["NUITKA_DATACOMPOSER_VERBOSE"] = "1" blob_filename = getConstantBlobFilename(source_dir) with withEnvironmentVarsOverriden(mapping): subprocess.check_call( [ sys.executable, data_composer_path, source_dir, blob_filename, ], shell=False, ) return blob_filename def getConstantBlobFilename(source_dir): return os.path.join(source_dir, "__constants.bin") def deriveModuleConstantsBlobName(filename): assert filename.endswith(".const") basename = filename[:-6] if basename == "__constants": return "" elif basename == "__bytecode": return ".bytecode" else: # Strip "module." prefix" basename = basename[7:] return basename Nuitka-0.6.19.1/nuitka/build/SconsCaching.py0000600000372100037210000003230114166627112025574 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Caching of C compiler output. """ import os import platform import re import sys from collections import defaultdict from nuitka.Tracing import scons_details_logger, scons_logger from nuitka.utils.AppDirs import getCacheDir from nuitka.utils.Download import getCachedDownload from nuitka.utils.FileOperations import ( areSamePaths, getExternalUsePath, getFileContentByLine, getFileContents, getLinkTarget, makePath, ) from nuitka.utils.Importing import importFromInlineCopy from nuitka.utils.Utils import isMacOS, isWin32Windows from .SconsUtils import ( getExecutablePath, getSconsReportValue, setEnvironmentVariable, ) def _getPythonDirCandidates(python_prefix): result = [python_prefix] for python_dir in ( sys.prefix, os.environ.get("CONDA_PREFIX"), os.environ.get("CONDA"), ): if python_dir and python_dir not in result: result.append(python_dir) return result def _getCcacheGuessedPaths(python_prefix): if isWin32Windows(): # Search the compiling Python, the Scons Python (likely the same, but not necessarily) # and then Anaconda, if an environment variable present from activated, or installed in # CI like Github actions. for python_dir in _getPythonDirCandidates(python_prefix): yield os.path.join(python_dir, "bin", "ccache.exe") yield os.path.join(python_dir, "scripts", "ccache.exe") elif isMacOS(): # For macOS, we might find Homebrew ccache installed but not in PATH. yield "/usr/local/opt/ccache" def _injectCcache(env, cc_path, python_prefix, target_arch, assume_yes_for_downloads): ccache_binary = os.environ.get("NUITKA_CCACHE_BINARY") # If not provided, search it in PATH and guessed directories. if ccache_binary is None: ccache_binary = getExecutablePath("ccache", env=env) if ccache_binary is None: for candidate in _getCcacheGuessedPaths(python_prefix): scons_details_logger.info( "Checking if ccache is at '%s' guessed path." % candidate ) if os.path.exists(candidate): ccache_binary = candidate scons_details_logger.info( "Using ccache '%s' from guessed path." % ccache_binary ) break if ccache_binary is None: if isWin32Windows(): url = "https://github.com/ccache/ccache/releases/download/v3.7.12/ccache-3.7.12-windows-32.zip" ccache_binary = getCachedDownload( url=url, is_arch_specific=False, specifity=url.rsplit("/", 2)[1], flatten=True, binary="ccache.exe", message="Nuitka will make use of ccache to speed up repeated compilation.", reject=None, assume_yes_for_downloads=assume_yes_for_downloads, ) elif isMacOS(): # TODO: Do not yet have M1 access to create one and 10.14 is minimum # we managed to compile ccache for. if target_arch != "arm64" and tuple( int(d) for d in platform.release().split(".") ) >= (18, 2): url = "https://nuitka.net/ccache/v4.2.1/ccache-4.2.1.zip" ccache_binary = getCachedDownload( url=url, is_arch_specific=False, specifity=url.rsplit("/", 2)[1], flatten=True, binary="ccache", message="Nuitka will make use of ccache to speed up repeated compilation.", reject=None, assume_yes_for_downloads=assume_yes_for_downloads, ) else: scons_details_logger.info( "Using ccache '%s' from NUITKA_CCACHE_BINARY environment variable." % ccache_binary ) if ccache_binary is not None and os.path.exists(ccache_binary): # Make sure the # In case we are on Windows, make sure the Anaconda form runs outside of Anaconda # environment, by adding DLL folder to PATH. assert areSamePaths( getExecutablePath(os.path.basename(env.the_compiler), env=env), cc_path ) # We use absolute paths for CC, pass it like this, as ccache does not like absolute. env["CXX"] = env["CC"] = '"%s" "%s"' % (ccache_binary, cc_path) # Spare ccache the detection of the compiler, seems it will also misbehave when it's # prefixed with "ccache" on old gcc versions in terms of detecting need for C++ linkage. env["LINK"] = cc_path scons_details_logger.info( "Found ccache '%s' to cache C compilation result." % ccache_binary ) scons_details_logger.info( "Providing real CC path '%s' via PATH extension." % cc_path ) else: if isWin32Windows(): scons_logger.warning( "Didn't find ccache for C level caching, follow Nuitka User Manual description." ) def enableCcache( env, source_dir, python_prefix, target_arch, assume_yes_for_downloads, ): # The ccache needs absolute path, otherwise it will not work. ccache_logfile = os.path.abspath( os.path.join(source_dir, "ccache-%d.txt" % os.getpid()) ) setEnvironmentVariable(env, "CCACHE_LOGFILE", ccache_logfile) env["CCACHE_LOGFILE"] = ccache_logfile # Unless asked to do otherwise, store ccache files in our own directory. if "CCACHE_DIR" not in os.environ: ccache_dir = os.path.join(getCacheDir(), "ccache") makePath(ccache_dir) ccache_dir = getExternalUsePath(ccache_dir) setEnvironmentVariable(env, "CCACHE_DIR", ccache_dir) env["CCACHE_DIR"] = ccache_dir # First check if it's not already supposed to be a ccache, then do nothing. cc_path = getExecutablePath(env.the_compiler, env=env) cc_is_link, cc_link_path = getLinkTarget(cc_path) if cc_is_link and os.path.basename(cc_link_path) == "ccache": scons_details_logger.info( "Chosen compiler %s is pointing to ccache %s already." % (cc_path, cc_link_path) ) return True return _injectCcache( env=env, cc_path=cc_path, python_prefix=python_prefix, target_arch=target_arch, assume_yes_for_downloads=assume_yes_for_downloads, ) def enableClcache(env, source_dir): importFromInlineCopy("atomicwrites", must_exist=True) importFromInlineCopy("clcache", must_exist=True) # Avoid importing this in threads, triggers CPython 3.9 importing bugs at least, # do it now, so it's not a race issue. import concurrent.futures.thread # pylint: disable=I0021,unused-import,unused-variable cl_binary = getExecutablePath(env.the_compiler, env) # The compiler is passed via environment. setEnvironmentVariable(env, "CLCACHE_CL", cl_binary) env["CXX"] = env["CC"] = "" setEnvironmentVariable(env, "CLCACHE_HIDE_OUTPUTS", "1") # The clcache stats filename needs absolute path, otherwise it will not work. clcache_stats_filename = os.path.abspath( os.path.join(source_dir, "clcache-stats.%d.txt" % os.getpid()) ) setEnvironmentVariable(env, "CLCACHE_STATS", clcache_stats_filename) env["CLCACHE_STATS"] = clcache_stats_filename # Unless asked to do otherwise, store ccache files in our own directory. if "CLCACHE_DIR" not in os.environ: clcache_dir = os.path.join(getCacheDir(), "clcache") makePath(clcache_dir) clcache_dir = getExternalUsePath(clcache_dir) setEnvironmentVariable(env, "CLCACHE_DIR", clcache_dir) env["CLCACHE_DIR"] = clcache_dir scons_details_logger.info( "Using inline copy of clcache with %r cl binary." % cl_binary ) def _getCcacheStatistics(ccache_logfile): data = {} if os.path.exists(ccache_logfile): re_command = re.compile(r"\[.*? (\d+) *\] Command line: (.*)$") re_result = re.compile(r"\[.*? (\d+) *\] Result: (.*)$") re_anything = re.compile(r"\[.*? (\d+) *\] (.*)$") # Remember command from the pid, so later decision logged against pid # can be matched against it. commands = {} for line in getFileContentByLine(ccache_logfile): match = re_command.match(line) if match: pid, command = match.groups() commands[pid] = command match = re_result.match(line) if match: pid, result = match.groups() result = result.strip() try: command = data[commands[pid]] except KeyError: # It seems writing to the file can be lossy, so we can have results for # unknown commands, but we don't use the command yet anyway, so just # be unique. command = "unknown command leading to " + line # Older ccache on e.g. RHEL6 wasn't explicit about linking. if result == "unsupported compiler option": if " -o " in command or "unknown command" in command: result = "called for link" # But still try to catch this with log output if it happens. if result == "unsupported compiler option": scons_logger.warning( "Encountered unsupported compiler option for ccache in '%s'." % command ) all_text = [] for line2 in getFileContentByLine(ccache_logfile): match = re_anything.match(line2) if match: pid2, result = match.groups() if pid == pid2: all_text.append(result) scons_logger.warning("Full scons output: %s" % all_text) if result != "called for link": data[command] = result return data def checkCachingSuccess(source_dir): ccache_logfile = getSconsReportValue(source_dir=source_dir, key="CCACHE_LOGFILE") if ccache_logfile is not None: stats = _getCcacheStatistics(ccache_logfile) if not stats: scons_logger.warning("You are not using ccache.") else: counts = defaultdict(int) for _command, result in stats.items(): # These are not important to our users, time based decisions differentiate these. if result in ("cache hit (direct)", "cache hit (preprocessed)"): result = "cache hit" # Usage of incbin causes this for the constants blob integration. if result == "unsupported code directive": continue counts[result] += 1 scons_logger.info("Compiled %d C files using ccache." % len(stats)) for result, count in counts.items(): scons_logger.info( "Cached C files (using ccache) with result '%s': %d" % (result, count) ) if os.name == "nt": clcache_stats_filename = getSconsReportValue( source_dir=source_dir, key="CLCACHE_STATS" ) if clcache_stats_filename is not None and os.path.exists( clcache_stats_filename ): stats = eval( # lazy, pylint: disable=eval-used getFileContents(clcache_stats_filename) ) clcache_hit = stats["CacheHits"] clcache_miss = stats["CacheMisses"] scons_logger.info( "Compiled %d C files using clcache with %d cache hits and %d cache misses." % (clcache_hit + clcache_miss, clcache_hit, clcache_miss) ) def runClCache(args, env): # pylint: disable=I0021,import-error,no-name-in-module,redefined-outer-name from clcache.caching import runClCache # No Python2 compatibility if str is bytes: scons_logger.sysexit("Error, cannot use Python2 for scons when using MSVC.") # The first argument is "" and should not be used. return runClCache( os.environ["CLCACHE_CL"], [arg.strip('"') for arg in args[1:]], env ) Nuitka-0.6.19.1/nuitka/build/SconsHacks.py0000600000372100037210000001166414166627112025302 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Hacks for scons that we apply. We block some tools from the standard scan, there is e.g. no need to ask what fortran version we have installed to compile with Nuitka. Also we hack the gcc version detection to fix some bugs in it, and to avoid scanning for g++ when we have a gcc installer, but only if that is not too version. """ import os import re import subprocess import SCons.Tool.gcc # pylint: disable=I0021,import-error from SCons.Script import Environment # pylint: disable=I0021,import-error from nuitka.Tracing import scons_details_logger from nuitka.utils.FileOperations import openTextFile from .SconsUtils import decodeData, getExecutablePath, isGccName # Cache for detected versions. v_cache = {} # Prevent these programs from being found, avoiding the burden of tool init. _blocked_tools = ( # TODO: Where the fallback is needed, g++ needs to scanned or else it # cannot be used. # "g++", "c++", "f95", "f90", "f77", "gfortran", "ifort", "javah", "tar", "dmd", "gdc", "flex", "bison", "ranlib", "ar", "ldc2", "pdflatex", "pdftex", "latex", "tex", "dvipdf", "dvips", "gs", "swig", "ifl", "rpcgen", "rpmbuild", "bk", "p4", "m4", "ml", "icc", "sccs", "rcs", "cvs", "as", "gas", "nasm", ) def _myDetectVersion(env, clvar): clvar0 = os.path.basename(clvar[0]) if isGccName(clvar0) or "clang" in clvar0: command = clvar + ("-dumpversion",) else: command = clvar + ("--version",) # pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'], pipe = SCons.Action._subproc( # pylint: disable=protected-access env, command, stdin="devnull", stderr="devnull", stdout=subprocess.PIPE ) line = pipe.stdout.readline() # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer: # So continue with reading to let the child process actually terminate. while pipe.stdout.readline(): pass ret = pipe.wait() if ret != 0: scons_details_logger.info( "Error, error exit from '%s' (%d) gave %r." % (command, ret, pipe.stderr.read()) ) return None if str is not bytes and type(line) is bytes: line = decodeData(line) line = line.strip() match = re.findall(r"[0-9]+(?:\.[0-9]+)+", line) if match: version = match[0] else: # gcc 8 or higher version = line.strip() version = tuple(int(part) for part in version.split(".")) return version # From gcc.py of Scons def myDetectVersion(env, cc): """Return the version of the GNU compiler, or None if it is not a GNU compiler.""" cc = env.subst(cc) if not cc: return None if "++" in os.path.basename(cc): return None # Make path absolute, to improve cache hit rate. cc = getExecutablePath(cc, env) if cc is None: return None if cc not in v_cache: v_cache[cc] = _myDetectVersion(env, (cc,)) scons_details_logger.info("CC %r version check gives %r" % (cc, v_cache[cc])) return v_cache[cc] def myDetect(self, progs): # Don't consider Fortran, tar, D, c++, we don't need it. We do manual # fallback for blocked_tool in _blocked_tools: if blocked_tool in progs: return None return orig_detect(self, progs) # The original value will be used in our form. orig_detect = Environment.Detect def getEnhancedToolDetect(): SCons.Tool.gcc.detect_version = myDetectVersion return myDetect def makeGccUseLinkerFile(source_dir, source_files, env): tmp_linker_filename = os.path.join(source_dir, "@link_input.txt") env["LINKCOM"] = env["LINKCOM"].replace( "$SOURCES", "@%s" % env.get("ESCAPE", lambda x: x)(tmp_linker_filename) ) with openTextFile(tmp_linker_filename, "w") as tmpfile: for filename in source_files: filename = ".".join(filename.split(".")[:-1]) + ".o" if os.name == "nt": filename = filename.replace(os.path.sep, "/") tmpfile.write('"%s"\n' % filename) tmpfile.write(env.subst("$SOURCES")) Nuitka-0.6.19.1/nuitka/build/Onefile.scons0000600000372100037210000005154214167275603025325 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- python -*- # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ The Onefile scons file for Windows, check out Backend.scons for where the actual compiled binaries are build. If you have Scons or Windows platform knowledge, please be especially invited and contribute improvements. This file is used to build a bootstrap binary that only unpacks the Python DLL and other data files needed, to have a onefile solution for Windows. """ # Make nuitka package importable from calling installation import sys import os import types sys.modules["nuitka"] = types.ModuleType("nuitka") sys.modules["nuitka"].__path__ = [os.environ["NUITKA_PACKAGE_DIR"]] # We are in the build.build package really. import nuitka.build # pylint: disable=unused-import __package__ = "nuitka.build" # pylint: disable=redefined-builtin # isort:start from SCons.Script import ( # pylint: disable=I0021,import-error ARGUMENTS, Environment, GetOption, ) from nuitka.Tracing import ( my_print, scons_details_logger, scons_logger, setQuiet, ) from .SconsCaching import enableCcache, enableClcache from .SconsCompilerSettings import ( checkWindowsCompilerFound, reportCCompiler, setupCCompiler, switchFromGccToGpp, ) from .SconsHacks import getEnhancedToolDetect from .SconsProgress import enableSconsProgressBar, setSconsProgressBarTotal from .SconsSpawn import enableSpawnMonitoring from .SconsUtils import ( addClangClPathFromMSVC, addToPATH, changeKeyboardInteruptToErrorExit, createDefinitionsFile, createEnvironment, getArgumentBool, getArgumentDefaulted, getArgumentList, getArgumentRequired, getExecutablePath, getMsvcVersion, getMsvcVersionString, initScons, isGccName, provideStaticSourceFile, raiseNoCompilerFoundErrorExit, setArguments, setupScons, writeSconsReport, ) # Set the arguments. setArguments(ARGUMENTS) # Set up the basic stuff. initScons() # The directory containing the C files generated by Nuitka to be built using # scons. They are referred to as sources from here on. source_dir = getArgumentRequired("source_dir") # The directory containing Nuitka provided C files to be built and where it # should be used. nuitka_src = getArgumentRequired("nuitka_src") static_src = os.path.join(source_dir, "static") # The name of executable or extension module that we produce. result_basepath = getArgumentRequired("result_name") # The name of executable that we produce result_exe = getArgumentDefaulted("result_exe", None) # The name of executable that we that copy resources from compiled_exe = getArgumentDefaulted("compiled_exe", None) # The suffix for an extension module (in module mode). module_suffix = getArgumentDefaulted("module_suffix", None) # Full names shall be used, no remapping for cacheable filenames. full_names = getArgumentBool("full_names", False) # Module mode: Create a Python extension module, create an executable otherwise. module_mode = getArgumentBool("module_mode", False) # Debug mode: Less optimizations, debug information in the resulting binary. debug_mode = getArgumentBool("debug_mode", False) # Experimental indications. Do things that are not yet safe to do. experimental = getArgumentList("experimental", "") # Tracing mode. Output program progress. trace_mode = getArgumentBool("trace_mode", False) # LTO mode: Use link time optimizations of C compiler if available and known # good with the compiler in question. lto_mode = getArgumentDefaulted("lto_mode", "auto") # Windows target mode: Compile for Windows. Used to be an option, but we # no longer cross compile this way. win_target = os.name == "nt" # Windows subsystem mode: Disable console for windows builds. disable_console = getArgumentBool("disable_console", False) # Unstriped mode: Do not remove debug symbols. unstripped_mode = getArgumentBool("unstripped_mode", False) # Target arch, uses for compiler choice and quick linking of constants binary # data. target_arch = ARGUMENTS["target_arch"] # MinGW compiler mode, optional and interesting to Windows only. mingw_mode = getArgumentBool("mingw_mode", False) # Clang compiler mode, forced on macOS and FreeBSD (excluding PowerPC), optional on Linux. clang_mode = getArgumentBool("clang_mode", False) # For the msys2 python, we can know a few things, it's not Win32 entirely. msys2_mingw_python = getArgumentBool("msys2_mingw_python", False) # Clang on Windows with no requirement to use MinGW64 or using MSYS2 MinGW flavor, # is changed to ClangCL from Visual Studio. clangcl_mode = False if win_target and not (mingw_mode or msys2_mingw_python) and clang_mode: clang_mode = False clangcl_mode = True # Show scons mode, output information about Scons operation show_scons_mode = getArgumentBool("show_scons", False) scons_details_logger.is_quiet = not show_scons_mode if int(os.environ.get("NUITKA_QUIET", "0")): setQuiet() # Home of Python to be compiled against, used to find tools like clcache and # ccache, no linking against Python is needed here. python_prefix = getArgumentRequired("python_prefix") # Forced MSVC version (windows-only) msvc_version = getArgumentDefaulted("msvc_version", None) # Disable ccache usage if requested disable_ccache = getArgumentBool("disable_ccache", False) # Preprocessor defines and link libraries from plugins cpp_defines = getArgumentList("cpp_defines", "") link_dirs = getArgumentList("link_dirs", "") link_libraries = getArgumentList("link_libraries", "") # Mode to only output compiler information, for use in "nuitka --version" # only. compiler_version_mode = getArgumentBool("compiler_version", False) assume_yes_for_downloads = getArgumentBool("assume_yes_for_downloads", False) # Onefile compression is optional. onefile_compression = getArgumentBool("onefile_compression", False) # Onefile bootstrap is opptional. onefile_splash_screen = getArgumentBool("onefile_splash_screen", False) # Minimum version required on macOS. macos_minversion = getArgumentDefaulted("macos_minversion", "") if getArgumentBool("progress_bar", True) and not show_scons_mode: enableSconsProgressBar() def printCompilerVersionOutput(*args): if compiler_version_mode or show_scons_mode: my_print("Scons:", *args) # Amount of jobs to use. job_count = GetOption("num_jobs") # Add environment specified compilers to the PATH variable. if "CC" in os.environ: os.environ["CC"] = os.path.normpath(os.environ["CC"]) if os.path.isdir(os.environ["CC"]): sys.exit("Error, the CC variable must point to file, not directory.") cc_dirname = os.path.dirname(os.environ["CC"]) if win_target and isGccName(os.path.basename(os.environ["CC"])): if show_scons_mode: my_print("Scons: Environment CC seems to be a gcc, enable mingw_mode.") mingw_mode = True if os.path.isdir(cc_dirname): addToPATH(None, cc_dirname, prefix=True) printCompilerVersionOutput("CC=%r" % os.environ["CC"]) if "CXX" in os.environ: os.environ["CXX"] = os.path.normpath(os.environ["CXX"]) if os.path.isdir(os.environ["CXX"]): sys.exit("Error, the CXX variable must point to file, not directory.") cxx_dirname = os.path.dirname(os.environ["CXX"]) if win_target and isGccName(os.path.basename(os.environ["CXX"])): if show_scons_mode: my_print("Scons: Environment CXX seems to be a gcc, enable mingw_mode.") mingw_mode = True if os.path.isdir(cxx_dirname): os.environ["PATH"] = os.pathsep.join( [cxx_dirname] + os.environ["PATH"].split(os.pathsep) ) printCompilerVersionOutput("CXX=%r" % os.environ["CXX"]) # Patch the compiler detection. Environment.Detect = getEnhancedToolDetect() # Create Scons environment, the main control tool. Don't include "mingw" on # Windows immediately, we will default to MSVC if available. env = createEnvironment( mingw_mode=mingw_mode, msvc_version=msvc_version, target_arch=target_arch, experimental=experimental, ) scons_details_logger.info("Initial CC: %r" % env.get("CC")) scons_details_logger.info( "Initial CCVERSION: %r" % (env.get("CCVERSION"),), ) if "CC" in os.environ: # If the environment variable CC is set, use that. env["CC"] = os.path.expanduser(os.environ["CC"]) env["CCVERSION"] = None scons_details_logger.info("Overridden with environment CC: %r" % env["CC"]) elif clangcl_mode: # If possible, add Clang directory from MSVC if available. addClangClPathFromMSVC(env=env, target_arch=target_arch) elif clang_mode: # If requested by the user, use the clang compiler, overriding what was # said in environment. env["CC"] = "clang" env["CCVERSION"] = None # On Windows, in case MSVC was not found and not previously forced, use the # winlibs MinGW64 as a download, and use it as a fallback. env = checkWindowsCompilerFound( env=env, target_arch=target_arch, clang_mode=clang_mode, msvc_version=msvc_version, assume_yes_for_downloads=assume_yes_for_downloads, ) env.the_compiler = env["CC"] or env["CXX"] env.the_cc_name = os.path.normcase(os.path.basename(env.the_compiler)) env.standalone_mode = True # We are only used in this case. env.debug_mode = debug_mode env.source_dir = source_dir env.low_memory = False # Never a concern in this case. env.macos_minversion = macos_minversion scons_logger.info("Onefile C compiler: %s (%s)." % (env.the_compiler, env.the_cc_name)) # Requested or user provided, detect if it's clang even from environment if "clang" in env.the_cc_name and "-cl" not in env.the_cc_name: clang_mode = True env["CCVERSION"] = None # We consider clang to be a form of gcc for the most things, they strive to # be compatible. env.gcc_mode = isGccName(env.the_cc_name) or clang_mode env.clang_mode = clang_mode # Only use MSVC if not already clear, we are using MinGW. env.msvc_mode = win_target and not env.gcc_mode env.mingw_mode = win_target and env.gcc_mode env.clangcl_mode = clangcl_mode # Python specific modes have to influence some decisions, but not # for Onefile. env.nuitka_python = False env.debian_python = False env.msys2_mingw_python = False env.static_libpython = None # Consider switching from gcc to its g++ compiler as a workaround that makes us work without C11. switchFromGccToGpp( env=env, ) if env.the_compiler is None or getExecutablePath(env.the_compiler, env=env) is None: raiseNoCompilerFoundErrorExit() if show_scons_mode: my_print("Scons: Compiler used", end=" ") my_print(getExecutablePath(env.the_compiler, env=env), end=" ") if win_target and env.msvc_mode: my_print("(MSVC %s)" % getMsvcVersionString(env)) my_print() # Set build directory and scons general settings. setupScons(env, source_dir) # Report the C compiler used. reportCCompiler(env, "Onefile") # Set up C compiler settings. setupCCompiler( env=env, lto_mode=lto_mode, pgo_mode="no", # TODO: Have this here too, decompression might benefit. job_count=job_count, ) # Avoid them as appearing to be different files. TODO: Find out which # clang version has this, clang-8 does not. if env.gcc_mode and not env.clang_mode and env.gcc_version >= (8,): if source_dir != "." and not full_names: # TODO: This also lies for modules codes. env.Append( CCFLAGS=[ "--file-prefix-map=%s=%s" % (os.path.normpath(source_dir), "."), "--file-prefix-map=%s=%s" % ( os.path.normpath(os.path.join(source_dir, "static_src")), os.path.normpath(os.path.join(nuitka_src, "static_src")), ), ] ) if env.msvc_mode: # With Clang on Windows, there is also an linker to use. env.Append( CCFLAGS=[ "/EHsc", # No C++ exception handling code. "/J", # default char type is unsigned. "/Gd", # Use C calling convention by default. "/bigobj", # Product object files with larger internal limits. ] ) # No incremental linking. env.Append(LINKFLAGS=["/INCREMENTAL:NO"]) if debug_mode: if env.gcc_mode: # Allow gcc/clang to point out all kinds of inconsistency to us by # raising an error. env.Append( CCFLAGS=[ "-Wall", "-Werror", # Unfortunately Py_INCREF(Py_False) triggers aliasing warnings, # which are unfounded, so disable them. "-Wno-error=strict-aliasing", "-Wno-strict-aliasing", # At least for self-compiled Python3.2, and MinGW this happens # and has little use anyway. "-Wno-error=format", "-Wno-format", ] ) elif env.msvc_mode: # Disable warnings that system headers already show. env.Append( CCFLAGS=[ "/W4", "/wd4505", "/wd4127", "/wd4100", "/wd4702", "/wd4189", "/wd4211", "/WX", ] ) # Disable warnings, the first 3 are for Python headers, maybe not needed. env.Append(CCFLAGS=["/wd4512", "/wd4510", "/wd4610", "/wd4996"]) if trace_mode: env.Append(CPPDEFINES=["_NUITKA_TRACE"]) # For MinGW and cross compilation, we need to tell the subsystem # to target as well as to automatically import everything used. if win_target: if env.gcc_mode: if not env.clang_mode: env.Append(LINKFLAGS=["-Wl,--enable-auto-import"]) if disable_console: env.Append(LINKFLAGS=["-Wl,--subsystem,windows"]) if disable_console: env.Append(CPPDEFINES=["_NUITKA_WINMAIN_ENTRY_POINT"]) # For shell API usage to lookup app folders we need this. if env.msvc_mode: env.Append(LIBS=["Shell32"]) # The static include files reside in Nuitka installation, which may be where # the "nuitka.build" package lives. nuitka_include = os.path.join(nuitka_src, "include") if not os.path.exists(os.path.join(nuitka_include, "nuitka", "prelude.h")): sys.exit( "Error, cannot locate Nuitka includes at '%s', broken installation." % nuitka_include ) # We have include files in the build directory and the static include directory # that is located inside Nuitka installation, as well as an inline copy of zstd # that should be found. env.Append( CPPPATH=[ source_dir, nuitka_include, os.path.join(nuitka_src, "static_src"), os.path.join(nuitka_src, "inline_copy", "zstd"), ], ) if debug_mode or unstripped_mode: # Use debug format, so we get good tracebacks from it. if env.gcc_mode: env.Append(CCFLAGS=["-g"]) env.Append(ASFLAGS=["-g"]) if not env.clang_mode: env.Append(CCFLAGS=["-feliminate-unused-debug-types"]) elif env.msvc_mode: env.Append(CCFLAGS=["/Z7"]) # Higher MSVC versions need this for parallel compilation if job_count > 1 and getMsvcVersion(env) >= 11: env.Append(CCFLAGS=["/FS"]) env.Append(LINKFLAGS=["/DEBUG"]) else: if env.gcc_mode: if not env.clang_mode: env.Append(LINKFLAGS=["-s"]) # Tell compiler to create a program. if env.msvc_mode: env.Append(CCFLAGS=["/MT"]) # Multithreaded, static version of C run time. def discoverSourceFiles(): result = [] # If we use C11 capable compiler, all good. Otherwise use C++, which Scons # needs to derive from filenames, so make copies (or links) with a different # name. def _scanSourceDir(dirname): if not os.path.exists(dirname): return for filename in sorted(os.listdir(dirname)): # Only C files are of interest here. if not filename.endswith((".c", "cpp")) or not filename.startswith( ("module.", "__", "plugin.") ): continue filename = os.path.join(dirname, filename) target_file = filename # We pretend to use C++ if no C11 compiler is present. if env.c11_mode: result.append(filename) else: if filename.endswith(".c"): target_file += "pp" # .cpp" suffix then os.rename(filename, target_file) result.append(target_file) # Scan for Nuitka created source files, and add them too. _scanSourceDir(source_dir) _scanSourceDir(os.path.join(source_dir, "plugins")) # Main onefile bootstrap program result.append( provideStaticSourceFile( sub_path="OnefileBootstrap.c", nuitka_src=nuitka_src, source_dir=source_dir, c11_mode=env.c11_mode, ) ) return result source_targets = [] source_files = discoverSourceFiles() target = env.Program(result_exe, source_files + source_targets) # Avoid dependency on MinGW libraries. if win_target and env.gcc_mode and not env.clang_mode: env.Append(LINKFLAGS=["-static-libgcc"]) # on Windows link against imagehlp to support signed applications detection if win_target: link_libraries.append("imagehlp") # Outside compiler settings are respected. if "CPPFLAGS" in os.environ: if show_scons_mode: my_print("Scons: Inherited CPPFLAGS='%s' variable." % os.environ["CPPFLAGS"]) env.Append(CPPFLAGS=os.environ["CPPFLAGS"].split()) if "CCFLAGS" in os.environ: if show_scons_mode: my_print("Scons: Inherited CCFLAGS='%s' variable." % os.environ["CCFLAGS"]) env.Append(CCFLAGS=os.environ["CCFLAGS"].split()) if "CXXFLAGS" in os.environ: if show_scons_mode: my_print("Scons: Inherited CXXFLAGS='%s' variable." % os.environ["CXXFLAGS"]) env.Append(CXXFLAGS=os.environ["CXXFLAGS"].split()) # Outside linker flags are respected. if "LDFLAGS" in os.environ: if show_scons_mode: my_print("Scons: Inherited LDFLAGS='%s' variable." % os.environ["LDFLAGS"]) env.Append(LINKFLAGS=os.environ["LDFLAGS"].split()) # Remove the target file to avoid cases where it falsely doesn't get rebuild # and then lingers from previous builds, if os.path.exists(target[0].abspath): os.unlink(target[0].abspath) if job_count: scons_details_logger.info("Told to run compilation on %d CPUs." % job_count) # Plugin contributed C defines should be used too. env.Append(CPPDEFINES=cpp_defines) # Plugin contributed link dirs should be used too. env.Append(LIBPATH=link_dirs) # Plugin contributed link libraries should be used too. env.Append(LIBS=link_libraries) # Work around windows bugs and use watchdogs to track progress of compilation. enableSpawnMonitoring( env=env, win_target=win_target, module_mode=module_mode, source_files=source_files, ) # Before we go, also lets turn KeyboardInterrupt into a mere error exit as the # scons traceback is not going to be very interesting to us. changeKeyboardInteruptToErrorExit() # Check if ccache is installed, and complain if it is not. if env.gcc_mode and not disable_ccache: enableCcache( env=env, source_dir=source_dir, python_prefix=python_prefix, target_arch=target_arch, assume_yes_for_downloads=assume_yes_for_downloads, ) if env.msvc_mode and not disable_ccache: enableClcache( env=env, source_dir=source_dir, ) onefile_definitions = {} if "ONEFILE_COMPANY" in os.environ: onefile_definitions["ONEFILE_COMPANY"] = os.environ["ONEFILE_COMPANY"] onefile_definitions["ONEFILE_PRODUCT"] = os.environ["ONEFILE_PRODUCT"] onefile_definitions["ONEFILE_VERSION"] = os.environ["ONEFILE_VERSION"] if "ONEFILE_TEMP_SPEC" in os.environ: onefile_definitions["_NUITKA_ONEFILE_TEMP_SPEC"] = os.environ["ONEFILE_TEMP_SPEC"] onefile_definitions["_NUITKA_ONEFILE_TEMP"] = 1 else: onefile_definitions["_NUITKA_ONEFILE_TEMP"] = 0 if onefile_compression: onefile_definitions["_NUITKA_ONEFILE_COMPRESSION"] = 1 if onefile_splash_screen: onefile_definitions["_NUITKA_ONEFILE_SPLASH_SCREEN"] = 1 env.Append(LIBS=["Ole32", "Windowscodecs", "User32", "Gdi32", "Shlwapi"]) createDefinitionsFile(source_dir, "onefile_definitions.h", onefile_definitions) writeSconsReport( env=env, source_dir=source_dir, ) setSconsProgressBarTotal(name="Onefile", total=len(source_files)) scons_details_logger.info("Launching Scons target: %s" % target) env.Default(target) Nuitka-0.6.19.1/nuitka/build/Backend.scons0000600000372100037210000010525214167275603025271 0ustar nuitka-buildslavenuitka-buildslave00000000000000# -*- python -*- # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ The Nuitka scons file. If you have Scons or platform knowledge, please be especially invited and contribute improvements. This file is used to build an executable or shared library. Nuitka needs no build process for itself, although it can be compiled using the same method. """ # Make nuitka package importable from calling installation import sys import os import types sys.modules["nuitka"] = types.ModuleType("nuitka") sys.modules["nuitka"].__path__ = [os.environ["NUITKA_PACKAGE_DIR"]] # We are in the build.build package really. import nuitka.build # pylint: disable=unused-import __package__ = "nuitka.build" # pylint: disable=redefined-builtin # isort:start from SCons.Script import ( # pylint: disable=I0021,import-error ARGUMENTS, Environment, GetOption, ) from nuitka.Tracing import ( my_print, scons_details_logger, scons_logger, setQuiet, ) from nuitka.utils.Execution import check_output from nuitka.utils.Json import loadJsonFromFilename from nuitka.utils.Utils import isDebianBasedLinux, isNetBSD from .SconsCaching import enableCcache, enableClcache from .SconsCompilerSettings import ( addConstantBlobFile, checkWindowsCompilerFound, decideConstantsBlobResourceMode, enableWindowsStackSize, reportCCompiler, setupCCompiler, switchFromGccToGpp, ) from .SconsHacks import getEnhancedToolDetect, makeGccUseLinkerFile from .SconsProgress import enableSconsProgressBar, setSconsProgressBarTotal from .SconsSpawn import enableSpawnMonitoring from .SconsUtils import ( addClangClPathFromMSVC, addToPATH, changeKeyboardInteruptToErrorExit, createDefinitionsFile, createEnvironment, getArgumentBool, getArgumentDefaulted, getArgumentInt, getArgumentList, getArgumentRequired, getExecutablePath, getMsvcVersion, getMsvcVersionString, initScons, isGccName, provideStaticSourceFile, raiseNoCompilerFoundErrorExit, scanSourceDir, setArguments, setupScons, writeSconsReport, ) # Set the arguments. setArguments(ARGUMENTS) # Set up the basic stuff. initScons() # The directory containing the C files generated by Nuitka to be built using # scons. They are referred to as sources from here on. source_dir = getArgumentRequired("source_dir") # The directory containing Nuitka provided C files to be built and where it # should be used. nuitka_src = getArgumentRequired("nuitka_src") static_src = os.path.join(source_dir, "static") # The name of executable or extension module that we produce. result_basepath = getArgumentRequired("result_name") # The name of executable that we produce (in executable mode). result_exe = getArgumentDefaulted("result_exe", None) # Name of the main program (in executable mode, typically __main__ but can be in a package too.) main_module_name = getArgumentDefaulted("main_module_name", "__main__") # The suffix for an extension module (in module mode). module_suffix = getArgumentDefaulted("module_suffix", None) # Full names shall be used, no remapping for cacheable filenames. full_names = getArgumentBool("full_names", False) # Module mode: Create a Python extension module, create an executable otherwise. module_mode = getArgumentBool("module_mode", False) # Debug mode: Less optimizations, debug information in the resulting binary. debug_mode = getArgumentBool("debug_mode", False) # Profiling mode: Outputs vmprof based information from program run. profile_mode = getArgumentBool("profile_mode", False) # Python version to target. python_version_str = getArgumentRequired("python_version") python_version = tuple(int(d) for d in python_version_str.split(".")) # The ABI flags to target. abiflags = getArgumentDefaulted("abiflags", "") python_abi_version = python_version_str + abiflags # Our own Python fork, for which we know a lot of optimization can be done. nuitka_python = getArgumentBool("nuitka_python", False) # The Debian Python, for which we know that some optimization can be done. debian_python = getArgumentBool("debian_python", False) # For the msys2 python, we can know a few things, it's not Win32 entirely. msys2_mingw_python = getArgumentBool("msys2_mingw_python", False) # Python debug mode: reference count checking, assertions in CPython core. python_debug = getArgumentBool("python_debug", False) # Full compatibility, even where it's stupid, i.e. do not provide information, # even if available, in order to assert maximum compatibility. Intended to # control level of compatibility to absurd. full_compat_mode = getArgumentBool("full_compat", False) # Experimental indications. Do things that are not yet safe to do. experimental = getArgumentList("experimental", "") # Tracing mode. Output program progress. trace_mode = getArgumentBool("trace_mode", False) # LTO mode: Use link time optimizations of C compiler if available and known # good with the compiler in question. lto_mode = getArgumentDefaulted("lto_mode", "auto") # PGO mode: Use profile guided optimization of C compiler if available. pgo_mode = getArgumentDefaulted("pgo_mode", "no") static_libpython = getArgumentDefaulted("static_libpython", "") if static_libpython: assert os.path.exists(static_libpython), static_libpython # Windows target mode: Compile for Windows. Used to be an option, but we # no longer cross compile this way. win_target = os.name == "nt" noelf_mode = getArgumentBool("noelf_mode", False) macosx_target = sys.platform == "darwin" # Windows subsystem mode: Disable console for windows builds. disable_console = getArgumentBool("disable_console", False) # Windows might be running a Python whose DLL we have to use. uninstalled_python = getArgumentBool("uninstalled_python", False) # Unstriped mode: Do not remove debug symbols. unstripped_mode = getArgumentBool("unstripped_mode", False) # Target arch, uses for compiler choice and quick linking of constants binary # data. target_arch = getArgumentRequired("target_arch") # MinGW compiler mode, optional and interesting to Windows only. mingw_mode = getArgumentBool("mingw_mode", False) # Clang compiler mode, forced on macOS and FreeBSD (excluding PowerPC), optional on Linux. clang_mode = getArgumentBool("clang_mode", False) # Clang on Windows with no requirement to use MinGW64 or using MSYS2 MinGW flavor, # is changed to ClangCL from Visual Studio. clangcl_mode = False if win_target and not mingw_mode and clang_mode: clang_mode = False clangcl_mode = True # Shared library and compiled modules count, determines the need for the # compiled module loader. module_count = getArgumentInt("module_count") # Frozen modules count, determines the need for the bytecode frozen # modules loader. frozen_modules = getArgumentInt("frozen_modules", 0) # Standalone mode standalone_mode = getArgumentBool("standalone_mode", False) # Onefile mode onefile_mode = getArgumentBool("onefile_mode", False) # Onefile temp mode onefile_temp_mode = getArgumentBool("onefile_temp_mode", False) forced_stdout_path = getArgumentDefaulted("forced_stdout_path", None) forced_stderr_path = getArgumentDefaulted("forced_stderr_path", None) # Show scons mode, output information about Scons operation show_scons_mode = getArgumentBool("show_scons", False) scons_details_logger.is_quiet = not show_scons_mode if int(os.environ.get("NUITKA_QUIET", "0")): setQuiet() # Home of Python to be compiled against, used to find include files and # libraries to link against. python_prefix = getArgumentRequired("python_prefix") # Forced MSVC version (windows-only) msvc_version = getArgumentDefaulted("msvc_version", None) # Disable ccache usage if requested disable_ccache = getArgumentBool("disable_ccache", False) no_python_warnings = getArgumentBool("no_python_warnings", False) # sys.flags values to pass along # python_sysflag_py3k_warning python_sysflag_py3k_warning = getArgumentBool("python_sysflag_py3k_warning", False) # python_sysflag_division_warning python_sysflag_division_warning = getArgumentBool( "python_sysflag_division_warning", False ) # python_sysflag_division_warning python_sysflag_bytes_warning = getArgumentBool("python_sysflag_bytes_warning", False) # python_sysflag_no_site python_sysflag_no_site = getArgumentBool("python_sysflag_no_site", False) # python_sysflag_verbose python_sysflag_verbose = getArgumentBool("python_sysflag_verbose", False) # python_sysflag_unicode python_sysflag_unicode = getArgumentBool("python_sysflag_unicode", False) # python_sysflag_utf8 python_sysflag_utf8 = getArgumentBool("python_sysflag_utf8", False) # python_sysflag_optimize python_sysflag_optimize = getArgumentBool("python_sysflag_optimize", False) # python_sysflag_no_randomization python_sysflag_no_randomization = getArgumentBool( "python_sysflag_no_randomization", False ) # Preprocessor defines from plugins cpp_defines = getArgumentList("cpp_defines", "") link_dirs = getArgumentList("link_dirs", "") link_libraries = getArgumentList("link_libraries", "") # Mode to only output compiler information, for use in "nuitka --version" # only. compiler_version_mode = getArgumentBool("compiler_version", False) # Allow automatic downloads for ccache, etc. assume_yes_for_downloads = getArgumentBool("assume_yes_for_downloads", False) # Low memory mode, compile using less memory if possible. low_memory = getArgumentBool("low_memory", False) # Minimum version required on macOS. macos_minversion = getArgumentDefaulted("macos_minversion", "") if getArgumentBool("progress_bar", True) and not show_scons_mode: enableSconsProgressBar() def printCompilerVersionOutput(*args): if compiler_version_mode or show_scons_mode: my_print("Scons:", *args) # Amount of jobs to use. job_count = GetOption("num_jobs") # Add environment specified compilers to the PATH variable. if "CC" in os.environ: os.environ["CC"] = os.path.normpath(os.environ["CC"]) if os.path.isdir(os.environ["CC"]): scons_logger.sysexit( "Error, the CC variable must point to file, not directory." ) if os.path.sep in os.environ["CC"]: cc_dirname = os.path.dirname(os.environ["CC"]) if os.path.isdir(cc_dirname): addToPATH(None, cc_dirname, prefix=True) if win_target and isGccName(os.path.basename(os.environ["CC"])): scons_details_logger.info( "Environment CC seems to be a gcc, enabling mingw_mode." ) mingw_mode = True printCompilerVersionOutput("CC=%r" % os.environ["CC"]) # Patch the compiler detection. Environment.Detect = getEnhancedToolDetect() # Create Scons environment, the main control tool. Don't include "mingw" on # Windows immediately, we will default to MSVC if available. env = createEnvironment( mingw_mode=mingw_mode, msvc_version=msvc_version, target_arch=target_arch, experimental=experimental, ) scons_details_logger.info("Initial CC: %r" % env.get("CC")) scons_details_logger.info( "Initial CCVERSION: %r" % (env.get("CCVERSION"),), ) if "CC" in os.environ: # If the environment variable CC is set, use that. env["CC"] = os.path.expanduser(os.environ["CC"]) env["CCVERSION"] = None scons_details_logger.info("Overridden with environment CC: %r" % env["CC"]) elif clangcl_mode: # If possible, add Clang directory from MSVC if available. addClangClPathFromMSVC(env=env, target_arch=target_arch) elif clang_mode: # If requested by the user, use the clang compiler, overriding what was # said in environment. env["CC"] = "clang" env["CCVERSION"] = None # On Windows, in case MSVC was not found and not previously forced, use the # winlibs MinGW64 as a download, and use it as a fallback. env = checkWindowsCompilerFound( env=env, target_arch=target_arch, clang_mode=clang_mode, msvc_version=msvc_version, assume_yes_for_downloads=assume_yes_for_downloads, ) env.the_compiler = env["CC"] env.the_cc_name = os.path.normcase(os.path.basename(env.the_compiler)) env.standalone_mode = standalone_mode env.debug_mode = debug_mode env.source_dir = source_dir env.low_memory = low_memory env.macos_minversion = macos_minversion # Various flavors could influence builds. env.anaconda_python = getArgumentBool("anaconda_python", False) env.pyenv_python = getArgumentBool("pyenv_python", False) env.apple_python = getArgumentBool("pyenv_python", False) # Requested or user provided, detect if it's clang even from environment if "clang" in env.the_cc_name and "-cl" not in env.the_cc_name: clang_mode = True env["CCVERSION"] = None # We consider clang to be a form of gcc for the most things, they strive to # be compatible. env.gcc_mode = isGccName(env.the_cc_name) or clang_mode env.clang_mode = clang_mode # Only use MSVC if not already clear, we are using MinGW. env.msvc_mode = win_target and not env.gcc_mode env.mingw_mode = win_target and env.gcc_mode env.clangcl_mode = clangcl_mode # Python specific modes have to influence some decisions env.nuitka_python = nuitka_python env.debian_python = debian_python env.msys2_mingw_python = msys2_mingw_python env.static_libpython = static_libpython # Consider switching from gcc to its g++ compiler as a workaround that makes us work without C11. switchFromGccToGpp( env=env, ) if env.the_compiler is None or getExecutablePath(env.the_compiler, env=env) is None: raiseNoCompilerFoundErrorExit() no_import_lib = False if show_scons_mode: my_print("Scons: Compiler used", end=" ") my_print(getExecutablePath(env.the_compiler, env=env), end=" ") if win_target and env.msvc_mode: my_print("(MSVC %s)" % getMsvcVersionString(env)) my_print() # Set build directory and scons general settings. setupScons(env, source_dir) # Report the C compiler used. reportCCompiler(env, "Backend") # Set up C compiler settings. setupCCompiler( env=env, lto_mode=lto_mode, pgo_mode=pgo_mode, job_count=job_count, ) # Avoid them as appearing to be different files. TODO: Find out which # clang version has this, clang-8 does not. if env.gcc_mode and not env.clang_mode and env.gcc_version >= (8,): if source_dir != "." and not full_names: # TODO: This also lies for modules codes. env.Append( CCFLAGS=[ "--file-prefix-map=%s=%s" % (os.path.normpath(source_dir), "."), "--file-prefix-map=%s=%s" % ( os.path.normpath(os.path.join(source_dir, "static_src")), os.path.normpath(os.path.join(nuitka_src, "static_src")), ), ] ) if env.gcc_mode and not noelf_mode and not macosx_target: env.Append(LINKFLAGS=["-z", "noexecstack"]) if env.msvc_mode: # With Clang on Windows, there is also an linker to use. env.Append( CCFLAGS=[ "/EHsc", # No C++ exception handling code. "/J", # default char type is unsigned. "/Gd", # Use C calling convention by default. "/bigobj", # Product object files with larger internal limits. ] ) # No incremental linking. env.Append(LINKFLAGS=["/INCREMENTAL:NO"]) if module_mode: # Make sure we handle import library on our own and put it into the # build directory. no_import_lib = True env.Append( LINKFLAGS=[ "/INCREMENTAL:NO", "/IMPLIB:%s" % os.path.join(source_dir, "import.lib"), ] ) if not module_mode: enableWindowsStackSize(env=env, target_arch=target_arch) if env.debug_mode: if env.gcc_mode: # Allow gcc/clang to point out all kinds of inconsistency to us by # raising an error. env.Append( CCFLAGS=[ "-Wall", "-Werror", # Unfortunately Py_INCREF(Py_False) triggers aliasing warnings, # which are unfounded, so disable them. "-Wno-error=strict-aliasing", "-Wno-strict-aliasing", # At least for self-compiled Python3.2, and MinGW this happens # and has little use anyway. "-Wno-error=format", "-Wno-format", ] ) elif env.msvc_mode: # Disable warnings that system headers already show. env.Append( CCFLAGS=[ "/W4", "/wd4505", "/wd4127", "/wd4100", "/wd4702", "/wd4189", "/wd4211", "/wd4115", "/WX", ] ) # Disable warnings, that CPython headers already show. if python_version >= (3, 4): env.Append(CCFLAGS=["/wd4512", "/wd4510", "/wd4610"]) env.Append(CCFLAGS=["/wd4996"]) if full_compat_mode: env.Append(CPPDEFINES=["_NUITKA_FULL_COMPAT"]) if profile_mode: env.Append(CPPDEFINES=["_NUITKA_PROFILE"]) if trace_mode: env.Append(CPPDEFINES=["_NUITKA_TRACE"]) if env.standalone_mode: env.Append(CPPDEFINES=["_NUITKA_STANDALONE"]) if onefile_mode: env.Append(CPPDEFINES=["_NUITKA_ONEFILE"]) if onefile_temp_mode: env.Append(CPPDEFINES=["_NUITKA_ONEFILE_TEMP"]) # We need "dl" in accelerated mode. if "linux" in sys.platform: env.Append(LIBS=["dl"]) if not env.msvc_mode: env.Append(LIBS=["m"]) if win_target: # For MinGW and cross compilation, we need to tell the subsystem # to target as well as to automatically import everything used. if env.gcc_mode: if not clang_mode: env.Append(LINKFLAGS=["-Wl,--enable-auto-import"]) if disable_console: env.Append(LINKFLAGS=["-Wl,--subsystem,windows"]) if disable_console: env.Append(CPPDEFINES=["_NUITKA_WINMAIN_ENTRY_POINT"]) if python_debug: env.Append(CPPDEFINES=["Py_DEBUG"]) if static_libpython: env.Append(CPPDEFINES=["Py_NO_ENABLE_SHARED"]) def detectHostMultiarch(): stdout = check_output("dpkg-architecture") for line in stdout.splitlines(): line = line.strip() if line.startswith(b"DEB_HOST_MULTIARCH="): return line.split("=", 1)[1].decode("utf8") return None if env.gcc_mode and debian_python: # TODO: Seems rather meaningless nowadays and hard codes this to not be # self compiled or so. if python_version == (3, 3): host_multiarch = detectHostMultiarch() if host_multiarch is not None: env.Append( CCFLAGS=[ "-I" + os.path.join( "/usr/include/", host_multiarch, "python" + python_abi_version ) ] ) def _detectPythonHeaderPath(): if win_target: # On Windows, the CPython installation layout is relatively fixed, but on MSYS2 # compiled for mingw64, it's more standard. candidates = [ os.path.join(python_prefix, "include"), # On MSYS2 with MinGW64 Python, it is also the other form. os.path.join(python_prefix, "include", "python" + python_abi_version), ] else: # The python header path is a combination of python version and debug # indication, we make sure the headers are found by adding it to the C # include path. candidates = [ os.path.join(python_prefix, "include", "python" + python_abi_version), # Haiku specific paths: os.path.join( python_prefix, "develop/headers", "python" + python_abi_version ), ] for candidate in candidates: if os.path.exists(os.path.join(candidate, "Python.h")): return candidate if win_target: scons_logger.sysexit( """Error, you seem to be using the unsupported embeddable CPython distribution.""" ) else: scons_logger.sysexit( """\ Error, no 'Python.h' %s headers can be found at '%s', dependency \ not satisfied!""" % ("debug" if python_debug else "development", candidates) ) env.Append(CPPPATH=[_detectPythonHeaderPath()]) # To support self-built Python on Windows, need to also add the "PC" directory, # that a normal install won't have. if os.name == "nt": python_header_path = os.path.join(python_prefix, "PC") if os.path.exists(python_header_path): env.Append(CPPPATH=[python_header_path]) def getWindowsPythonDLLPath(): return os.environ["NUITKA_PYTHON_DLL_PATH"] if nuitka_python: env.Append(CPPDEFINES=["_NUITKA_PYTHON"]) if static_libpython: env.Append(CPPDEFINES=["_NUITKA_STATIC_LIBPYTHON"]) if static_libpython and (not win_target or nuitka_python): env.Append(CPPDEFINES=["_NUITKA_USE_UNEXPOSED_API"]) if win_target: if nuitka_python: env.Append( LINKFLAGS=[ "/LTCG", "/USEPROFILE:PGD=" + os.path.join(python_prefix, "python.pgd"), ] ) link_data = loadJsonFromFilename(os.path.join(python_prefix, "link.json")) env.Append(LIBS=link_data["libraries"]) env.Append(LIBPATH=link_data["library_dirs"]) for define, value in link_data["macros"]: if value: env.Append(CPPDEFINES=[define + "=" + value]) else: env.Append(CPPDEFINES=[define]) elif env.gcc_mode and static_libpython: env.Append(LIBS=[env.File(static_libpython)]) else: # Some non CPython flavors on Windows have this. def addWinLib(): # Make sure to locate the Python link library from multiple potential # locations (installed vs. self-built). if python_debug: win_lib_name = "python" + python_abi_version.replace(".", "") + "_d" else: win_lib_name = "python" + python_abi_version.replace(".", "") if python_version >= (3,): pc_build_dir = ( "PCBuild/amd64" if target_arch == "x86_64" else "PCBuild/win32" ) else: pc_build_dir = "PCBuild" for candidate in ("libs", pc_build_dir): win_lib_path = os.path.join(python_prefix, candidate) if os.path.exists(os.path.join(win_lib_path, win_lib_name + ".lib")): break else: scons_logger.sysexit("Error, cannot find '%s.lib' file." % win_lib_name) env.Append(LIBPATH=[win_lib_path]) env.Append(LIBS=[win_lib_name]) if not msys2_mingw_python: addWinLib() elif not module_mode: # Add the python library path to the library path python_lib_path = os.path.join(python_prefix, "lib") env.Append(LIBPATH=[python_lib_path]) if nuitka_python and "pgo-link" in experimental: # With Nuitka-Python, we do not use the static link library actually, but # instead we link against the object files, as otherwise gcc doesn't seem # to want to pick the profiling information up. TODO: This is not showing # any benefit over plain LTO yet. pgo_dir = os.path.join(python_prefix, "lib/pgo") env.Append(LINKFLAGS=["-fprofile-dir=%s" % pgo_dir]) env.Append(LINKFLAGS=["-fprofile-correction"]) for filename in check_output(["ar", "t", static_libpython]).splitlines(): filename = os.path.join(pgo_dir, filename) if not filename.endswith(".o"): continue if os.path.basename(filename) in ("main.o", "python.o"): continue gcda_filename = filename[:-2] + ".gcda" if os.path.exists(gcda_filename): env.Append( LINKFLAGS=["-fprofile-use=%s" % os.path.basename(gcda_filename)] ) env.Append(LIBS=[env.File(filename)]) elif static_libpython: env.Append(LIBS=[env.File(static_libpython)]) # The linker won't succeed in searching for those for system Python of Debian # compiled Pythons. Help that. For self-compiled, if python_prefix == "/usr" and isDebianBasedLinux(): env.Append(LIBS=["z", "m", "util", "pthread"]) if python_version >= (3,): env.Append(LIBS=["expat"]) env.Append(LINKFLAGS=["-Xlinker", "-export-dynamic", "-rdynamic"]) else: # Debian and Ubuntu distinguish the system libraries like this. if ( python_debug and python_prefix == "/usr" and python_version < (3,) and isDebianBasedLinux() ): env.Append(LIBS=["python" + python_abi_version + "_d"]) else: env.Append(LIBS=["python" + python_abi_version]) if python_prefix != "/usr" and "linux" in sys.platform: env.Append(LIBS=["dl", "pthread", "util", "rt", "m"]) if env.gcc_mode and not clang_mode: env.Append(LINKFLAGS=["-export-dynamic"]) # For NetBSD the rpath is required, on FreeBSD it's warned as unused. if isNetBSD(): env.Append(LINKFLAGS=["-rpath=" + python_lib_path]) elif macosx_target and module_mode: env.Append(LINKFLAGS=["-undefined", "dynamic_lookup"]) # The static include files reside in Nuitka installation, which may be where # the "nuitka.build" package lives. nuitka_include = os.path.join(nuitka_src, "include") if not os.path.exists(os.path.join(nuitka_include, "nuitka", "prelude.h")): scons_logger.sysexit( "Error, cannot locate Nuitka includes at '%s', this is a broken Nuitka installation." % nuitka_include ) # We have include files in the build directory and the static include directory # that is located inside Nuitka installation. env.Append(CPPPATH=[source_dir, nuitka_include, os.path.join(nuitka_src, "static_src")]) if env.debug_mode or unstripped_mode: # Use debug format, so we get good tracebacks from it. if env.gcc_mode: env.Append(LINKFLAGS=["-g"]) env.Append(CCFLAGS=["-g"]) env.Append(ASFLAGS=["-g"]) if not env.clang_mode: env.Append(CCFLAGS=["-feliminate-unused-debug-types"]) elif env.msvc_mode: env.Append(CCFLAGS=["/Z7"]) # Higher MSVC versions need this for parallel compilation if job_count > 1 and getMsvcVersion(env) >= 11: env.Append(CCFLAGS=["/FS"]) env.Append(LINKFLAGS=["/DEBUG"]) else: if env.gcc_mode: if macosx_target: env.Append(LINKFLAGS=["-Wno-deprecated-declarations"]) elif not env.clang_mode: env.Append(LINKFLAGS=["-s"]) # MinGW for 64 bits needs this due to CPython bugs. if win_target and target_arch == "x86_64" and env.gcc_mode: env.Append(CPPDEFINES=["MS_WIN64"]) # Set load libpython from binary directory default if env.gcc_mode and not macosx_target and not win_target and not module_mode: if env.standalone_mode: rpath = "$$ORIGIN" else: rpath = python_lib_path env.Append(LINKFLAGS=["-Wl,-R,'%s'" % rpath]) # The rpath is no longer used unless we do this on modern Linux. The # option name is not very revealing, but basically without this, the # rpath in the binary will be ignored by the loader. if "linux" in sys.platform: env.Append(LINKFLAGS=["-Wl,--disable-new-dtags"]) # For macOS we need to make sure install_name_tool can do its work if macosx_target and not module_mode: env.Append(LINKFLAGS=["-headerpad_max_install_names"]) addConstantBlobFile( env=env, resource_desc=decideConstantsBlobResourceMode(env=env, module_mode=module_mode), source_dir=source_dir, target_arch=target_arch, ) env.Append(CPPDEFINES=["_NUITKA_FROZEN=%d" % frozen_modules]) # Tell compiler to create a shared library or program. if module_mode: if isGccName(env.the_cc_name): env.Append(CCFLAGS=["-shared"]) elif env.clang_mode: pass elif env.msvc_mode: env.Append(CCFLAGS=["/LD"]) # Create a DLL. else: assert False, env.the_cc_name else: if env.msvc_mode: env.Append(CCFLAGS=["/MT"]) # Multithreaded, static version of C run time. if module_mode: env.Append(CPPDEFINES=["_NUITKA_MODULE"]) else: env.Append(CPPDEFINES=["_NUITKA_EXE"]) def discoverSourceFiles(): result = [] # Scan for Nuitka created source files, and add them too. result.extend(scanSourceDir(env=env, dirname=source_dir, plugins=False)) result.extend( scanSourceDir( env=env, dirname=os.path.join(source_dir, "plugins"), plugins=True, ) ) static_src_filenames = [] # Main program, unless of course it's a Python module/package we build. if not module_mode: static_src_filenames.append("MainProgram.c") # Compiled types. static_src_filenames.append("CompiledCellType.c") static_src_filenames.append("CompiledFunctionType.c") static_src_filenames.append("CompiledGeneratorType.c") # Helper codes. static_src_filenames.append("InspectPatcher.c") static_src_filenames.append("MetaPathBasedLoader.c") result += [ provideStaticSourceFile( sub_path=filename, nuitka_src=nuitka_src, source_dir=source_dir, c11_mode=env.c11_mode, ) for filename in static_src_filenames ] return result source_files = discoverSourceFiles() if module_mode: # For Python modules, the standard shared library extension is not what # gets used. env["SHLIBSUFFIX"] = module_suffix target = env.SharedLibrary( result_basepath, source_files, no_import_lib=no_import_lib ) else: target = env.Program(result_exe, source_files) # Avoid dependency on MinGW libraries. if win_target and env.gcc_mode and not env.clang_mode: env.Append(LINKFLAGS=["-static-libgcc"]) # Outside compiler settings are respected. if "CPPFLAGS" in os.environ: scons_logger.info( "Scons: Inherited CPPFLAGS='%s' variable." % os.environ["CPPFLAGS"] ) env.Append(CPPFLAGS=os.environ["CPPFLAGS"].split()) if "CCFLAGS" in os.environ: scons_logger.info("Inherited CCFLAGS='%s' variable." % os.environ["CCFLAGS"]) env.Append(CCFLAGS=os.environ["CCFLAGS"].split()) if "CXXFLAGS" in os.environ: scons_logger.info( "Scons: Inherited CXXFLAGS='%s' variable." % os.environ["CXXFLAGS"] ) env.Append(CXXFLAGS=os.environ["CXXFLAGS"].split()) # Outside linker flags are respected. if "LDFLAGS" in os.environ: scons_logger.info("Scons: Inherited LDFLAGS='%s' variable." % os.environ["LDFLAGS"]) env.Append(LINKFLAGS=os.environ["LDFLAGS"].split()) # Remove the target file to avoid cases where it falsely doesn't get rebuild # and then lingers from previous builds, if os.path.exists(target[0].abspath): os.unlink(target[0].abspath) if job_count: scons_details_logger.info("Told to run compilation on %d CPUs." % job_count) def createBuildDefinitionsFile(): build_definitions = {} if uninstalled_python and not static_libpython: if win_target: build_definitions["DLL_EXTRA_PATH"] = os.path.dirname( getWindowsPythonDLLPath() ) build_definitions["PYTHON_HOME_PATH"] = python_prefix build_definitions["NO_PYTHON_WARNINGS"] = 1 if no_python_warnings else 0 if python_version < (3,): build_definitions["SYSFLAG_PY3K_WARNING"] = ( 1 if python_sysflag_py3k_warning else 0 ) build_definitions["SYSFLAG_DIVISION_WARNING"] = ( 1 if python_sysflag_division_warning else 0 ) build_definitions["SYSFLAG_UNICODE"] = 1 if python_sysflag_unicode else 0 build_definitions["SYSFLAG_BYTES_WARNING"] = ( 1 if python_sysflag_bytes_warning else 0 ) build_definitions["SYSFLAG_NO_SITE"] = 1 if python_sysflag_no_site else 0 build_definitions["SYSFLAG_VERBOSE"] = 1 if python_sysflag_verbose else 0 build_definitions["SYSFLAG_UTF8"] = 1 if python_sysflag_utf8 else 0 build_definitions["SYSFLAG_OPTIMIZE"] = 1 if python_sysflag_optimize else 0 build_definitions["SYSFLAG_NO_RANDOMIZATION"] = ( 1 if python_sysflag_no_randomization else 0 ) if forced_stdout_path: build_definitions["NUITKA_FORCED_STDOUT_PATH"] = forced_stdout_path if forced_stderr_path: build_definitions["NUITKA_FORCED_STDERR_PATH"] = forced_stderr_path build_definitions["NUITKA_MAIN_MODULE_NAME"] = main_module_name if main_module_name != "__main__": build_definitions["NUITKA_MAIN_PACKAGE_MODE"] = 1 createDefinitionsFile(source_dir, "build_definitions.h", build_definitions) createBuildDefinitionsFile() # The meta path based loader might want to respect that, so it does verbose traces in module # mode, mostly for debugging purposes only. if module_mode and python_sysflag_verbose: env.Append(CPPDEFINES=["_NUITKA_SYSFLAG_VERBOSE=1"]) # Hack to make Scons use tempfile for gcc linking, to avoid line length limits, # which can make linking fail with many modules otherwise. Most needed on Windows, # but useful on other platforms too. if env.gcc_mode: makeGccUseLinkerFile(source_dir=source_dir, source_files=source_files, env=env) # Plugin contributed C defines should be used too. env.Append(CPPDEFINES=cpp_defines) # Plugin contributed link dirs should be used too. env.Append(LIBPATH=link_dirs) # Plugin contributed link libraries should be used too. env.Append(LIBS=link_libraries) # Work around windows bugs and use watchdogs to track progress of compilation. enableSpawnMonitoring( env=env, win_target=win_target, module_mode=module_mode, source_files=source_files, ) # Before we go, also lets turn KeyboardInterrupt into a mere error exit as the # scons traceback is not going to be very interesting to us. changeKeyboardInteruptToErrorExit() # Check if ccache is installed, and complain if it is not. if env.gcc_mode and not disable_ccache: enableCcache( env=env, source_dir=source_dir, python_prefix=python_prefix, target_arch=target_arch, assume_yes_for_downloads=assume_yes_for_downloads, ) if env.msvc_mode and not disable_ccache: enableClcache( env=env, source_dir=source_dir, ) writeSconsReport( env=env, source_dir=source_dir, ) setSconsProgressBarTotal(name=env.progressbar_name, total=len(source_files)) scons_details_logger.info("Launching Scons target: %s" % target) env.Default(target) Nuitka-0.6.19.1/nuitka/build/__init__.py0000600000372100037210000000150114166627112024767 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/freezer/0000700000372100037210000000000014167275622023230 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/freezer/RuntimeTracing.py0000600000372100037210000001477014166627112026542 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Runtime tracing At this time we detect DLLs used by a program with this code, such that we can check if it loads things outside of the program, but we can also use this to determine what to include, so some plugins will be using this. """ import os import re from nuitka.__past__ import subprocess from nuitka.utils.Execution import ( callProcess, isExecutableCommand, withEnvironmentVarOverriden, ) from nuitka.utils.Utils import getOS from .DependsExe import getDependsExePath, parseDependsExeOutput def getRuntimeTraceOfLoadedFiles(logger, command, required=False): """Returns the files loaded when executing a binary.""" # This will make a crazy amount of work, # pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements path = command[0] if not os.path.exists(path): logger.sysexit("Error, cannot find %r (%r)." % (path, os.path.abspath(path))) result = [] if os.name == "posix": if getOS() in ("Darwin", "FreeBSD"): if not isExecutableCommand("dtruss"): logger.sysexit( """\ Error, needs 'dtruss' on your system to scan used libraries.""" ) if not isExecutableCommand("sudo"): logger.sysexit( """\ Error, needs 'sudo' on your system to scan used libraries.""" ) args = ("sudo", "dtruss", "-t", "open", os.path.abspath(path)) else: if not isExecutableCommand("strace"): logger.sysexit( """\ Error, needs 'strace' on your system to scan used libraries.""" ) args = ( "strace", "-e", "file", "-s4096", # Some paths are truncated in output otherwise os.path.abspath(path), ) # Ensure executable is not polluted with third party stuff, # tests may fail otherwise due to unexpected libs being loaded with withEnvironmentVarOverriden("LD_PRELOAD", None): tracing_command = args[0] if args[0] != "sudo" else args[1] process = subprocess.Popen( args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) _stdout_strace, stderr_strace = process.communicate() exit_strace = process.returncode if exit_strace != 0: if str is not bytes: stderr_strace = stderr_strace.decode("utf8") logger.warning(stderr_strace) logger.sysexit("Failed to run %r." % tracing_command) with open(path + ".strace", "wb") as f: f.write(stderr_strace) for line in stderr_strace.split(b"\n"): if process.returncode != 0: logger.my_print(line) if not line: continue # Don't consider files not found. The "site" module checks lots # of things. if b"ENOENT" in line: continue if line.startswith(b"stat(") and b"S_IFDIR" in line: continue result.extend( os.path.abspath(match) for match in re.findall(b'"(.*?)(?:\\\\0)?"', line) ) if str is not bytes: result = [s.decode("utf8") for s in result] elif os.name == "nt": command = ( getDependsExePath(), "-c", # Console mode "-ot%s" % path + ".depends", "-f1", "-pb", "-pa1", # Turn on all profiling options. "-ps1", # Simulate ShellExecute with app dirs in PATH. "-pp1", # Do not long DllMain calls. "-po1", # Log DllMain call for all other messages. "-ph1", # Hook the process. "-pl1", # Log LoadLibrary calls. "-pt1", # Thread information. "-pe1", # First chance exceptions. "-pg1", # Log GetProcAddress calls. "-pf1", # Use full paths. "-pc1", # Profile child processes. ) + tuple(command) # TODO: Move the handling of this into nuitka.tools.Execution module methods. try: callProcess(command, timeout=5 * 60) except Exception as e: # Catch all the things, pylint: disable=broad-except if e.__class__.__name__ == "TimeoutExpired": if required: logger.sysexit( "Timeout encountered when running dependency walker." ) logger.warning("Timeout encountered when running dependency walker.") return [] else: raise result = parseDependsExeOutput(path + ".depends") os.unlink(path + ".depends") result = list(sorted(set(result))) return result if __name__ == "__main__": import sys from nuitka.Tracing import general from nuitka.utils.FileOperations import withTemporaryFile source_code = """ import sys from PySide2.QtQuick import QQuickView from PySide2.QtWidgets import QApplication from PySide2.QtCore import QUrl QApplication(sys.argv) viewer = QQuickView() viewer.setSource(QUrl.fromLocalFile(sys.argv[1])) """ qml_code = """ import QtQuick 2.0 """ with withTemporaryFile(suffix=".qml", delete=False) as qml_file: qml_file.write(qml_code) qml_filename = qml_file.name with withTemporaryFile(suffix=".py", delete=False) as temp_file: temp_file.write(source_code) temp_filename = temp_file.name getRuntimeTraceOfLoadedFiles( logger=general, command=[sys.executable, temp_filename, qml_filename] ) Nuitka-0.6.19.1/nuitka/freezer/Standalone.py0000600000372100037210000014326714166627112025703 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Pack and copy files for standalone mode. This is still under heavy evolution, but expected to work for macOS, Windows, and Linux. Patches for other platforms are very welcome. """ import hashlib import marshal import os import pkgutil import shutil import sys from nuitka import Options, SourceCodeReferences from nuitka.__past__ import iterItems from nuitka.Bytecodes import compileSourceToBytecode from nuitka.containers.odict import OrderedDict from nuitka.containers.oset import OrderedSet from nuitka.importing import ImportCache from nuitka.importing.Importing import locateModule from nuitka.importing.StandardLibrary import ( getStandardLibraryPaths, isStandardLibraryPath, ) from nuitka.nodes.ModuleNodes import ( PythonShlibModule, makeUncompiledPythonModule, ) from nuitka.plugins.Plugins import Plugins from nuitka.PythonVersions import python_version from nuitka.Tracing import general, inclusion_logger, printError from nuitka.tree.SourceReading import readSourceCodeFromFilename from nuitka.utils import Utils from nuitka.utils.AppDirs import getCacheDir from nuitka.utils.Execution import executeProcess, withEnvironmentPathAdded from nuitka.utils.FileOperations import ( areSamePaths, copyFileWithPermissions, getDirectoryRealPath, getFileContentByLine, getFileContents, getFileList, getSubDirectories, haveSameFileContents, listDir, makePath, putTextFileContents, relpath, resolveShellPatternToFilenames, withFileLock, ) from nuitka.utils.Importing import getSharedLibrarySuffixes from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.SharedLibraries import ( callInstallNameTool, getPyWin32Dir, getSharedLibraryRPATH, getWindowsDLLVersion, removeSxsFromDLL, setSharedLibraryRPATH, ) from nuitka.utils.Signing import removeMacOSCodeSignature from nuitka.utils.ThreadedExecutor import ThreadPoolExecutor, waitWorkers from nuitka.utils.Timing import TimerReport from .DependsExe import detectDLLsWithDependencyWalker from .IncludedDataFiles import ( IncludedDataDirectory, IncludedDataFile, makeIncludedDataFile, ) def loadCodeObjectData(precompiled_filename): # Ignoring magic numbers, etc. which we don't have to care for much as # CPython already checked them (would have rejected it otherwise). with open(precompiled_filename, "rb") as f: return f.read()[8:] module_names = set() def _detectedPrecompiledFile(filename, module_name, result, user_provided, technical): if filename.endswith(".pyc"): if os.path.isfile(filename[:-1]): return _detectedSourceFile( filename=filename[:-1], module_name=module_name, result=result, user_provided=user_provided, technical=technical, ) if module_name in module_names: return if Options.isShowInclusion(): inclusion_logger.info( "Freezing module '%s' (from '%s')." % (module_name, filename) ) uncompiled_module = makeUncompiledPythonModule( module_name=module_name, bytecode=loadCodeObjectData(precompiled_filename=filename), is_package="__init__" in filename, filename=filename, user_provided=user_provided, technical=technical, ) ImportCache.addImportedModule(uncompiled_module) result.append(uncompiled_module) module_names.add(module_name) def _detectedSourceFile(filename, module_name, result, user_provided, technical): if module_name in module_names: return if module_name == "collections.abc": _detectedSourceFile( filename=filename, module_name=ModuleName("_collections_abc"), result=result, user_provided=user_provided, technical=technical, ) source_code = readSourceCodeFromFilename(module_name, filename) if module_name == "site": if source_code.startswith("def ") or source_code.startswith("class "): source_code = "\n" + source_code source_code = """\ __file__ = (__nuitka_binary_dir + '%s%s') if '__nuitka_binary_dir' in dict(__builtins__ ) else '';%s""" % ( os.path.sep, os.path.basename(filename), source_code, ) # Debian stretch site.py source_code = source_code.replace( "PREFIXES = [sys.prefix, sys.exec_prefix]", "PREFIXES = []" ) if Options.isShowInclusion(): inclusion_logger.info( "Freezing module '%s' (from '%s')." % (module_name, filename) ) is_package = os.path.basename(filename) == "__init__.py" # Plugins can modify source code: source_code = Plugins.onFrozenModuleSourceCode( module_name=module_name, is_package=is_package, source_code=source_code ) bytecode = compileSourceToBytecode( source_code=source_code, filename=module_name.replace(".", os.path.sep) + ".py", ) # Plugins can modify bytecode code: bytecode = Plugins.onFrozenModuleBytecode( module_name=module_name, is_package=is_package, bytecode=bytecode ) uncompiled_module = makeUncompiledPythonModule( module_name=module_name, bytecode=marshal.dumps(bytecode), is_package=is_package, filename=filename, user_provided=user_provided, technical=technical, ) ImportCache.addImportedModule(uncompiled_module) result.append(uncompiled_module) module_names.add(module_name) def _detectedShlibFile(filename, module_name): # That is not a shared library, but looks like one. if module_name == "__main__": return # Cyclic dependency from nuitka import ModuleRegistry if ModuleRegistry.hasRootModule(module_name): return source_ref = SourceCodeReferences.fromFilename(filename=filename) shlib_module = PythonShlibModule(module_name=module_name, source_ref=source_ref) ModuleRegistry.addRootModule(shlib_module) ImportCache.addImportedModule(shlib_module) module_names.add(module_name) def _detectImports(command, user_provided, technical): # This is pretty complicated stuff, with variants to deal with. # pylint: disable=too-many-branches,too-many-locals,too-many-statements # Print statements for stuff to show, the modules loaded. if python_version >= 0x300: command += """ print("\\n".join(sorted( "import %s # sourcefile %s" % (module.__name__, module.__file__) for module in sys.modules.values() if getattr(module, "__file__", None) not in (None, "" ))), file = sys.stderr)""" reduced_path = [ path_element for path_element in sys.path if not areSamePaths(path_element, ".") if not areSamePaths( path_element, os.path.dirname(sys.modules["__main__"].__file__) ) ] # Make sure the right import path (the one Nuitka binary is running with) # is used. command = ( "import sys; sys.path = %s; sys.real_prefix = sys.prefix;" % repr(reduced_path) ) + command import tempfile tmp_file, tmp_filename = tempfile.mkstemp() try: if python_version >= 0x300: command = command.encode("utf8") os.write(tmp_file, command) os.close(tmp_file) # TODO: Check exit code, should never fail. _stdout, stderr, exit_code = executeProcess( command=(sys.executable, "-s", "-S", "-v", tmp_filename), env=dict(os.environ, PYTHONIOENCODING="utf-8"), ) finally: os.unlink(tmp_filename) # Don't let errors here go unnoticed. if exit_code != 0: # An error by the user pressing CTRL-C should not lead to the below output. if b"KeyboardInterrupt" in stderr: general.sysexit("Pressed CTRL-C while detecting early imports.") general.warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): printError(line) general.sysexit("Error, please report the issue with above output.") result = [] detections = [] for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if python_version >= 0x300: module_name = module_name.decode("utf8") module_name = ModuleName(module_name) if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from ") :] if python_version >= 0x300: filename = filename.decode("utf8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue detections.append((module_name, 3, "precompiled", filename)) elif origin == b"from" and python_version < 0x300: filename = parts[1][len(b"from ") :] if python_version >= 0x300: # For consistency, and maybe later reuse filename = filename.decode("utf8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue if filename.endswith(".py"): detections.append((module_name, 2, "sourcefile", filename)) else: assert False elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile ") :] if python_version >= 0x300: filename = filename.decode("utf8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue if filename.endswith(".py"): detections.append((module_name, 2, "sourcefile", filename)) elif filename.endswith(".pyc"): detections.append((module_name, 3, "precompiled", filename)) elif not filename.endswith(""): # Python3 started lying in "__name__" for the "_decimal" # calls itself "decimal", which then is wrong and also # clashes with "decimal" proper if python_version >= 0x300: if module_name == "decimal": module_name = ModuleName("_decimal") detections.append((module_name, 2, "shlib", filename)) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from ") :] if python_version >= 0x300: filename = filename.decode("utf8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue detections.append((module_name, 1, "shlib", filename)) for module_name, _prio, kind, filename in sorted(detections): if kind == "precompiled": _detectedPrecompiledFile( filename=filename, module_name=module_name, result=result, user_provided=user_provided, technical=technical, ) elif kind == "sourcefile": _detectedSourceFile( filename=filename, module_name=module_name, result=result, user_provided=user_provided, technical=technical, ) elif kind == "shlib": _detectedShlibFile(filename=filename, module_name=module_name) else: assert False, kind return result # Some modules we want to exclude. _excluded_stdlib_modules = ["__main__.py", "__init__.py", "antigravity.py"] if os.name != "nt": # On posix systems, and posix Python veriants on Windows, this won't # work. _excluded_stdlib_modules.append("wintypes.py") _excluded_stdlib_modules.append("cp65001.py") def scanStandardLibraryPath(stdlib_dir): # There is a lot of filtering here, done in branches, so there # is many of # them, but that's acceptable, pylint: disable=too-many-branches,too-many-statements for root, dirs, filenames in os.walk(stdlib_dir): import_path = root[len(stdlib_dir) :].strip("/\\") import_path = import_path.replace("\\", ".").replace("/", ".") if import_path == "": if "site-packages" in dirs: dirs.remove("site-packages") if "dist-packages" in dirs: dirs.remove("dist-packages") if "test" in dirs: dirs.remove("test") if "idlelib" in dirs: dirs.remove("idlelib") if "turtledemo" in dirs: dirs.remove("turtledemo") if "ensurepip" in filenames: filenames.remove("ensurepip") if "ensurepip" in dirs: dirs.remove("ensurepip") # Ignore "lib-dynload" and "lib-tk" and alike. dirs[:] = [ dirname for dirname in dirs if not dirname.startswith("lib-") if dirname != "Tools" if not dirname.startswith("plat-") ] if import_path in ( "tkinter", "importlib", "ctypes", "unittest", "sqlite3", "distutils", "email", "bsddb", ): if "test" in dirs: dirs.remove("test") if import_path == "distutils.command": # Misbehaving and crashing while importing the world. if "bdist_conda.py" in filenames: filenames.remove("bdist_conda.py") if import_path in ("lib2to3", "json", "distutils"): if "tests" in dirs: dirs.remove("tests") if import_path == "asyncio": if "test_utils.py" in filenames: filenames.remove("test_utils.py") if python_version >= 0x340 and Utils.isWin32Windows(): if import_path == "multiprocessing": filenames.remove("popen_fork.py") filenames.remove("popen_forkserver.py") filenames.remove("popen_spawn_posix.py") if python_version >= 0x300 and Utils.isPosixWindows(): if import_path == "curses": filenames.remove("has_key.py") if Utils.isNetBSD(): if import_path == "xml.sax": filenames.remove("expatreader.py") for filename in filenames: if filename.endswith(".py") and filename not in _excluded_stdlib_modules: module_name = filename[:-3] if import_path == "": yield module_name else: yield import_path + "." + module_name if python_version >= 0x300: if "__pycache__" in dirs: dirs.remove("__pycache__") for dirname in dirs: if import_path == "": yield dirname else: yield import_path + "." + dirname def _detectEarlyImports(): encoding_names = [ m[1] for m in pkgutil.iter_modules(sys.modules["encodings"].__path__) ] if os.name != "nt": # On posix systems, and posix Python veriants on Windows, these won't # work and fail to import. for encoding_name in ("mbcs", "cp65001", "oem"): if encoding_name in encoding_names: encoding_names.remove(encoding_name) import_code = ";".join( "import encodings.%s" % encoding_name for encoding_name in sorted(encoding_names) ) import_code += ";import locale;" # For Python3 we patch inspect without knowing if it is used. if python_version >= 0x300: import_code += "import inspect;" result = _detectImports(command=import_code, user_provided=False, technical=True) if Options.shallFreezeAllStdlib(): stdlib_modules = set() # Scan the standard library paths (multiple in case of virtualenv. for stdlib_dir in getStandardLibraryPaths(): for module_name in scanStandardLibraryPath(stdlib_dir): stdlib_modules.add(module_name) # Put here ones that should be imported first. first_ones = ("Tkinter",) # We have to fight zombie modules in this, some things, e.g. Tkinter # on newer Python 2.7, comes back after failure without a second error # being raised, leading to other issues. So we fight it after each # module that was tried, and prevent re-try by adding a meta path # based loader that will never load it again, and remove it from the # "sys.modules" over and over, once it sneaks back. The root cause is # that extension modules sometimes only raise an error when first # imported, not the second time around. # Otherwise this just makes imports of everything so we can see where # it comes from and what it requires. import_code = """ imports = %r failed = set() class ImportBlocker(object): def find_module(self, fullname, path = None): if fullname in failed: return self return None def load_module(self, name): raise ImportError("%%s has failed before" %% name) sys.meta_path.insert(0, ImportBlocker()) for imp in imports: try: __import__(imp) except (ImportError, SyntaxError): failed.add(imp) except ValueError as e: if "cannot contain null bytes" in e.args[0]: failed.add(imp) else: sys.stderr.write("PROBLEM with '%%s'\\n" %% imp) raise except Exception: sys.stderr.write("PROBLEM with '%%s'\\n" %% imp) raise for fail in failed: if fail in sys.modules: del sys.modules[fail] """ % sorted( stdlib_modules, key=lambda name: (name not in first_ones, name) ) early_names = [module.getFullName() for module in result] result += [ module for module in _detectImports( command=import_code, user_provided=False, technical=False ) if module.getFullName() not in early_names ] return result def detectEarlyImports(): # Cyclic dependency from nuitka import ModuleRegistry early_modules = tuple(_detectEarlyImports()) for module in early_modules: ModuleRegistry.addUncompiledModule(module) return early_modules _detected_python_rpath = None ldd_result_cache = {} _linux_dll_ignore_list = ( # Do not include kernel / glibc specific libraries. This list has been # assembled by looking what are the most common .so files provided by # glibc packages from ArchLinux, Debian Stretch and CentOS. # # Online sources: # - https://centos.pkgs.org/7/puias-computational-x86_64/glibc-aarch64-linux-gnu-2.24-2.sdl7.2.noarch.rpm.html # - https://centos.pkgs.org/7/centos-x86_64/glibc-2.17-222.el7.x86_64.rpm.html # - https://archlinux.pkgs.org/rolling/archlinux-core-x86_64/glibc-2.28-5-x86_64.pkg.tar.xz.html # - https://packages.debian.org/stretch/amd64/libc6/filelist # # Note: This list may still be incomplete. Some additional libraries # might be provided by glibc - it may vary between the package versions # and between Linux distros. It might or might not be a problem in the # future, but it should be enough for now. "ld-linux-x86-64.so", "libc.so", "libpthread.so", "libm.so", "libdl.so", "libBrokenLocale.so", "libSegFault.so", "libanl.so", "libcidn.so", "libcrypt.so", "libmemusage.so", "libmvec.so", "libnsl.so", "libnss3.so", "libnssutils3.so", "libnss_compat.so", "libnss_db.so", "libnss_dns.so", "libnss_files.so", "libnss_hesiod.so", "libnss_nis.so", "libnss_nisplus.so", "libpcprofile.so", "libresolv.so", "librt.so", "libthread_db-1.0.so", "libthread_db.so", "libutil.so", # The C++ standard library can also be ABI specific, and can cause system # libraries like MESA to not load any drivers, so we exclude it too, and # it can be assumed to be installed everywhere anyway. "libstdc++.so", # The DRM layer should also be taken from the OS in question and won't # allow loading native drivers otherwise. "libdrm.so", ) def _getLdLibraryPath(package_name, python_rpath, original_dir): ld_library_path = OrderedSet() if python_rpath: ld_library_path.add(python_rpath) ld_library_path.update(getPackageSpecificDLLDirectories(package_name)) if original_dir is not None: ld_library_path.add(original_dir) return ld_library_path def _detectBinaryPathDLLsPosix(dll_filename, package_name, original_dir): # This is complex, as it also includes the caching mechanism # pylint: disable=too-many-branches if ldd_result_cache.get(dll_filename): return ldd_result_cache[dll_filename] # Ask "ldd" about the libraries being used by the created binary, these # are the ones that interest us. # This is the rpath of the Python binary, which will be effective when # loading the other DLLs too. This happens at least for Python installs # on Travis. pylint: disable=global-statement global _detected_python_rpath if _detected_python_rpath is None and not Utils.isPosixWindows(): _detected_python_rpath = getSharedLibraryRPATH(sys.executable) or False if _detected_python_rpath: _detected_python_rpath = _detected_python_rpath.replace( "$ORIGIN", os.path.dirname(sys.executable) ) # TODO: Actually would be better to pass it as env to the created process instead. with withEnvironmentPathAdded( "LD_LIBRARY_PATH", *_getLdLibraryPath( package_name=package_name, python_rpath=_detected_python_rpath, original_dir=original_dir, ) ): # TODO: Check exit code, should never fail. stdout, stderr, _exit_code = executeProcess(command=("ldd", dll_filename)) stderr = b"\n".join( line for line in stderr.splitlines() if not line.startswith( b"ldd: warning: you do not have execution permission for" ) ) inclusion_logger.debug("ldd output for %s is:\n%s" % (dll_filename, stdout)) if stderr: inclusion_logger.debug("ldd error for %s is:\n%s" % (dll_filename, stderr)) result = set() for line in stdout.split(b"\n"): if not line: continue if b"=>" not in line: continue part = line.split(b" => ", 2)[1] if b"(" in part: filename = part[: part.rfind(b"(") - 1] else: filename = part if not filename: continue if python_version >= 0x300: filename = filename.decode("utf8") # Sometimes might use stuff not found or supplied by ldd itself. if filename in ("not found", "ldd"): continue # Normalize, sometimes the DLLs produce "something/../", this has # been seen with Qt at least. filename = os.path.normpath(filename) # Do not include kernel DLLs on the ignore list. filename_base = os.path.basename(filename) if any( filename_base == entry or filename_base.startswith(entry + ".") for entry in _linux_dll_ignore_list ): continue result.add(filename) ldd_result_cache[dll_filename] = result sub_result = set(result) for sub_dll_filename in result: sub_result = sub_result.union( _detectBinaryPathDLLsPosix( dll_filename=sub_dll_filename, package_name=package_name, original_dir=original_dir, ) ) return sub_result def _detectBinaryPathDLLsMacOS( original_dir, binary_filename, package_name, keep_unresolved ): # TODO: Actually would be better to pass it as env to the created process instead. with withEnvironmentPathAdded( "DYLD_LIBRARY_PATH", *_getLdLibraryPath( package_name=package_name, python_rpath=None, original_dir=original_dir ) ): # TODO: Check exit code, should never fail. stdout, _stderr, _exit_code = executeProcess( command=("otool", "-L", binary_filename) ) system_paths = ( "/usr/lib/", "/System/Library/Frameworks/", "/System/Library/PrivateFrameworks/", ) result = OrderedSet() for line in stdout.split(b"\n")[1:]: if str is not bytes: line = line.decode("utf8") if not line: continue filename = line.split(" (", 1)[0].strip() for w in system_paths: if filename.startswith(w): break else: result.add(filename) resolved_result = _resolveBinaryPathDLLsMacOS( original_dir=original_dir, binary_filename=binary_filename, paths=result, keep_unresolved=keep_unresolved, ) return resolved_result def _resolveBinaryPathDLLsMacOS(original_dir, binary_filename, paths, keep_unresolved): if keep_unresolved: result = {} else: result = set() rpaths = _detectBinaryRPathsMacOS(original_dir, binary_filename) for path in paths: if path.startswith("@rpath/"): for rpath in rpaths: if os.path.isfile(os.path.join(rpath, path[7:])): resolved_path = os.path.join(rpath, path[7:]) break else: resolved_path = os.path.join(original_dir, path[7:]) elif path.startswith("@loader_path/"): resolved_path = os.path.join(original_dir, path[13:]) else: resolved_path = path if keep_unresolved: result.update({resolved_path: path}) else: result.add(resolved_path) return result def _detectBinaryRPathsMacOS(original_dir, binary_filename): # TODO: Check exit code, should never fail. stdout, _stderr, _exit_code = executeProcess( command=("otool", "-l", binary_filename) ) lines = stdout.split(b"\n") result = set() for i, line in enumerate(lines): if line.endswith(b"cmd LC_RPATH"): line = lines[i + 2] if str is not bytes: line = line.decode("utf8") line = line.split("path ", 1)[1] line = line.split(" (offset", 1)[0] if line.startswith("@loader_path"): line = os.path.join(original_dir, line[13:]) elif line.startswith("@executable_path"): continue result.add(line) return result def _getCacheFilename( dependency_tool, is_main_executable, source_dir, original_dir, binary_filename ): original_filename = os.path.join(original_dir, os.path.basename(binary_filename)) original_filename = os.path.normcase(original_filename) if is_main_executable: # Normalize main program name for caching as well, but need to use the # scons information to distinguish different compilers, so we use # different libs there. hashed_value = getFileContents(os.path.join(source_dir, "scons-report.txt")) else: hashed_value = original_filename # Have different values for different Python major versions. hashed_value += sys.version + sys.executable if str is not bytes: hashed_value = hashed_value.encode("utf8") cache_dir = os.path.join(getCacheDir(), "library_deps", dependency_tool) makePath(cache_dir) return os.path.join(cache_dir, hashlib.md5(hashed_value).hexdigest()) _scan_dir_cache = {} def getPackageSpecificDLLDirectories(package_name): scan_dirs = OrderedSet() if package_name is not None: package_dir = locateModule( module_name=package_name, parent_package=None, level=0 )[1] if os.path.isdir(package_dir): scan_dirs.add(package_dir) scan_dirs.update( getSubDirectories(package_dir, ignore_dirs=("__pycache__",)) ) scan_dirs.update(Plugins.getModuleSpecificDllPaths(package_name)) return scan_dirs def getScanDirectories(package_name, original_dir): # Many cases, pylint: disable=too-many-branches cache_key = package_name, original_dir if cache_key in _scan_dir_cache: return _scan_dir_cache[cache_key] scan_dirs = [sys.prefix] if package_name is not None: scan_dirs.extend(getPackageSpecificDLLDirectories(package_name)) if original_dir is not None: scan_dirs.append(original_dir) scan_dirs.extend(getSubDirectories(original_dir)) if ( Utils.isWin32Windows() and package_name is not None and package_name.isBelowNamespace("win32com") ): pywin32_dir = getPyWin32Dir() if pywin32_dir is not None: scan_dirs.append(pywin32_dir) for path_dir in os.environ["PATH"].split(";"): if not os.path.isdir(path_dir): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"])): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "System32")): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")): continue scan_dirs.append(path_dir) result = [] # Remove directories that hold no DLLs. for scan_dir in scan_dirs: sys.stdout.flush() # These are useless, but plenty. if os.path.basename(scan_dir) == "__pycache__": continue scan_dir = getDirectoryRealPath(scan_dir) # No DLLs, no use. if not any(entry[1].lower().endswith(".dll") for entry in listDir(scan_dir)): continue result.append(os.path.realpath(scan_dir)) _scan_dir_cache[cache_key] = result return result def detectBinaryPathDLLsWindowsDependencyWalker( is_main_executable, source_dir, original_dir, binary_filename, package_name, use_cache, update_cache, ): # This is the caching mechanism and plugin handling for DLL imports. if use_cache or update_cache: cache_filename = _getCacheFilename( dependency_tool="depends.exe", is_main_executable=is_main_executable, source_dir=source_dir, original_dir=original_dir, binary_filename=binary_filename, ) if use_cache: with withFileLock(): if not os.path.exists(cache_filename): use_cache = False if use_cache: result = OrderedSet() for line in getFileContentByLine(cache_filename): line = line.strip() result.add(line) return result if Options.isShowProgress(): general.info("Analysing dependencies of '%s'." % binary_filename) scan_dirs = getScanDirectories(package_name, original_dir) result = detectDLLsWithDependencyWalker(binary_filename, scan_dirs) if update_cache: putTextFileContents(filename=cache_filename, contents=result) return result def detectBinaryDLLs( is_main_executable, source_dir, original_filename, binary_filename, package_name, use_cache, update_cache, ): """Detect the DLLs used by a binary. Using "ldd" (Linux), "depends.exe" (Windows), or "otool" (macOS) the list of used DLLs is retrieved. """ if ( Utils.getOS() in ("Linux", "NetBSD", "FreeBSD", "OpenBSD") or Utils.isPosixWindows() ): return _detectBinaryPathDLLsPosix( dll_filename=original_filename, package_name=package_name, original_dir=os.path.dirname(original_filename), ) elif Utils.isWin32Windows(): with TimerReport( message="Running 'depends.exe' for %s took %%.2f seconds" % binary_filename, decider=Options.isShowProgress, ): return detectBinaryPathDLLsWindowsDependencyWalker( is_main_executable=is_main_executable, source_dir=source_dir, original_dir=os.path.dirname(original_filename), binary_filename=binary_filename, package_name=package_name, use_cache=use_cache, update_cache=update_cache, ) elif Utils.isMacOS(): return _detectBinaryPathDLLsMacOS( original_dir=os.path.dirname(original_filename), binary_filename=original_filename, package_name=package_name, keep_unresolved=False, ) else: # Support your platform above. assert False, Utils.getOS() _unfound_dlls = set() def detectUsedDLLs(source_dir, standalone_entry_points, use_cache, update_cache): def addDLLInfo(count, source_dir, original_filename, binary_filename, package_name): used_dlls = detectBinaryDLLs( is_main_executable=count == 0, source_dir=source_dir, original_filename=original_filename, binary_filename=binary_filename, package_name=package_name, use_cache=use_cache, update_cache=update_cache, ) # Allow plugins to prevent inclusion, this may discard things from used_dlls. Plugins.removeDllDependencies( dll_filename=binary_filename, dll_filenames=used_dlls ) for dll_filename in sorted(tuple(used_dlls)): if not os.path.isfile(dll_filename): if _unfound_dlls: general.warning( "Dependency '%s' could not be found, you might need to copy it manually." % dll_filename ) _unfound_dlls.add(dll_filename) used_dlls.remove(dll_filename) return binary_filename, used_dlls result = OrderedDict() with ThreadPoolExecutor(max_workers=Utils.getCoreCount() * 3) as worker_pool: workers = [] for count, standalone_entry_point in enumerate(standalone_entry_points): workers.append( worker_pool.submit( addDLLInfo, count, source_dir, standalone_entry_point.source_path, standalone_entry_point.dest_path, standalone_entry_point.package_name, ) ) for binary_filename, used_dlls in waitWorkers(workers): for dll_filename in used_dlls: # We want these to be absolute paths. Solve that in the parts # where detectBinaryDLLs is platform specific. assert os.path.isabs(dll_filename), dll_filename if dll_filename not in result: result[dll_filename] = [] result[dll_filename].append(binary_filename) return result def fixupBinaryDLLPathsMacOS(binary_filename, dll_map, original_location): """For macOS, the binary needs to be told to use relative DLL paths""" # There may be nothing to do, in case there are no DLLs. if not dll_map: return rpath_map = _detectBinaryPathDLLsMacOS( original_dir=os.path.dirname(original_location), binary_filename=original_location, package_name=None, keep_unresolved=True, ) for i, o in enumerate(dll_map): dll_map[i] = (rpath_map.get(o[0], o[0]), o[1]) callInstallNameTool( filename=binary_filename, mapping=( (original_path, "@executable_path/" + dist_path) for (original_path, dist_path) in dll_map ), rpath=None, ) # These DLLs are run time DLLs from Microsoft, and packages will depend on different # ones, but it will be OK to use the latest one. ms_runtime_dlls = ( "msvcp140_1.dll", "msvcp140.dll", "vcruntime140_1.dll", "concrt140.dll", ) def copyUsedDLLs(source_dir, dist_dir, standalone_entry_points): # This is terribly complex, because we check the list of used DLLs # trying to avoid duplicates, and detecting errors with them not # being binary identical, so we can report them. And then of course # we also need to handle OS specifics. # pylint: disable=too-many-branches,too-many-locals,too-many-statements used_dlls = detectUsedDLLs( source_dir=source_dir, standalone_entry_points=standalone_entry_points, use_cache=not Options.shallNotUseDependsExeCachedResults() and not Options.getWindowsDependencyTool() == "depends.exe", update_cache=not Options.shallNotStoreDependsExeCachedResults() and not Options.getWindowsDependencyTool() == "depends.exe", ) removed_dlls = set() warned_about = set() # Fist make checks and remove some. for dll_filename1, sources1 in tuple(iterItems(used_dlls)): if dll_filename1 in removed_dlls: continue for dll_filename2, sources2 in tuple(iterItems(used_dlls)): if dll_filename1 == dll_filename2: continue if dll_filename2 in removed_dlls: continue # Colliding basenames are an issue to us. if os.path.basename(dll_filename1) != os.path.basename(dll_filename2): continue # May already have been removed earlier if dll_filename1 not in used_dlls: continue if dll_filename2 not in used_dlls: continue dll_name = os.path.basename(dll_filename1) if Options.isShowInclusion(): inclusion_logger.info( """Colliding DLL names for %s, checking identity of \ '%s' <-> '%s'.""" % (dll_name, dll_filename1, dll_filename2) ) # Check that if a DLL has the same name, if it's identical, then it's easy. if haveSameFileContents(dll_filename1, dll_filename2): del used_dlls[dll_filename2] removed_dlls.add(dll_filename2) continue # For Win32 we can check out file versions. if Utils.isWin32Windows(): dll_version1 = getWindowsDLLVersion(dll_filename1) dll_version2 = getWindowsDLLVersion(dll_filename2) if dll_version2 < dll_version1: del used_dlls[dll_filename2] removed_dlls.add(dll_filename2) solved = True elif dll_version1 < dll_version2: del used_dlls[dll_filename1] removed_dlls.add(dll_filename1) solved = True else: solved = False if solved: if dll_name not in warned_about and dll_name not in ms_runtime_dlls: warned_about.add(dll_name) inclusion_logger.warning( "Conflicting DLLs for '%s' in your installation, newest file version used, hoping for the best." % dll_name ) continue # So we have conflicting DLLs, in which case we do report the fact. inclusion_logger.warning( """\ Ignoring non-identical DLLs for '%s'. %s used by: %s different from %s used by %s""" % ( dll_name, dll_filename1, "\n ".join(sources1), dll_filename2, "\n ".join(sources2), ) ) del used_dlls[dll_filename2] removed_dlls.add(dll_filename2) dll_map = [] for dll_filename, sources in iterItems(used_dlls): dll_name = os.path.basename(dll_filename) target_path = os.path.join(dist_dir, dll_name) # Sometimes DLL dependencies were copied there already. if not os.path.exists(target_path): shutil.copyfile(dll_filename, target_path) dll_map.append((dll_filename, dll_name)) if Options.isShowInclusion(): inclusion_logger.info( "Included used shared library '%s' (used by %s)." % (dll_filename, ", ".join(sources)) ) if Utils.isMacOS(): # For macOS, the binary and the DLLs needs to be changed to reflect # the relative DLL location in the ".dist" folder. for standalone_entry_point in standalone_entry_points: fixupBinaryDLLPathsMacOS( binary_filename=standalone_entry_point.dest_path, dll_map=dll_map, original_location=standalone_entry_point.source_path, ) for original_path, dll_filename in dll_map: fixupBinaryDLLPathsMacOS( binary_filename=os.path.join(dist_dir, dll_filename), dll_map=dll_map, original_location=original_path, ) # Remove code signature from CPython installed library candidate = os.path.join( dist_dir, "Python", ) if os.path.exists(candidate): removeMacOSCodeSignature(candidate) # Remove or update rpath settings. if Utils.getOS() in ("Linux", "Darwin"): # For Linux, the "rpath" of libraries may be an issue and must be # removed. if Utils.isMacOS(): start = 0 else: start = 1 for standalone_entry_point in standalone_entry_points[start:]: count = relpath( path=standalone_entry_point.dest_path, start=dist_dir ).count(os.path.sep) rpath = os.path.join("$ORIGIN", *([".."] * count)) setSharedLibraryRPATH(standalone_entry_point.dest_path, rpath) for _original_path, dll_filename in dll_map: setSharedLibraryRPATH(os.path.join(dist_dir, dll_filename), "$ORIGIN") if Utils.isWin32Windows(): if python_version < 0x300: # For Win32, we might have to remove SXS paths for standalone_entry_point in standalone_entry_points[1:]: removeSxsFromDLL(standalone_entry_point.dest_path) for _original_path, dll_filename in dll_map: removeSxsFromDLL(os.path.join(dist_dir, dll_filename)) def _handleDataFile(dist_dir, tracer, included_datafile): """Handle a data file.""" if not isinstance(included_datafile, (IncludedDataFile, IncludedDataDirectory)): tracer.sysexit("Error, cannot only include 'IncludedData*' objects in plugins.") if included_datafile.kind == "empty_dirs": tracer.info( "Included empty directories '%s' due to %s." % ( ",".join(included_datafile.dest_path), included_datafile.reason, ) ) for sub_dir in included_datafile.dest_path: created_dir = os.path.join(dist_dir, sub_dir) makePath(created_dir) putTextFileContents( filename=os.path.join(created_dir, ".keep_dir.txt"), contents="" ) elif included_datafile.kind == "data_file": dest_path = os.path.join(dist_dir, included_datafile.dest_path) tracer.info( "Included data file '%s' due to %s." % ( included_datafile.dest_path, included_datafile.reason, ) ) makePath(os.path.dirname(dest_path)) copyFileWithPermissions( source_path=included_datafile.source_path, dest_path=dest_path ) elif included_datafile.kind == "data_dir": dest_path = os.path.join(dist_dir, included_datafile.dest_path) makePath(os.path.dirname(dest_path)) copied = [] for filename in getFileList( included_datafile.source_path, ignore_dirs=included_datafile.ignore_dirs, ignore_filenames=included_datafile.ignore_filenames, ignore_suffixes=included_datafile.ignore_suffixes, only_suffixes=included_datafile.only_suffixes, normalize=included_datafile.normalize, ): filename_relative = os.path.relpath(filename, included_datafile.source_path) filename_dest = os.path.join(dest_path, filename_relative) makePath(os.path.dirname(filename_dest)) copyFileWithPermissions(source_path=filename, dest_path=filename_dest) copied.append(filename_relative) tracer.info( "Included data dir %r with %d files due to: %s." % ( included_datafile.dest_path, len(copied), included_datafile.reason, ) ) elif included_datafile.kind == "data_blob": dest_path = os.path.join(dist_dir, included_datafile.dest_path) makePath(os.path.dirname(dest_path)) putTextFileContents(filename=dest_path, contents=included_datafile.data) tracer.info( "Included data file '%s' due to %s." % ( included_datafile.dest_path, included_datafile.reason, ) ) else: assert False, included_datafile def copyDataFiles(dist_dir): """Copy the data files needed for standalone distribution. Args: dist_dir: The distribution folder under creation Notes: This is for data files only, not DLLs or even extension modules, those must be registered as entry points, and would not go through necessary handling if provided like this. """ # Many details to deal with, pylint: disable=too-many-branches,too-many-locals for pattern, src, dest, arg in Options.getShallIncludeDataFiles(): filenames = resolveShellPatternToFilenames(pattern) if not filenames: inclusion_logger.warning( "No matching data file to be included for '%s'." % pattern ) for filename in filenames: file_reason = "specified data file '%s' on command line" % arg if src is None: rel_path = dest if rel_path.endswith(("/", os.path.sep)): rel_path = os.path.join(rel_path, os.path.basename(filename)) else: rel_path = os.path.join(dest, relpath(filename, src)) _handleDataFile( dist_dir, inclusion_logger, makeIncludedDataFile(filename, rel_path, file_reason), ) for src, dest in Options.getShallIncludeDataDirs(): filenames = getFileList(src) if not filenames: inclusion_logger.warning("No files in directory '%s.'" % src) for filename in filenames: relative_filename = relpath(filename, src) file_reason = "specified data dir %r on command line" % src rel_path = os.path.join(dest, relative_filename) _handleDataFile( dist_dir, inclusion_logger, makeIncludedDataFile(filename, rel_path, file_reason), ) # Cyclic dependency from nuitka import ModuleRegistry for module in ModuleRegistry.getDoneModules(): for plugin, included_datafile in Plugins.considerDataFiles(module): _handleDataFile( dist_dir=dist_dir, tracer=plugin, included_datafile=included_datafile ) for module in ModuleRegistry.getDoneModules(): if module.isCompiledPythonPackage() or module.isUncompiledPythonPackage(): package_name = module.getFullName() match, reason = package_name.matchesToShellPatterns( patterns=Options.getShallIncludePackageData() ) if match: package_directory = module.getCompileTimeDirectory() pkg_filenames = getFileList( package_directory, ignore_dirs=("__pycache__",), ignore_suffixes=(".py", ".pyw", ".pyc", ".pyo", ".dll") + getSharedLibrarySuffixes(), ) if pkg_filenames: file_reason = "package '%s' %s" % (package_name, reason) for pkg_filename in pkg_filenames: rel_path = os.path.join( package_name.asPath(), os.path.relpath(pkg_filename, package_directory), ) _handleDataFile( dist_dir, inclusion_logger, makeIncludedDataFile(pkg_filename, rel_path, file_reason), ) Nuitka-0.6.19.1/nuitka/freezer/IncludedDataFiles.py0000600000372100037210000000567114166627112027113 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Included data files for standalone mode. This keeps track of data files for standalone mode. Do not should them for DLLs or extension modules, these need to be seen by Nuitka as entry points for dependency analysis. """ import collections import os from nuitka.utils.FileOperations import isRelativePath IncludedDataFile = collections.namedtuple( "IncludedDataFile", ("kind", "source_path", "dest_path", "reason", "data") ) def makeIncludedEmptyDirectories(source_path, dest_paths, reason): for dest_path in dest_paths: assert not os.path.isabs(dest_path) # Require that to not be empty. assert dest_paths return IncludedDataFile( kind="empty_dirs", source_path=source_path, dest_path=dest_paths, data=None, reason=reason, ) def makeIncludedDataFile(source_path, dest_path, reason): assert isRelativePath(dest_path), dest_path return IncludedDataFile( kind="data_file", source_path=source_path, dest_path=dest_path, data=None, reason=reason, ) IncludedDataDirectory = collections.namedtuple( "IncludedDataDirectory", ( "kind", "source_path", "dest_path", "reason", "ignore_dirs", "ignore_filenames", "ignore_suffixes", "only_suffixes", "normalize", ), ) def makeIncludedDataDirectory( source_path, dest_path, reason, ignore_dirs=(), ignore_filenames=(), ignore_suffixes=(), only_suffixes=(), normalize=True, ): assert isRelativePath(dest_path), dest_path return IncludedDataDirectory( kind="data_dir", source_path=source_path, dest_path=dest_path, ignore_dirs=ignore_dirs, ignore_filenames=ignore_filenames, ignore_suffixes=ignore_suffixes, only_suffixes=only_suffixes, normalize=normalize, reason=reason, ) def makeIncludedGeneratedDataFile(data, dest_path, reason): assert isRelativePath(dest_path), dest_path return IncludedDataFile( kind="data_blob", source_path=None, dest_path=dest_path, reason=reason, data=data, ) Nuitka-0.6.19.1/nuitka/freezer/DependsExe.py0000600000372100037210000001361214166627112025625 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Interface to depends.exe on Windows. We use depends.exe to investigate needed DLLs of Python DLLs. """ import os from nuitka.containers.oset import OrderedSet from nuitka.Options import assumeYesForDownloads from nuitka.Tracing import inclusion_logger from nuitka.utils.Download import getCachedDownload from nuitka.utils.Execution import executeProcess from nuitka.utils.FileOperations import ( deleteFile, getExternalUsePath, getFileContentByLine, putTextFileContents, withFileLock, ) from nuitka.utils.Utils import getArchitecture def getDependsExePath(): """Return the path of depends.exe (for Windows). Will prompt the user to download if not already cached in AppData directory for Nuitka. """ if getArchitecture() == "x86": depends_url = "https://dependencywalker.com/depends22_x86.zip" else: depends_url = "https://dependencywalker.com/depends22_x64.zip" return getCachedDownload( url=depends_url, is_arch_specific=getArchitecture(), binary="depends.exe", flatten=True, specifity="", # Note: If there ever was an update, put version here. message="""\ Nuitka will make use of Dependency Walker (https://dependencywalker.com) tool to analyze the dependencies of Python extension modules.""", reject="Nuitka does not work in --standalone or --onefile on Windows without.", assume_yes_for_downloads=assumeYesForDownloads(), ) def _parseDependsExeOutput2(lines): result = OrderedSet() inside = False first = False for line in lines: if "| Module Dependency Tree |" in line: inside = True first = True continue if not inside: continue if "| Module List |" in line: break if "]" not in line: continue dll_filename = line[line.find("]") + 2 :].rstrip() dll_filename = os.path.normcase(dll_filename) # Skip DLLs that failed to load, apparently not needed anyway. if "E" in line[: line.find("]")]: continue # Skip missing DLLs, apparently not needed anyway. if "?" in line[: line.find("]")]: # One exception are PythonXY.DLL if dll_filename.startswith("python") and dll_filename.endswith(".dll"): dll_filename = os.path.join( os.environ["SYSTEMROOT"], "SysWOW64" if getArchitecture() == "x86_64" else "System32", dll_filename, ) dll_filename = os.path.normcase(dll_filename) else: continue dll_filename = os.path.abspath(dll_filename) dll_name = os.path.basename(dll_filename) # Ignore this runtime DLL of Python2, will be coming via manifest. if dll_name in ("msvcr90.dll",): continue # The executable itself is of course exempted. We cannot check its path # because depends.exe mistreats unicode paths. if first: first = False continue assert os.path.isfile(dll_filename), (dll_filename, line) result.add(os.path.normcase(os.path.abspath(dll_filename))) return result def parseDependsExeOutput(filename): return _parseDependsExeOutput2(getFileContentByLine(filename, encoding="latin1")) def detectDLLsWithDependencyWalker(binary_filename, scan_dirs): dwp_filename = binary_filename + ".dwp" output_filename = binary_filename + ".depends" # User query should only happen once if at all. with withFileLock( "Finding out dependency walker path and creating DWP file for %s" % binary_filename ): depends_exe = getDependsExePath() # Note: Do this under lock to avoid forked processes to hold # a copy of the file handle on Windows. putTextFileContents( dwp_filename, contents="""\ %(scan_dirs)s SxS """ % { "scan_dirs": "\n".join( "UserDir %s" % getExternalUsePath(dirname) for dirname in scan_dirs ) }, ) # Starting the process while locked, so file handles are not duplicated. # TODO: At least exit code should be checked, output goes to a filename, # but errors might be interesting potentially. _stdout, _stderr, _exit_code = executeProcess( command=( depends_exe, "-c", "-ot%s" % output_filename, "-d:%s" % dwp_filename, "-f1", "-pa1", "-ps1", binary_filename, ), external_cwd=True, ) if not os.path.exists(output_filename): inclusion_logger.sysexit( "Error, depends.exe failed to produce expected output." ) # Opening the result under lock, so it is not getting locked by new processes. # Note: Do this under lock to avoid forked processes to hold # a copy of the file handle on Windows. result = parseDependsExeOutput(output_filename) deleteFile(output_filename, must_exist=True) deleteFile(dwp_filename, must_exist=True) return result Nuitka-0.6.19.1/nuitka/freezer/Onefile.py0000600000372100037210000003547614166627112025176 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Pack distribution folders into a single file. """ import os import shutil import struct import subprocess import sys from contextlib import contextmanager from nuitka import Options, OutputDirectories from nuitka.build import SconsInterface from nuitka.Options import assumeYesForDownloads, getIconPaths from nuitka.OutputDirectories import getResultBasepath, getResultFullpath from nuitka.plugins.Plugins import Plugins from nuitka.PostProcessing import ( executePostProcessingResources, version_resources, ) from nuitka.Progress import ( closeProgressBar, reportProgressBar, setupProgressBar, ) from nuitka.PythonVersions import python_version from nuitka.Tracing import onefile_logger, postprocessing_logger from nuitka.utils.Download import getCachedDownload from nuitka.utils.Execution import getNullInput, withEnvironmentVarsOverriden from nuitka.utils.FileOperations import ( addFileExecutablePermission, deleteFile, getFileContents, getFileList, openTextFile, putTextFileContents, removeDirectory, ) from nuitka.utils.SharedLibraries import locateDLL from nuitka.utils.Utils import ( getArchitecture, getOS, hasOnefileSupportedOS, isLinux, isWin32Windows, ) def packDistFolderToOnefile(dist_dir, binary_filename): """Pack distribution to onefile, i.e. a single file that is directly executable.""" onefile_output_filename = getResultFullpath(onefile=True) if getOS() == "Windows" or Options.isOnefileTempDirMode(): packDistFolderToOnefileBootstrap(onefile_output_filename, dist_dir) elif isLinux(): packDistFolderToOnefileLinux(onefile_output_filename, dist_dir, binary_filename) else: postprocessing_logger.sysexit( "Onefile mode is not yet available on %r." % getOS() ) Plugins.onOnefileFinished(onefile_output_filename) def _getAppImageToolPath(for_operation, assume_yes_for_downloads): """Return the path of appimagetool (for Linux). Will prompt the user to download if not already cached in AppData directory for Nuitka. """ arch_name = getArchitecture() # Mismatch between Debian arch name and appimage arch naming. if arch_name == "armv7l": arch_name = "armhf" appimagetool_url = ( "https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-%s.AppImage" % arch_name ) return getCachedDownload( url=appimagetool_url, is_arch_specific=getArchitecture(), binary=appimagetool_url.rsplit("/", 1)[1], flatten=True, specifity=appimagetool_url.rsplit("/", 2)[1], message="""\ Nuitka will make use of AppImage (https://appimage.org/) tool to combine Nuitka dist folder to onefile binary.""", reject="Nuitka does not work in --onefile on Linux without." if for_operation else None, assume_yes_for_downloads=assume_yes_for_downloads, ) def packDistFolderToOnefileLinux(onefile_output_filename, dist_dir, binary_filename): """Pack to onefile binary on Linux. Notes: This is mostly a wrapper around AppImage, which does all the heavy lifting. """ if not locateDLL("fuse"): postprocessing_logger.sysexit( """\ Error, the fuse library (libfuse.so.x from fuse2, *not* fuse3) must be installed for onefile creation to work on Linux.""" ) # This might be possible to avoid being done with --runtime-file. apprun_filename = os.path.join(dist_dir, "AppRun") putTextFileContents( apprun_filename, contents="""\ #!/bin/bash exec -a $ARGV0 $APPDIR/%s \"$@\"""" % os.path.basename(binary_filename), ) addFileExecutablePermission(apprun_filename) binary_basename = os.path.basename(getResultBasepath()) icon_paths = getIconPaths() assert icon_paths extension = os.path.splitext(icon_paths[0])[1].lower() shutil.copyfile(icon_paths[0], getResultBasepath() + extension) putTextFileContents( getResultBasepath() + ".desktop", contents="""\ [Desktop Entry] Name=%(binary_basename)s Exec=%(binary_filename)s Icon=%(binary_basename)s Type=Application Categories=Utility;""" % { "binary_basename": binary_basename, "binary_filename": os.path.basename(binary_filename), }, ) postprocessing_logger.info( "Creating single file from dist folder, this may take a while." ) stdout_filename = binary_filename + ".appimage.stdout.txt" stderr_filename = binary_filename + ".appimage.stderr.txt" stdout_file = openTextFile(stdout_filename, "wb") stderr_file = openTextFile(stderr_filename, "wb") # Starting the process while locked, so file handles are not duplicated, we # need fine grained control over process here, therefore we cannot use the # Execution.executeProcess() function without making it too complex and not # all Python versions allow using with, pylint: disable=consider-using-with # pylint: disable appimagetool_process = subprocess.Popen( ( _getAppImageToolPath( for_operation=True, assume_yes_for_downloads=assumeYesForDownloads() ), dist_dir, "--comp", "xz", "-n", onefile_output_filename, ), shell=False, stdin=getNullInput(), stdout=stdout_file, stderr=stderr_file, ) result = appimagetool_process.wait() stdout_file.close() stderr_file.close() if result != 0: # Useless result if there were errors, so now remove it. deleteFile(onefile_output_filename, must_exist=False) stderr = getFileContents(stderr_filename, mode="rb") if b"Text file busy" in stderr: postprocessing_logger.sysexit( "Error, error exit from AppImage because target file is locked." ) if b"modprobe fuse" in stderr: postprocessing_logger.sysexit( "Error, error exit from AppImage because fuse kernel module was not loaded." ) postprocessing_logger.sysexit( "Error, error exit from AppImage, check its outputs '%s' and '%s'." % (stdout_filename, stderr_filename) ) if not os.path.exists(onefile_output_filename): postprocessing_logger.sysexit( "Error, expected output file %r not created by AppImage, check its outputs '%s' and '%s'." % (onefile_output_filename, stdout_filename, stderr_filename) ) deleteFile(stdout_filename, must_exist=True) deleteFile(stderr_filename, must_exist=True) postprocessing_logger.info("Completed onefile creation.") def _runOnefileScons(quiet, onefile_compression): source_dir = OutputDirectories.getSourceDirectoryPath(onefile=True) SconsInterface.cleanSconsDirectory(source_dir) asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=True), "result_exe": OutputDirectories.getResultFullpath(onefile=True), "source_dir": source_dir, "debug_mode": asBoolStr(Options.is_debug), "unstripped_mode": asBoolStr(Options.isUnstripped()), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "target_arch": getArchitecture(), "python_prefix": sys.prefix, "nuitka_src": SconsInterface.getSconsDataPath(), "compiled_exe": OutputDirectories.getResultFullpath(onefile=False), "onefile_compression": asBoolStr(onefile_compression), "onefile_splash_screen": asBoolStr( Options.getWindowsSplashScreen() is not None ), } if Options.isClang(): options["clang_mode"] = "true" SconsInterface.setCommonOptions(options) onefile_env_values = {} if Options.isOnefileTempDirMode(): onefile_env_values["ONEFILE_TEMP_SPEC"] = Options.getOnefileTempDirSpec( use_default=True ) else: # Merge version information if possible, to avoid collisions, or deep nesting # in file system. product_version = version_resources["ProductVersion"] file_version = version_resources["FileVersion"] if product_version != file_version: effective_version = "%s-%s" % (product_version, file_version) else: effective_version = file_version onefile_env_values["ONEFILE_COMPANY"] = version_resources["CompanyName"] onefile_env_values["ONEFILE_PRODUCT"] = version_resources["ProductName"] onefile_env_values["ONEFILE_VERSION"] = effective_version with withEnvironmentVarsOverriden(onefile_env_values): result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Onefile.scons" ) # Exit if compilation failed. if not result: onefile_logger.sysexit("Error, onefile bootstrap binary build failed.") if Options.isRemoveBuildDir(): onefile_logger.info("Removing onefile build directory %r." % source_dir) removeDirectory(path=source_dir, ignore_errors=False) assert not os.path.exists(source_dir) else: onefile_logger.info("Keeping onefile build directory %r." % source_dir) def _pickCompressor(): try: from zstandard import ZstdCompressor # pylint: disable=I0021,import-error except ImportError: if python_version < 0x350: onefile_logger.info( "Onefile compression is not supported before Python 3.5 at this time." ) else: onefile_logger.warning( "Onefile mode cannot compress without 'zstandard' module installed." ) else: cctx = ZstdCompressor(level=22) @contextmanager def useCompressedFile(output_file): with cctx.stream_writer(output_file, closefd=False) as compressed_file: yield compressed_file onefile_logger.info("Using compression for onefile payload.") return b"Y", useCompressedFile # By default use the same file handle that does not compress. @contextmanager def useSameFile(output_file): yield output_file return b"X", useSameFile def packDistFolderToOnefileBootstrap(onefile_output_filename, dist_dir): # Dealing with details, pylint: disable=too-many-locals postprocessing_logger.info( "Creating single file from dist folder, this may take a while." ) onefile_logger.info("Running bootstrap binary compilation via Scons.") # Now need to append to payload it, potentially compressing it. compression_indicator, compressor = _pickCompressor() # First need to create the bootstrap binary for unpacking. _runOnefileScons( quiet=not Options.isShowScons(), onefile_compression=compression_indicator == b"Y", ) if isWin32Windows(): executePostProcessingResources(manifest=None, onefile=True) with open(onefile_output_filename, "ab") as output_file: # Seeking to end of file seems necessary on Python2 at least, maybe it's # just that tell reports wrong value initially. output_file.seek(0, 2) start_pos = output_file.tell() output_file.write(b"KA" + compression_indicator) # Move the binary to start immediately to the start position start_binary = getResultFullpath(onefile=False) file_list = getFileList(dist_dir, normalize=False) file_list.remove(start_binary) file_list.insert(0, start_binary) if isWin32Windows(): filename_encoding = "utf-16le" else: filename_encoding = "utf8" payload_size = 0 setupProgressBar( stage="Onefile Payload", unit="module", total=len(file_list), ) with compressor(output_file) as compressed_file: # TODO: Use progress bar here. for filename_full in file_list: filename_relative = os.path.relpath(filename_full, dist_dir) reportProgressBar( item=filename_relative, update=False, ) filename_encoded = (filename_relative + "\0").encode(filename_encoding) compressed_file.write(filename_encoded) payload_size += len(filename_encoded) with open(filename_full, "rb") as input_file: input_file.seek(0, 2) input_size = input_file.tell() input_file.seek(0, 0) compressed_file.write(struct.pack("Q", input_size)) shutil.copyfileobj(input_file, compressed_file) payload_size += input_size + 8 reportProgressBar( item=filename_relative, update=True, ) # Using empty filename as a terminator. filename_encoded = "\0".encode(filename_encoding) compressed_file.write(filename_encoded) payload_size += len(filename_encoded) compressed_size = compressed_file.tell() if compression_indicator == b"Y": onefile_logger.info( "Onefile payload compression ratio (%.2f%%) size %d to %d." % ( (float(compressed_size) / payload_size) * 100, payload_size, compressed_size, ) ) # add padding to have the start position at a double world boundary # this is needed on windows so that a possible certificate immediately # follows the start position pad = output_file.tell() % 8 if pad != 0: output_file.write(bytes(8 - pad)) output_file.write(struct.pack("Q", start_pos)) closeProgressBar() def checkOnefileReadiness(assume_yes_for_downloads): if isLinux(): app_image_path = _getAppImageToolPath( for_operation=False, assume_yes_for_downloads=assume_yes_for_downloads ) return app_image_path is not None else: return hasOnefileSupportedOS() Nuitka-0.6.19.1/nuitka/freezer/__init__.py0000600000372100037210000000150114166627112025332 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/freezer/IncludedEntryPoints.py0000600000372100037210000001071214166627112027545 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Included entry points for standalone mode. This keeps track of entry points for standalone. These should be extension modules, added by core code, the main binary, added by core code, and from plugins in their getExtraDlls implementation, where they provide DLLs to be added, and whose dependencies will also be included. """ import collections import os import shutil from nuitka.OutputDirectories import getStandaloneDirectoryPath from nuitka.utils.FileOperations import isRelativePath, makePath from nuitka.utils.Importing import getSharedLibrarySuffix from nuitka.utils.ModuleNames import ModuleName IncludedEntryPoint = collections.namedtuple( "IncludedEntryPoint", ("kind", "source_path", "dest_path", "package_name", "executable"), ) # Since inheritance is not a thing with namedtuple, have factory functions def makeIncludedEntryPoint(kind, source_path, dest_path, package_name, executable): if package_name is not None: package_name = ModuleName(package_name) assert type(executable) is bool return IncludedEntryPoint(kind, source_path, dest_path, package_name, executable) def makeMainExecutableEntryPoint(dest_path): return makeIncludedEntryPoint( "executable", source_path=dest_path, dest_path=dest_path, package_name=None, executable=True, ) def makeDllEntryPoint(source_path, dest_path, package_name): assert type(dest_path) not in (tuple, list) assert type(source_path) not in (tuple, list) assert isRelativePath(dest_path), dest_path dest_path = os.path.join(getStandaloneDirectoryPath(), dest_path) return makeIncludedEntryPoint( "dll", source_path, dest_path, package_name, executable=False ) def makeExeEntryPoint(source_path, dest_path, package_name): assert type(dest_path) not in (tuple, list) assert type(source_path) not in (tuple, list) assert isRelativePath(dest_path), dest_path dest_path = os.path.join(getStandaloneDirectoryPath(), dest_path) return makeIncludedEntryPoint( "dll", source_path=source_path, dest_path=dest_path, package_name=package_name, executable=True, ) def makeDllEntryPointOld(source_path, dest_path, package_name): return makeIncludedEntryPoint( "dll", source_path=source_path, dest_path=dest_path, package_name=package_name, executable=False, ) def makeExtensionModuleEntryPoint(source_path, dest_path, package_name): return makeIncludedEntryPoint( "shlib", source_path=source_path, dest_path=dest_path, package_name=package_name, executable=False, ) standalone_entry_points = [] def addIncludedEntryPoints(entry_points): for entry_point in entry_points: if entry_point not in standalone_entry_points: standalone_entry_points.append(entry_point) def setMainEntryPoint(binary_filename): entry_point = makeMainExecutableEntryPoint(binary_filename) standalone_entry_points.insert(0, entry_point) def addShlibEntryPoint(module): target_filename = os.path.join( getStandaloneDirectoryPath(), module.getFullName().asPath() ) target_filename += getSharedLibrarySuffix(preferred=False) target_dir = os.path.dirname(target_filename) if not os.path.isdir(target_dir): makePath(target_dir) shutil.copyfile(module.getFilename(), target_filename) standalone_entry_points.append( makeExtensionModuleEntryPoint( source_path=module.getFilename(), dest_path=target_filename, package_name=module.getFullName().getPackageName(), ) ) def getStandaloneEntryPoints(): return standalone_entry_points Nuitka-0.6.19.1/nuitka/MainControl.py0000600000372100037210000010421114166627112024360 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This is the main actions of Nuitka. This can do all the steps to translate one module to a target language using the Python C/API, to compile it to either an executable or an extension module, potentially with bytecode included and used library copied into a distribution folder. """ import os import sys from nuitka.build.DataComposerInterface import runDataComposer from nuitka.build.SconsUtils import getSconsReportValue from nuitka.constants.Serialization import ConstantAccessor from nuitka.freezer.IncludedEntryPoints import ( addIncludedEntryPoints, addShlibEntryPoint, getStandaloneEntryPoints, setMainEntryPoint, ) from nuitka.freezer.Standalone import copyDataFiles from nuitka.importing import Importing, Recursion from nuitka.Options import ( getPythonPgoInput, hasPythonFlagNoAsserts, hasPythonFlagNoWarnings, ) from nuitka.plugins.Plugins import Plugins from nuitka.PostProcessing import executePostProcessing from nuitka.Progress import ( closeProgressBar, reportProgressBar, setupProgressBar, ) from nuitka.PythonFlavors import ( isAnacondaPython, isApplePython, isDebianPackagePython, isMSYS2MingwPython, isNuitkaPython, isPyenvPython, ) from nuitka.PythonVersions import ( getPythonABI, getSupportedPythonVersions, getSystemPrefixPath, python_version, python_version_str, ) from nuitka.Tracing import general, inclusion_logger from nuitka.tree import SyntaxErrors from nuitka.utils import InstanceCounters, MemoryUsage from nuitka.utils.Execution import ( callProcess, withEnvironmentVarOverriden, wrapCommandForDebuggerForExec, ) from nuitka.utils.FileOperations import ( deleteFile, getDirectoryRealPath, getExternalUsePath, makePath, putTextFileContents, removeDirectory, ) from nuitka.utils.Importing import getSharedLibrarySuffix from nuitka.utils.ModuleNames import ModuleName from nuitka.utils.ReExecute import callExecProcess, reExecuteNuitka from nuitka.utils.StaticLibraries import getSystemStaticLibPythonPath from nuitka.utils.Utils import getArchitecture, getOS, isWin32Windows from nuitka.Version import getCommercialVersion, getNuitkaVersion from . import ModuleRegistry, Options, OutputDirectories, TreeXML from .build import SconsInterface from .codegen import CodeGeneration, LoaderCodes, Reports from .finalizations import Finalization from .freezer.Onefile import packDistFolderToOnefile from .freezer.Standalone import copyUsedDLLs from .optimizations.Optimization import optimizeModules from .pgo.PGO import readPGOInputFile from .Reports import writeCompilationReport from .tree import Building def _createNodeTree(filename): """Create a node tree. Turn that source code into a node tree structure. If recursion into imported modules is available, more trees will be available during optimization, or immediately through recursed directory paths. """ # Many cases to deal with, pylint: disable=too-many-branches # First, build the raw node tree from the source code. main_module = Building.buildMainModuleTree( filename=filename, is_main=not Options.shallMakeModule(), ) # First remove old object files and old generated files, old binary or # module, and standalone mode program directory if any, they can only do # harm. source_dir = OutputDirectories.getSourceDirectoryPath() if not Options.shallOnlyExecCCompilerCall(): SconsInterface.cleanSconsDirectory(source_dir) # Prepare the ".dist" directory, throwing away what was there before. if Options.isStandaloneMode(): standalone_dir = OutputDirectories.getStandaloneDirectoryPath() removeDirectory(path=standalone_dir, ignore_errors=True) makePath(standalone_dir) # Delete result file, to avoid confusion with previous build and to # avoid locking issues after the build. deleteFile( path=OutputDirectories.getResultFullpath(onefile=False), must_exist=False ) if Options.isOnefileMode(): deleteFile( path=OutputDirectories.getResultFullpath(onefile=True), must_exist=False ) # Second, do it for the directories given. for plugin_filename in Options.getShallFollowExtra(): Recursion.checkPluginPath(plugin_filename=plugin_filename, module_package=None) for pattern in Options.getShallFollowExtraFilePatterns(): Recursion.checkPluginFilenamePattern(pattern=pattern) for package_name in Options.getMustIncludePackages(): package_name, package_directory, kind = Importing.locateModule( module_name=ModuleName(package_name), parent_package=None, level=0, ) if kind != "absolute": inclusion_logger.sysexit( "Error, failed to locate package %r you asked to include." % package_name.asString() ) Recursion.checkPluginPath( plugin_filename=package_directory, module_package=package_name.getPackageName(), ) for module_name in Options.getMustIncludeModules(): module_name, module_filename, kind = Importing.locateModule( module_name=ModuleName(module_name), parent_package=None, level=0, ) if kind != "absolute": inclusion_logger.sysexit( "Error, failed to locate module '%s' you asked to include." % module_name.asString() ) Recursion.checkPluginSinglePath( plugin_filename=module_filename, module_package=module_name.getPackageName() ) # Allow plugins to add more modules based on the initial set being complete. Plugins.onModuleInitialSet() # Then optimize the tree and potentially recursed modules. optimizeModules(main_module.getOutputFilename()) # Allow plugins to comment on final module set. Plugins.onModuleCompleteSet() if Options.isExperimental("check_xml_persistence"): for module in ModuleRegistry.getRootModules(): if module.isMainModule(): return module assert False else: # Main module might change behind our back, look it up again. return main_module def dumpTreeXML(tree): xml_root = tree.asXml() TreeXML.dump(xml_root) def pickSourceFilenames(source_dir, modules): """Pick the names for the C files of each module. Args: source_dir - the directory to put the module sources will be put into modules - all the modules to build. Returns: Dictionary mapping modules to filenames in source_dir. Notes: These filenames can collide, due to e.g. mixed case usage, or there being duplicate copies, e.g. a package named the same as the main binary. Conflicts are resolved by appending @ with a count in the list of sorted modules. We try to be reproducible here, so we get still good caching for external tools. """ collision_filenames = set() def _getModuleFilenames(module): base_filename = os.path.join(source_dir, "module." + module.getFullName()) # Note: Could detect if the file system is cases sensitive in source_dir # or not, but that's probably not worth the effort. False positives do # no harm at all. We cannot use normcase, as macOS is not using one that # will tell us the truth. collision_filename = base_filename.lower() return base_filename, collision_filename seen_filenames = set() # First pass, check for collisions. for module in modules: if module.isPythonShlibModule(): continue _base_filename, collision_filename = _getModuleFilenames(module) if collision_filename in seen_filenames: collision_filenames.add(collision_filename) seen_filenames.add(collision_filename) # Our output. module_filenames = {} # Count up for colliding filenames as we go. collision_counts = {} # Second pass, this time sorted, so we get deterministic results. We will # apply an "@1"/"@2",... to disambiguate the filenames. for module in sorted(modules, key=lambda x: x.getFullName()): if module.isPythonShlibModule(): continue base_filename, collision_filename = _getModuleFilenames(module) if collision_filename in collision_filenames: collision_counts[collision_filename] = ( collision_counts.get(collision_filename, 0) + 1 ) base_filename += "@%d" % collision_counts[collision_filename] module_filenames[module] = base_filename + ".c" return module_filenames standalone_entry_points = [] def makeSourceDirectory(): """Get the full list of modules imported, create code for all of them.""" # We deal with a lot of details here, but rather one by one, and split makes # no sense, pylint: disable=too-many-branches # assert main_module in ModuleRegistry.getDoneModules() # We might have chosen to include it as bytecode, and only compiled it for # fun, and to find its imports. In this case, now we just can drop it. Or # a module may shadow a frozen module, but be a different one, then we can # drop the frozen one. # TODO: This really should be done when the compiled module comes into # existence. for module in ModuleRegistry.getDoneModules(): if module.isCompiledPythonModule(): uncompiled_module = ModuleRegistry.getUncompiledModule( module_name=module.getFullName(), module_filename=module.getCompileTimeFilename(), ) if uncompiled_module is not None: # We now need to decide which one to keep, compiled or uncompiled # module. Some uncompiled modules may have been asked by the user # or technically required. By default, frozen code if it exists # is preferred, as it will be from standalone mode adding it. if ( uncompiled_module.isUserProvided() or uncompiled_module.isTechnical() ): ModuleRegistry.removeDoneModule(module) else: ModuleRegistry.removeUncompiledModule(uncompiled_module) # Lets check if the asked modules are actually present, and warn the # user if one of those was not found. for any_case_module in Options.getShallFollowModules(): if "*" in any_case_module or "{" in any_case_module: continue for module in ModuleRegistry.getDoneModules(): if module.getFullName() == any_case_module: break else: general.warning( "Did not follow import to unused '%s', consider include options." % any_case_module ) # Prepare code generation, i.e. execute finalization for it. for module in ModuleRegistry.getDoneModules(): if module.isCompiledPythonModule(): Finalization.prepareCodeGeneration(module) # Do some reporting and determine compiled module to work on compiled_modules = [] for module in ModuleRegistry.getDoneModules(): if module.isCompiledPythonModule(): compiled_modules.append(module) if Options.isShowInclusion(): inclusion_logger.info( "Included compiled module '%s'." % module.getFullName() ) elif module.isPythonShlibModule(): addShlibEntryPoint(module) if Options.isShowInclusion(): inclusion_logger.info( "Included extension module '%s'." % module.getFullName() ) elif module.isUncompiledPythonModule(): if Options.isShowInclusion(): inclusion_logger.info( "Included uncompiled module '%s'." % module.getFullName() ) else: assert False, module # Pick filenames. source_dir = OutputDirectories.getSourceDirectoryPath() module_filenames = pickSourceFilenames( source_dir=source_dir, modules=compiled_modules ) setupProgressBar( stage="C Source Generation", unit="module", total=len(compiled_modules), ) # Generate code for compiled modules, this can be slow, so do it separately # with a progress bar. for module in compiled_modules: c_filename = module_filenames[module] reportProgressBar( item=module.getFullName(), ) source_code = CodeGeneration.generateModuleCode( module=module, data_filename=os.path.basename(c_filename + "onst"), # Really .const ) writeSourceCode(filename=c_filename, source_code=source_code) closeProgressBar() ( helper_decl_code, helper_impl_code, constants_header_code, constants_body_code, ) = CodeGeneration.generateHelpersCode() writeSourceCode( filename=os.path.join(source_dir, "__helpers.h"), source_code=helper_decl_code ) writeSourceCode( filename=os.path.join(source_dir, "__helpers.c"), source_code=helper_impl_code ) writeSourceCode( filename=os.path.join(source_dir, "__constants.h"), source_code=constants_header_code, ) writeSourceCode( filename=os.path.join(source_dir, "__constants.c"), source_code=constants_body_code, ) def _runPgoBinary(): pgo_executable = OutputDirectories.getPgoRunExecutable() if not os.path.isfile(pgo_executable): general.sysexit("Error, failed to produce PGO binary '%s'" % pgo_executable) return callProcess( [getExternalUsePath(pgo_executable)] + Options.getPgoArgs(), shell=False, ) def _wasMsvcMode(): if not isWin32Windows(): return False return ( getSconsReportValue( source_dir=OutputDirectories.getSourceDirectoryPath(), key="msvc_mode" ) == "True" ) def _deleteMsvcPGOFiles(pgo_mode): assert _wasMsvcMode() msvc_pgc_filename = OutputDirectories.getResultBasepath(onefile=False) + "!1.pgc" deleteFile(msvc_pgc_filename, must_exist=False) if pgo_mode == "use": msvc_pgd_filename = OutputDirectories.getResultBasepath(onefile=False) + ".pgd" deleteFile(msvc_pgd_filename, must_exist=False) return msvc_pgc_filename def _runCPgoBinary(): # Note: For exit codes, we do not insist on anything yet, maybe we could point it out # or ask people to make scripts that buffer these kinds of errors, and take an error # instead as a serious failure. general.info( "Running created binary to produce C level PGO information:", style="blue" ) if _wasMsvcMode(): msvc_pgc_filename = _deleteMsvcPGOFiles(pgo_mode="generate") with withEnvironmentVarOverriden( "PATH", getSconsReportValue( source_dir=OutputDirectories.getSourceDirectoryPath(), key="PATH" ), ): _exit_code = _runPgoBinary() pgo_data_collected = os.path.exists(msvc_pgc_filename) else: _exit_code = _runPgoBinary() gcc_constants_pgo_filename = os.path.join( OutputDirectories.getSourceDirectoryPath(), "__constants.gcda" ) pgo_data_collected = os.path.exists(gcc_constants_pgo_filename) if not pgo_data_collected: general.sysexit( "Error, no PGO information produced, did the created binary run at all?" ) general.info("Successfully collected C level PGO information.", style="blue") def _runPythonPgoBinary(): # Note: For exit codes, we do not insist on anything yet, maybe we could point it out # or ask people to make scripts that buffer these kinds of errors, and take an error # instead as a serious failure. pgo_filename = OutputDirectories.getPgoRunInputFilename() with withEnvironmentVarOverriden("NUITKA_PGO_OUTPUT", pgo_filename): _exit_code = _runPgoBinary() if not os.path.exists(pgo_filename): general.sysexit( "Error, no Python PGO information produced, did the created binary run at all?" ) return pgo_filename def runSconsBackend(quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=False), "source_dir": OutputDirectories.getSourceDirectoryPath(), "nuitka_python": asBoolStr(isNuitkaPython()), "debug_mode": asBoolStr(Options.is_debug), "python_debug": asBoolStr(Options.isPythonDebug()), "unstripped_mode": asBoolStr(Options.isUnstripped()), "module_mode": asBoolStr(Options.shallMakeModule()), "full_compat": asBoolStr(Options.is_fullcompat), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "python_version": python_version_str, "target_arch": getArchitecture(), "python_prefix": getDirectoryRealPath(getSystemPrefixPath()), "nuitka_src": SconsInterface.getSconsDataPath(), "module_count": "%d" % ( 1 + len(ModuleRegistry.getDoneModules()) + len(ModuleRegistry.getUncompiledNonTechnicalModules()) ), } if Options.isLowMemory(): options["low_memory"] = asBoolStr(True) if not Options.shallMakeModule(): options["result_exe"] = OutputDirectories.getResultFullpath(onefile=False) main_module = ModuleRegistry.getRootTopModule() assert main_module.isMainModule() main_module_name = main_module.getFullName() if main_module_name != "__main__": options["main_module_name"] = main_module_name if Options.shallUseStaticLibPython(): options["static_libpython"] = getSystemStaticLibPythonPath() if isDebianPackagePython(): options["debian_python"] = asBoolStr(True) if isMSYS2MingwPython(): options["msys2_mingw_python"] = asBoolStr(True) if isAnacondaPython(): options["anaconda_python"] = asBoolStr(True) if isApplePython(): options["apple_python"] = asBoolStr(True) if isPyenvPython(): options["pyenv_python"] = asBoolStr(True) if Options.isStandaloneMode(): options["standalone_mode"] = asBoolStr(True) if Options.isOnefileMode(): options["onefile_mode"] = asBoolStr(True) if Options.isOnefileTempDirMode(): options["onefile_temp_mode"] = asBoolStr(True) if Options.getForcedStdoutPath(): options["forced_stdout_path"] = Options.getForcedStdoutPath() if Options.getForcedStderrPath(): options["forced_stderr_path"] = Options.getForcedStderrPath() if Options.shallTreatUninstalledPython(): options["uninstalled_python"] = asBoolStr(True) if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules()) ) if getOS() == "Windows": options["noelf_mode"] = asBoolStr(True) if Options.isProfile(): options["profile_mode"] = asBoolStr(True) if hasPythonFlagNoWarnings(): options["no_python_warnings"] = asBoolStr(True) if hasPythonFlagNoAsserts(): options["python_sysflag_optimize"] = asBoolStr(True) if python_version < 0x300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = asBoolStr(True) if python_version < 0x300 and ( sys.flags.division_warning or sys.flags.py3k_warning ): options["python_sysflag_division_warning"] = asBoolStr(True) if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = asBoolStr(True) if int(os.environ.get("NUITKA_NOSITE_FLAG", Options.hasPythonFlagNoSite())): options["python_sysflag_no_site"] = asBoolStr(True) if Options.hasPythonFlagTraceImports(): options["python_sysflag_verbose"] = asBoolStr(True) if Options.hasPythonFlagNoRandomization(): options["python_sysflag_no_randomization"] = asBoolStr(True) if python_version < 0x300 and sys.flags.unicode: options["python_sysflag_unicode"] = asBoolStr(True) if python_version >= 0x370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = asBoolStr(True) abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags if Options.shallMakeModule(): options["module_suffix"] = getSharedLibrarySuffix(preferred=True) SconsInterface.setCommonOptions(options) if Options.shallCreatePgoInput(): options["pgo_mode"] = "python" result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ) if not result: return result, options # Need to make it usable before executing it. executePostProcessing() _runPythonPgoBinary() return True, options # Need to restart compilation from scratch here. if Options.isPgoMode(): # For C level PGO, we have a 2 pass system. TODO: Make it more global for onefile # and standalone mode proper support, which might need data files to be # there, which currently are not yet there, so it won't run. if Options.isPgoMode(): options["pgo_mode"] = "generate" result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ) if not result: return result, options # Need to make it usable before executing it. executePostProcessing() _runCPgoBinary() options["pgo_mode"] = "use" result = ( SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ), options, ) if options.get("pgo_mode") == "use" and _wasMsvcMode(): _deleteMsvcPGOFiles(pgo_mode="use") return result def writeSourceCode(filename, source_code): # Prevent accidental overwriting. When this happens the collision detection # or something else has failed. assert not os.path.isfile(filename), filename putTextFileContents(filename=filename, contents=source_code, encoding="latin1") def writeBinaryData(filename, binary_data): # Prevent accidental overwriting. When this happens the collision detection # or something else has failed. assert not os.path.isfile(filename), filename assert type(binary_data) is bytes with open(filename, "wb") as output_file: output_file.write(binary_data) def callExecPython(args, clean_path, add_path): old_python_path = os.environ.get("PYTHONPATH") if clean_path and old_python_path is not None: os.environ["PYTHONPATH"] = "" if add_path: if "PYTHONPATH" in os.environ: os.environ["PYTHONPATH"] += ":" + Options.getOutputDir() else: os.environ["PYTHONPATH"] = Options.getOutputDir() # We better flush these, "os.execl" won't do it anymore. sys.stdout.flush() sys.stderr.flush() # Add the main arguments, previous separated. args += Options.getPositionalArgs()[1:] + Options.getMainArgs() callExecProcess(args) def executeMain(binary_filename, clean_path): if Options.shallRunInDebugger(): args = wrapCommandForDebuggerForExec(binary_filename) else: args = (binary_filename, binary_filename) callExecPython(clean_path=clean_path, add_path=False, args=args) def executeModule(tree, clean_path): if python_version < 0x340: python_command_template = """\ import os, imp;\ assert os.path.normcase(os.path.abspath(os.path.normpath(\ imp.find_module('%(module_name)s')[1]))) == %(expected_filename)r,\ 'Error, cannot launch extension module %(module_name)s, original package is in the way.'""" else: python_command_template = """\ import os, importlib.util;\ assert os.path.normcase(os.path.abspath(os.path.normpath(\ importlib.util.find_spec('%(module_name)s').origin))) == %(expected_filename)r,\ 'Error, cannot launch extension module %(module_name)s, original package is in the way.'""" python_command_template += ";__import__('%(module_name)s')" python_command = python_command_template % { "module_name": tree.getName(), "expected_filename": os.path.normcase( os.path.abspath( os.path.normpath(OutputDirectories.getResultFullpath(onefile=False)) ) ), } if Options.shallRunInDebugger(): args = wrapCommandForDebuggerForExec(sys.executable, "-c", python_command) else: args = (sys.executable, "python", "-c", python_command) callExecPython(clean_path=clean_path, add_path=True, args=args) def compileTree(): source_dir = OutputDirectories.getSourceDirectoryPath() general.info("Completed Python level compilation and optimization.") if not Options.shallOnlyExecCCompilerCall(): general.info("Generating source code for C backend compiler.") if Options.isShowProgress() or Options.isShowMemory(): general.info( "Total memory usage before generating C code: {memory}:".format( memory=MemoryUsage.getHumanReadableProcessMemoryUsage() ) ) # Now build the target language code for the whole tree. makeSourceDirectory() bytecode_accessor = ConstantAccessor( data_filename="__bytecode.const", top_level_name="bytecode_data" ) # This should take all bytecode values, even ones needed for frozen or # not produce anything. loader_code = LoaderCodes.getMetapathLoaderBodyCode(bytecode_accessor) writeSourceCode( filename=os.path.join(source_dir, "__loader.c"), source_code=loader_code ) else: source_dir = OutputDirectories.getSourceDirectoryPath() if not os.path.isfile(os.path.join(source_dir, "__helpers.h")): general.sysexit("Error, no previous build directory exists.") if Options.isShowProgress() or Options.isShowMemory(): general.info( "Total memory usage before running scons: {memory}:".format( memory=MemoryUsage.getHumanReadableProcessMemoryUsage() ) ) if Options.isShowMemory(): InstanceCounters.printStats() if Options.is_debug: Reports.doMissingOptimizationReport() if Options.shallNotDoExecCCompilerCall(): return True, {} general.info("Running data composer tool for optimal constant value handling.") blob_filename = runDataComposer(source_dir) Plugins.onDataComposerResult(blob_filename) for filename, source_code in Plugins.getExtraCodeFiles().items(): target_dir = os.path.join(source_dir, "plugins") if not os.path.isdir(target_dir): makePath(target_dir) writeSourceCode( filename=os.path.join(target_dir, filename), source_code=source_code ) general.info("Running C compilation via Scons.") # Run the Scons to build things. result, options = runSconsBackend(quiet=not Options.isShowScons()) return result, options def handleSyntaxError(e): # Syntax or indentation errors, output them to the user and abort. If # we are not in full compat, and user has not specified the Python # versions he wants, tell him about the potential version problem. error_message = SyntaxErrors.formatOutput(e) if not Options.is_fullcompat: if python_version < 0x300: suggested_python_version_str = getSupportedPythonVersions()[-1] else: suggested_python_version_str = "2.7" error_message += """ Nuitka is very syntax compatible with standard Python. It is currently running with Python version '%s', you might want to specify more clearly with the use of the precise Python interpreter binary and '-m nuitka', e.g. use this 'python%s -m nuitka' option, if that's not the one the program expects. """ % ( python_version_str, suggested_python_version_str, ) sys.exit(error_message) def main(): """Main program flow of Nuitka At this point, options will be parsed already, Nuitka will be executing in the desired version of Python with desired flags, and we just get to execute the task assigned. We might be asked to only re-compile generated C, dump only an XML representation of the internal node tree after optimization, etc. """ # Main has to fulfill many options, leading to many branches and statements # to deal with them. pylint: disable=too-many-branches,too-many-statements # In case we are in a PGO run, we read its information first, so it becomes # available for later parts. pgo_filename = getPythonPgoInput() if pgo_filename is not None: readPGOInputFile(pgo_filename) if not Options.shallDumpBuiltTreeXML(): general.info( "Starting Python compilation with Nuitka %r on Python %r commercial %r." % (getNuitkaVersion(), python_version_str, getCommercialVersion()) ) filename = Options.getPositionalArgs()[0] # Inform the importing layer about the main script directory, so it can use # it when attempting to follow imports. Importing.setMainScriptDirectory( main_dir=os.path.dirname(os.path.abspath(filename)) ) # Turn that source code into a node tree structure. try: main_module = _createNodeTree(filename=filename) except (SyntaxError, IndentationError) as e: handleSyntaxError(e) if Options.shallDumpBuiltTreeXML(): # XML output only. for module in ModuleRegistry.getDoneModules(): dumpTreeXML(module) else: # Make the actual compilation. result, options = compileTree() # Exit if compilation failed. if not result: sys.exit(1) # Relaunch in case of Python PGO input to be produced. if Options.shallCreatePgoInput(): # Will not return. pgo_filename = OutputDirectories.getPgoRunInputFilename() general.info( "Restarting compilation using collected information from '%s'." % pgo_filename ) reExecuteNuitka(pgo_filename=pgo_filename) if Options.shallNotDoExecCCompilerCall(): if Options.isShowMemory(): MemoryUsage.showMemoryTrace() sys.exit(0) executePostProcessing() if Options.isStandaloneMode(): binary_filename = options["result_exe"] setMainEntryPoint(binary_filename) dist_dir = OutputDirectories.getStandaloneDirectoryPath() for module in ModuleRegistry.getDoneModules(): addIncludedEntryPoints(Plugins.considerExtraDlls(dist_dir, module)) copyUsedDLLs( source_dir=OutputDirectories.getSourceDirectoryPath(), dist_dir=dist_dir, standalone_entry_points=getStandaloneEntryPoints(), ) copyDataFiles(dist_dir=dist_dir) Plugins.onStandaloneDistributionFinished(dist_dir) if Options.isOnefileMode(): packDistFolderToOnefile(dist_dir, binary_filename) if Options.isRemoveBuildDir(): general.info("Removing dist folder %r." % dist_dir) removeDirectory(path=dist_dir, ignore_errors=False) else: general.info( "Keeping dist folder %r for inspection, no need to use it." % dist_dir ) # Remove the source directory (now build directory too) if asked to. source_dir = OutputDirectories.getSourceDirectoryPath() if Options.isRemoveBuildDir(): general.info("Removing build directory %r." % source_dir) removeDirectory(path=source_dir, ignore_errors=False) assert not os.path.exists(source_dir) else: general.info("Keeping build directory %r." % source_dir) final_filename = OutputDirectories.getResultFullpath( onefile=Options.isOnefileMode() ) if "macos_minversion" in options: general.info( "Created binary that runs on macOS %s or higher." % options["macos_minversion"] ) Plugins.onFinalResult(final_filename) general.info("Successfully created %r." % final_filename) report_filename = Options.getCompilationReportFilename() if report_filename: writeCompilationReport(report_filename) # Execute the module immediately if option was given. if Options.shallExecuteImmediately(): run_filename = OutputDirectories.getResultRunFilename( onefile=Options.isOnefileMode() ) general.info("Launching %r." % run_filename) if Options.shallMakeModule(): executeModule( tree=main_module, clean_path=Options.shallClearPythonPathEnvironment(), ) else: executeMain( binary_filename=run_filename, clean_path=Options.shallClearPythonPathEnvironment(), ) Nuitka-0.6.19.1/nuitka/SourceCodeReferences.py0000600000372100037210000001107614166627112026176 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Source code reference record. All the information to lookup line and file of a code location, together with the future flags in use there. """ from nuitka.__past__ import total_ordering from nuitka.utils.InstanceCounters import ( counted_del, counted_init, isCountingInstances, ) @total_ordering class SourceCodeReference(object): __slots__ = ["filename", "line", "column"] @classmethod def fromFilenameAndLine(cls, filename, line): result = cls() result.filename = filename result.line = line return result if isCountingInstances(): __del__ = counted_del() @counted_init def __init__(self): self.filename = None self.line = None self.column = None def __repr__(self): return "<%s to %s:%s>" % (self.__class__.__name__, self.filename, self.line) def __hash__(self): return hash((self.filename, self.line, self.column)) def __lt__(self, other): # Many cases decide early, pylint: disable=too-many-return-statements if other is None: return True if other is self: return False assert isinstance(other, SourceCodeReference), other if self.filename < other.filename: return True elif self.filename > other.filename: return False else: if self.line < other.line: return True elif self.line > other.line: return False else: if self.column < other.column: return True elif self.column > other.column: return False else: return self.isInternal() < other.isInternal() def __eq__(self, other): if other is None: return False if other is self: return True assert isinstance(other, SourceCodeReference), other if self.filename != other.filename: return False if self.line != other.line: return False if self.column != other.column: return False return self.isInternal() is other.isInternal() def _clone(self, line): """Make a copy it itself.""" return self.fromFilenameAndLine(filename=self.filename, line=line) def atInternal(self): """Make a copy it itself but mark as internal code. Avoids useless copies, by returning an internal object again if it is already internal. """ if not self.isInternal(): result = self._clone(self.line) return result else: return self def atLineNumber(self, line): """Make a reference to the same file, but different line. Avoids useless copies, by returning same object if the line is the same. """ assert type(line) is int, line if self.line != line: return self._clone(line) else: return self def atColumnNumber(self, column): assert type(column) is int, column if self.column != column: result = self._clone(self.line) result.column = column return result else: return self def getLineNumber(self): return self.line def getColumnNumber(self): return self.column def getFilename(self): return self.filename def getAsString(self): return "%s:%s" % (self.filename, self.line) @staticmethod def isInternal(): return False class SourceCodeReferenceInternal(SourceCodeReference): __slots__ = () @staticmethod def isInternal(): return True def fromFilename(filename): return SourceCodeReference.fromFilenameAndLine(filename=filename, line=1) Nuitka-0.6.19.1/nuitka/containers/0000700000372100037210000000000014167275622023733 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/containers/oset.py0000600000372100037210000000762714166627112025267 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2009 Raymond Hettinger # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Note: Kay Hayen did some changes for Nuitka keeping this license. These # changes are not improvements, use the original source instead, not this # file. """ This module is only an abstraction of OrderedSet which is not present in Python at all. It was originally downloaded from http://code.activestate.com/recipes/576694/ """ # pylint: disable=I0021,arguments-differ,redefined-builtin from nuitka.__past__ import MutableSet try: from orderedset import OrderedSet except ImportError: class OrderedSet(MutableSet): def __init__(self, iterable=()): # pylint: disable=super-init-not-called self.end = end = [] end += (None, end, end) # sentinel node for doubly linked list self.map = {} # key --> [key, prev, next] if iterable: self |= iterable def __len__(self): return len(self.map) def __contains__(self, key): return key in self.map def add(self, key): if key not in self.map: end = self.end curr = end[1] curr[2] = end[1] = self.map[key] = [key, curr, end] def update(self, keys): for key in keys: self.add(key) def discard(self, key): if key in self.map: key, prev, next = self.map.pop(key) prev[2] = next next[1] = prev def __iter__(self): end = self.end curr = end[2] while curr is not end: yield curr[0] curr = curr[2] def __reversed__(self): end = self.end curr = end[1] while curr is not end: yield curr[0] curr = curr[1] def pop(self, last=True): if not self: raise KeyError("set is empty") key = self.end[1][0] if last else self.end[2][0] self.discard(key) return key def __repr__(self): if not self: return "%s()" % (self.__class__.__name__,) return "%s(%r)" % (self.__class__.__name__, list(self)) def __eq__(self, other): if isinstance(other, OrderedSet): return len(self) == len(other) and list(self) == list(other) return set(self) == set(other) def union(self, iterable): result = OrderedSet(self) for key in iterable: result.add(key) return result def index(self, key): if key in self.map: end = self.end curr = self.map[key] count = 0 while curr is not end: curr = curr[1] count += 1 return count - 1 return None Nuitka-0.6.19.1/nuitka/containers/__init__.py0000600000372100037210000000150114166627112026035 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/containers/odict.py0000600000372100037210000001463114166627112025410 0ustar nuitka-buildslavenuitka-buildslave00000000000000""" This module is only an abstraction of OrderedDict as present in 2.7 and 3.x. It is not in 2.6, for this version we are using the odict.py as mentioned in the PEP-0372. This can be removed safely after Python2.6 support is dropped (if ever), note that the documentation was removed, as it's not interesting really, being redundant to the Python 2.7 documentation. Starting with Python 3.6, we can safely use the built-in dictionary. """ # :copyright: (c) 2008 by Armin Ronacher and PEP 273 authors. # :license: modified BSD license. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Kay Hayen did some changes for Nuitka, and put everything he added under the same # modified BSD license. from nuitka.PythonVersions import python_version try: if python_version >= 0x360: OrderedDict = dict else: from collections import OrderedDict except ImportError: # This is for Python 2.6 only. # pylint: disable=I0021,protected-access,undefined-variable assert python_version < 0x270 from copy import deepcopy from itertools import imap, izip missing = object() class OrderedDict(dict): def __init__(self, *args, **kwargs): dict.__init__(self) self._keys = [] self.update(*args, **kwargs) def __delitem__(self, key): dict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): if key not in self: self._keys.append(key) dict.__setitem__(self, key, item) def __deepcopy__(self, memo=None): if memo is None: memo = {} d = memo.get(id(self), missing) if d is not missing: return d memo[id(self)] = d = self.__class__() dict.__init__(d, deepcopy(self.items(), memo)) d._keys = self._keys[:] return d def __getstate__(self): return {"items": dict(self), "keys": self._keys} def __setstate__(self, d): self._keys = d["keys"] dict.update(d["items"]) def __reversed__(self): return reversed(self._keys) def __eq__(self, other): if isinstance(other, OrderedDict): if not dict.__eq__(self, other): return False return self.items() == other.items() return dict.__eq__(self, other) def __ne__(self, other): return not self.__eq__(other) def __cmp__(self, other): if isinstance(other, OrderedDict): return cmp(self.items(), other.items()) elif isinstance(other, dict): return dict.__cmp__(self, other) return NotImplemented @classmethod def fromkeys(cls, iterable, default=None): return cls((key, default) for key in iterable) def clear(self): del self._keys[:] dict.clear(self) def copy(self): return self.__class__(self) def items(self): return zip(self._keys, self.values()) def iteritems(self): return izip(self._keys, self.itervalues()) def keys(self): return self._keys[:] def iterkeys(self): return iter(self._keys) def pop(self, key, default=missing): if default is missing: return dict.pop(self, key) elif key not in self: return default self._keys.remove(key) return dict.pop(self, key, default) def popitem(self, key): self._keys.remove(key) return dict.popitem(key) def setdefault(self, key, default=None): if key not in self: self._keys.append(key) dict.setdefault(self, key, default) def update(self, *args, **kwargs): sources = [] if len(args) == 1: if hasattr(args[0], "iteritems"): sources.append(args[0].iteritems()) else: sources.append(iter(args[0])) elif args: raise TypeError("expected at most one positional argument") if kwargs: sources.append(kwargs.iteritems()) for iterable in sources: for key, val in iterable: self[key] = val def values(self): return map(self.get, self._keys) def itervalues(self): return imap(self.get, self._keys) def index(self, item): return self._keys.index(item) def byindex(self, item): key = self._keys[item] return (key, dict.__getitem__(self, key)) def reverse(self): self._keys.reverse() def sort(self, *args, **kwargs): self._keys.sort(*args, **kwargs) def __repr__(self): return "OrderedDict(%r)" % self.items() __copy__ = copy __iter__ = iterkeys Nuitka-0.6.19.1/nuitka/Progress.py0000600000372100037210000001312214166627112023737 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Progress bars in Nuitka. This is responsible for wrapping the rendering of progress bar and emitting tracing to the user while it's being displayed. """ from contextlib import contextmanager from nuitka import Tracing from nuitka.Tracing import general from nuitka.utils.Importing import importFromInlineCopy from nuitka.utils.ThreadedExecutor import RLock from nuitka.utils.Utils import isWin32Windows # Late import and optional to be there. use_progress_bar = False tqdm = None class NuitkaProgessBar(object): def __init__(self, iterable, stage, total, min_total, unit): self.total = total # The minimum may not be provided, then default to 0. self.min_total = min_total # No item under work yet. self.item = None # No progress yet. self.progress = 0 # Render immediately with 0 progress, and setting disable=None enables tty detection. self.tqdm = tqdm( iterable=iterable, initial=self.progress, total=max(self.total, self.min_total) if self.min_total is not None else None, unit=unit, disable=None, leave=False, bar_format="{desc}{percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}{postfix}", ) self.tqdm.set_description(stage) self.setCurrent(self.item) def __iter__(self): return iter(self.tqdm) def updateTotal(self, total): if total != self.total: self.total = total self.tqdm.total = max(total, self.min_total) def setCurrent(self, item): if item != self.item: self.item = item if item is not None: self.tqdm.set_postfix_str(item) else: self.tqdm.set_postfix() def update(self): self.progress += 1 self.tqdm.update(1) def clear(self): self.tqdm.clear() def close(self): self.tqdm.close() @contextmanager def withExternalWritingPause(self): with self.tqdm.external_write_mode(): yield def _getTqdmModule(): global tqdm # singleton, pylint: disable=global-statement if tqdm: return tqdm elif tqdm is False: return None else: tqdm = importFromInlineCopy("tqdm", must_exist=False) if tqdm is None: try: # Cannot use import tqdm due to pylint bug. import tqdm as tqdm_installed # pylint: disable=I0021,import-error tqdm = tqdm_installed except ImportError: # We handle the case without inline copy too, but it may be removed, e.g. on # Debian it's only a recommended install, and not included that way. pass if tqdm is None: tqdm = False return None tqdm = tqdm.tqdm # Tolerate the absence ignore the progress bar tqdm.set_lock(RLock()) return tqdm def enableProgressBar(): global use_progress_bar # singleton, pylint: disable=global-statement if _getTqdmModule() is not None: use_progress_bar = True if isWin32Windows(): colorama = importFromInlineCopy("colorama", must_exist=True) colorama.init() def setupProgressBar(stage, unit, total, min_total=0): # Make sure the other was closed. assert Tracing.progress is None if use_progress_bar: Tracing.progress = NuitkaProgessBar( iterable=None, stage=stage, total=total, min_total=min_total, unit=unit, ) def reportProgressBar(item, total=None, update=True): if Tracing.progress is not None: try: if total is not None: Tracing.progress.updateTotal(total) Tracing.progress.setCurrent(item) if update: Tracing.progress.update() except Exception: # Catch all the things, pylint: disable=broad-except # We disable the progress bar now, because it's causing issues. general.warning("Progress bar disabled due to bug") closeProgressBar() def closeProgressBar(): """Close the active progress bar. Returns: int or None - if displayed, the total used last time. """ if Tracing.progress is not None: # Retrieve that previous total, for repeated progress bars, it # can be used as a new minimum. result = Tracing.progress.total Tracing.progress.close() Tracing.progress = None return result def wrapWithProgressBar(iterable, stage, unit): if tqdm is None: return iterable else: result = NuitkaProgessBar( iterable=iterable, unit=unit, stage=stage, total=None, min_total=None ) Tracing.progress = result return result Nuitka-0.6.19.1/nuitka/finalizations/0000700000372100037210000000000014167275622024440 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/finalizations/FinalizeMarkups.py0000600000372100037210000001372314166627112030120 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Finalize the markups Set flags on functions and classes to indicate if a locals dict is really needed. Set a flag on loops if they really need to catch Continue and Break exceptions or if it can be more simple code. Set a flag on return statements and functions that require the use of "ReturnValue" exceptions, or if it can be more simple code. Set a flag on re-raises of exceptions if they can be simple throws or if they are in another context. """ from nuitka import Tracing from nuitka.__past__ import unicode from nuitka.containers.oset import OrderedSet from nuitka.PythonVersions import python_version from nuitka.tree.Operations import VisitorNoopMixin imported_names = OrderedSet() def getImportedNames(): return imported_names class FinalizeMarkups(VisitorNoopMixin): def onEnterNode(self, node): try: self._onEnterNode(node) except Exception: Tracing.printError( "Problem with %r at %s" % (node, node.getSourceReference().getAsString()) ) raise def _onEnterNode(self, node): # This has many different things it deals with, so there need to be a # lot of branches and statements, pylint: disable=too-many-branches # Also all self specific things have been done on the outside, # pylint: disable=no-self-use if node.isStatementReturn() or node.isStatementGeneratorReturn(): search = node in_tried_block = False # Search up to the containing function, and check for a try/finally # containing the "return" statement. search = search.getParentReturnConsumer() if ( search.isExpressionGeneratorObjectBody() or search.isExpressionCoroutineObjectBody() or search.isExpressionAsyncgenObjectBody() ): if in_tried_block: search.markAsNeedsGeneratorReturnHandling(2) else: search.markAsNeedsGeneratorReturnHandling(1) if node.isExpressionBuiltinImport() and node.follow_attempted: module_name = node.subnode_name if module_name.isCompileTimeConstant(): imported_module_name = module_name.getCompileTimeConstant() if type(imported_module_name) in (str, unicode): if imported_module_name: imported_names.add(imported_module_name) if node.isExpressionFunctionCreation(): if ( not node.getParent().isExpressionFunctionCall() or node.getParent().subnode_function is not node ): node.subnode_function_ref.getFunctionBody().markAsNeedsCreation() if node.isExpressionFunctionCall(): node.subnode_function.subnode_function_ref.getFunctionBody().markAsDirectlyCalled() if node.isExpressionFunctionRef(): function_body = node.getFunctionBody() parent_module = function_body.getParentModule() node_module = node.getParentModule() if node_module is not parent_module: function_body.markAsCrossModuleUsed() node_module.addCrossUsedFunction(function_body) if node.isStatementAssignmentVariable(): target_var = node.getVariable() assign_source = node.subnode_source if assign_source.isExpressionOperationBinary(): left_arg = assign_source.subnode_left if ( left_arg.isExpressionVariableRef() or left_arg.isExpressionTempVariableRef() ): if assign_source.subnode_left.getVariable() is target_var: if assign_source.isInplaceSuspect(): node.markAsInplaceSuspect() elif left_arg.isExpressionLocalsVariableRefOrFallback(): # TODO: This might be bad. assign_source.unmarkAsInplaceSuspect() if python_version < 0x300 and node.isStatementPublishException(): node.getParentStatementsFrame().markAsFrameExceptionPreserving() if python_version >= 0x300: if ( node.isExpressionYield() or node.isExpressionYieldFrom() or node.isExpressionYieldFromWaitable() ): search = node.getParent() # TODO: This is best achieved by having different yield nodes # depending on containing function kind to begin with and should # be discovered during the build. while ( not search.isExpressionGeneratorObjectBody() and not search.isExpressionCoroutineObjectBody() and not search.isExpressionAsyncgenObjectBody() ): last_search = search search = search.getParent() if ( search.isStatementTry() and last_search == search.subnode_except_handler ): node.markAsExceptionPreserving() break Nuitka-0.6.19.1/nuitka/finalizations/Finalization.py0000600000372100037210000000231014166627112027431 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Finalizations. Last steps directly before code creation is called. Here the final tasks are executed. Things normally volatile during optimization can be computed here, so the code generation can be quick and doesn't have to check it many times. """ from nuitka.tree import Operations from .FinalizeMarkups import FinalizeMarkups def prepareCodeGeneration(tree): visitor = FinalizeMarkups() Operations.visitTree(tree, visitor) Nuitka-0.6.19.1/nuitka/finalizations/__init__.py0000600000372100037210000000150114166627112026542 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/__init__.py0000600000372100037210000000150114166627112023670 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/0000700000372100037210000000000014167275622022726 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/specialize/0000700000372100037210000000000014167275622025056 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/specialize/SpecializeC.py0000600000372100037210000021205314166627112027622 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This tool is generating code variants for helper codes from Jinja templates. """ import nuitka.Options nuitka.Options.is_fullcompat = False # isort:start import math import os from abc import abstractmethod import nuitka.codegen.ComparisonCodes import nuitka.codegen.HelperDefinitions import nuitka.codegen.Namify import nuitka.specs.BuiltinDictOperationSpecs import nuitka.specs.BuiltinStrOperationSpecs import nuitka.specs.BuiltinUnicodeOperationSpecs from nuitka.__past__ import getMetaClassBase, long from nuitka.codegen.CallCodes import ( getQuickCallCode, getQuickMethodCallCode, getQuickMethodDescrCallCode, getQuickMixedCallCode, getTemplateCodeDeclaredFunction, max_quick_call, ) from nuitka.nodes.ImportNodes import hard_modules from nuitka.utils.Jinja2 import getTemplateC from .Common import ( formatArgs, getMethodVariations, python2_dict_methods, python2_str_methods, python2_unicode_methods, python3_dict_methods, python3_str_methods, withFileOpenedAndAutoformatted, writeline, ) def getDoExtensionUsingTemplateC(template_name): return getTemplateC( package_name="nuitka.codegen", template_subdir="templates_c", template_name=template_name, extensions=("jinja2.ext.do",), ) class TypeDescBase(getMetaClassBase("Type")): # To be overloaded type_name = None type_desc = None type_decl = None python_requirement = None def __init__(self): assert self.type_name assert self.type_desc assert self.type_decl def __repr__(self): return "<%s %s %s>" % (self.__class__.__name__, self.type_name, self.type_desc) @classmethod def getHelperCodeName(cls): return cls.type_name.upper() @classmethod def getTypeName2(cls): return cls.type_name @classmethod def getTypeName3(cls): return cls.type_name @classmethod def getVariableDecl(cls, variable_name): if cls.type_decl.endswith("*"): return cls.type_decl + variable_name else: return cls.type_decl + " " + variable_name @classmethod def getTypeDecl(cls): return cls.type_decl @classmethod def getCheckValueCode(cls, operand): return "CHECK_OBJECT(%s);" % operand @classmethod def getTypeValueExpression(cls, operand): return "Py_TYPE(%s)" % operand @abstractmethod def getNewStyleNumberTypeCheckExpression(self, operand): pass @staticmethod def needsIndexConversion(): return True def isKnownToNotCoerce(self, right): if right is self and right is not object_desc: return True if self in (int_desc, long_desc, float_desc): if right in ( str_desc, unicode_desc, tuple_desc, list_desc, set_desc, dict_desc, ): return True if ( self.getNewStyleNumberTypeCheckExpression("dummy") == "1" and right.getNewStyleNumberTypeCheckExpression("dummy") == "1" ): return True if self is not object_desc: return not self.hasSlot("nb_coerce") else: return False def getMostSpecificType(self, right): if self is not object_desc: return self else: return right def getLeastSpecificType(self, right): if self is object_desc: return self else: return right @classmethod def hasOneOrBothType(cls, right, type_name): # At least one match if type_name not in (cls.type_name, right.type_name): return False # Two matches perfect. if cls.type_name == right.type_name: return True if "object" not in (cls.type_name, right.type_name): return False return True @classmethod def mayBothHaveType(cls, right, type_name): return cls.type_name in (type_name, "object") and right.type_name in ( type_name, "object", ) @classmethod def getTypeCheckExactExpression(cls, operand): if cls.type_name == "str": return "PyStr_CheckExact(%s)" % operand elif cls.type_name == "dict": return "PyDict_CheckExact(%s)" % operand else: assert False, cls @classmethod def getIntCheckExpression(cls, operand): if cls.type_name == "int": return "1" elif cls.type_name == "object": return "PyInt_CheckExact(%s)" % operand else: return "0" @classmethod def getLongCheckExpression(cls, operand): if cls.type_name == "long": return "1" elif cls.type_name == "object": return "PyLong_CheckExact(%s)" % operand else: return "0" @classmethod def getStringCheckExpression(cls, operand): if cls.type_name == "str": return "1" elif cls.type_name == "object": return "PyString_CheckExact(%s)" % operand else: return "0" @classmethod def getBytesCheckExpression(cls, operand): if cls.type_name == "bytes": return "1" elif cls.type_name == "object": return "PyBytes_CheckExact(%s)" % operand else: return "0" @classmethod def getUnicodeCheckExpression(cls, operand): if cls.type_name == "unicode": return "1" elif cls.type_name == "object": return "PyUnicode_CheckExact(%s)" % operand else: return "0" @classmethod def getFloatCheckExpression(cls, operand): if cls.type_name == "float": return "1" elif cls.type_name == "object": return "PyFloat_CheckExact(%s)" % operand else: return "0" @classmethod def getListCheckExpression(cls, operand): if cls.type_name == "list": return "1" elif cls.type_name == "object": return "PyList_CheckExact(%s)" % operand else: return "0" def getSequenceCheckExpression(self, operand, right): # Dictionaries are not really sequences despite slots. if self.type_name == "dict": return "0" elif self.type_name == "object": if right.type_name == "tuple": return "(PyTuple_CheckExact(%s) || PySequence_Check(%s))" % ( operand, operand, ) else: return "PySequence_Check(%s)" % operand elif self.hasSlot("sq_item"): return "1" else: return "0" def getInstanceCheckCode(self, operand): # We do not yet specialize for instances, therefore everything but object is one. if self.type_name == "object": return "PyInstance_Check(%s)" % operand else: return "0" def getIndexCheckExpression(self, operand): if self.hasSlot("nb_index"): return "1" elif self.type_name == "object": return "PyIndex_Check(%s)" % operand else: return "0" def getSaneTypeCheckCode(self, operand): # Is the type known to behave well for comparisons and object identity, e.g. not float. if self.type_name == "object": return "IS_SANE_TYPE(Py_TYPE(%s))" % operand elif self in (str_desc, int_desc, long_desc, list_desc, tuple_desc): return "1" elif self in (float_desc,): return "0" else: # Detect types not yet annotated. assert False, self return "0" def getTypeIdenticalCheckExpression(self, other, operand1, operand2): if self is object_desc or other is object_desc: return "%s == %s" % (operand1, operand2) elif self is other: return "1" else: return "0" @staticmethod def getRealSubTypeCheckCode(right, type2, type1): if right is object_desc: return "PyType_IsSubtype(%s, %s)" % (type2, type1) else: return 0 @abstractmethod def hasSlot(self, slot): pass def _getSlotValueExpression(self, operand, slot): if slot.startswith("nb_"): return "(%s) ? %s : NULL" % ( operand + "->tp_as_number != NULL && " + self.getNewStyleNumberTypeCheckExpression(operand), operand + "->tp_as_number->" + slot, ) elif slot.startswith("sq_"): return "%s ? %s : NULL" % ( operand + "->tp_as_sequence" + " != NULL", operand + "->tp_as_sequence->" + slot, ) elif slot == "tp_richcompare": # Try to detect fallbacks, this needs version specific management # for at least "LONG", maybe others. assert self is object_desc, self return "RICHCOMPARE(%s)" % operand elif slot == "tp_compare": return operand + "->tp_compare" else: assert False, slot @staticmethod def getSlotType(slot): if slot in ("nb_power", "nb_inplace_power"): return "ternaryfunc" elif slot in ("sq_repeat", "sq_inplace_repeat"): return "ssizeargfunc" else: return "binaryfunc" @staticmethod def getSlotCallExpression(nb_slot, slot_var, operand1, operand2): if nb_slot in ("nb_power", "nb_inplace_power"): return "%s(%s, %s, Py_None)" % (slot_var, operand1, operand2) else: return "%s(%s, %s)" % (slot_var, operand1, operand2) def getSlotValueExpression(self, operand, slot): assert ( "inplace_" not in slot or not self.hasSlot(slot) or self in (set_desc, list_desc) ), self.hasSlot if not self.hasSlot(slot): return "NULL" return self._getSlotValueExpression(operand, slot) def getSlotValueCheckExpression(self, operand, slot): # Virtual method, pylint: disable=unused-argument return "true" if self.hasSlot(slot) else "false" @staticmethod def getOperationErrorMessageName(operator): if operator == "%": return "%%" elif operator == "**": return "** or pow()" elif operator == "divmod": return "divmod()" else: return operator def getReturnUnorderableTypeErrorCode( self, operator, left, right, operand1, operand2 ): args = [] if left is object_desc: args.append("%s->tp_name" % operand1) if right is object_desc: args.append("%s->tp_name" % operand2) if args: args = ", " + ", ".join(args) else: args = "" if ( left.getTypeName2() != left.getTypeName3() or right.getTypeName2() != right.getTypeName3() ): # TODO: The message for Python2, can it be triggered at all for non-objects? return """\ #if PYTHON_VERSION < 0x300 PyErr_Format(PyExc_TypeError, "unorderable types: %(left_type2)s() %(operator)s %(right_type2)s()"%(args)s); #elif PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %(left_type3)s() %(operator)s %(right_type3)s()"%(args)s); #else PyErr_Format(PyExc_TypeError, "'%(operator)s' not supported between instances of '%(left_type3)s' and '%(right_type3)s'"%(args)s); #endif return %(return_value)s;""" % { "operator": operator, "left_type2": "%s" if left is object_desc else left.getTypeName2(), "right_type2": "%s" if right is object_desc else right.getTypeName2(), "left_type3": "%s" if left is object_desc else left.getTypeName3(), "right_type3": "%s" if right is object_desc else right.getTypeName3(), "args": args, "return_value": self.getExceptionResultIndicatorValue(), } else: return """\ #if PYTHON_VERSION < 0x360 PyErr_Format(PyExc_TypeError, "unorderable types: %(left_type)s() %(operator)s %(right_type)s()"%(args)s); #else PyErr_Format(PyExc_TypeError, "'%(operator)s' not supported between instances of '%(left_type)s' and '%(right_type)s'"%(args)s); #endif return %(return_value)s;""" % { "operator": operator, "left_type": "%s" if left is object_desc else left.getTypeName2(), "right_type": "%s" if right is object_desc else right.getTypeName2(), "args": args, "return_value": self.getExceptionResultIndicatorValue(), } def hasSameTypeOperationSpecializationCode(self, other, nb_slot, sq_slot): # Many cases, pylint: disable=too-many-branches,too-many-return-statements cand = self if self is not object_desc else other # Both are objects, nothing to be done. if cand is object_desc: assert self is object_desc assert other is object_desc return False # Special case for sequence concats/repeats. if sq_slot is not None and not cand.hasSlot(nb_slot) and cand.hasSlot(sq_slot): slot = sq_slot else: slot = nb_slot if slot == "sq_repeat": if cand in ( list_desc, tuple_desc, set_desc, dict_desc, unicode_desc, str_desc, bytes_desc, ): # No repeat with themselves. return False if slot == "nb_remainder": if cand in (list_desc, tuple_desc, set_desc, dict_desc): # No remainder with themselves. return False if slot == "nb_multiply": if cand in ( str_desc, bytes_desc, list_desc, tuple_desc, set_desc, dict_desc, ): # No multiply with themselves. return False if slot == "nb_add": # Tuple and list, etc. use sq_concat. # TODO: What about unicode_desc if cand in ( str_desc, bytes_desc, tuple_desc, list_desc, set_desc, dict_desc, ): # No add with themselves. return False if slot in ("nb_and", "nb_or", "nb_xor"): if cand in ( str_desc, bytes_desc, unicode_desc, list_desc, tuple_desc, dict_desc, float_desc, ): return False if slot in ("nb_lshift", "nb_rshift"): if cand in ( str_desc, bytes_desc, unicode_desc, tuple_desc, list_desc, set_desc, dict_desc, float_desc, ): return False if slot == "nb_matrix_multiply": # Nobody has it for anything return False return True def hasSimilarTypeSpecializationCode(self, other): return other in related_types.get(self, ()) def getSameTypeType(self, other): if self is object_desc: return other elif other is object_desc: return self else: return object_desc def isSimilarOrSameTypesAsOneOf(self, *others): for other in others: assert other is not None if self is other or other in related_types.get(self, ()): return True return False def hasTypeSpecializationCode(self, other, nb_slot, sq_slot): if self is object_desc and other is object_desc: return False if self is other: return self.hasSameTypeOperationSpecializationCode( other=other, nb_slot=nb_slot, sq_slot=sq_slot, ) return self.hasSimilarTypeSpecializationCode( other=other, ) def getSameTypeComparisonSpecializationCode( self, other, op_code, target, operand1, operand2 ): cand = self if self is not object_desc else other if cand is object_desc: return "" return "return COMPARE_%s_%s_%s_%s(%s, %s);" % ( op_code, target.getHelperCodeName(), cand.getHelperCodeName(), cand.getHelperCodeName(), operand1, operand2, ) @staticmethod def getTakeReferenceStatement(operand): return "Py_INCREF(%s);" % operand @classmethod def getReturnFromObjectExpressionCode( cls, operand, take_ref=False, check_exception=True ): if check_exception and not (cls.type_name == "object" and not take_ref): r = """if (unlikely(%s == NULL)) { return %s; }\n\n""" % ( operand, cls.getExceptionResultIndicatorValue(), ) else: r = "" return r + cls._getReturnFromObjectExpressionCode( operand=operand, take_ref=take_ref ) @classmethod def getAssignFromObjectExpressionCode(cls, result, operand, take_ref=False): if cls.type_name == "object": if take_ref: return "Py_INCREF(%s); %s = %s;" % (operand, result, operand) else: return "%s = %s;" % (result, operand) else: if take_ref: return """%s = %s; """ % ( result, cls.getToValueFromObjectExpression(operand), ) else: return """%s = %s; Py_DECREF(%s); """ % ( result, cls.getToValueFromObjectExpression(operand), operand, ) @classmethod def _getReturnFromObjectExpressionCode(cls, operand, take_ref): if cls.type_name == "object": if take_ref: return "Py_INCREF(%s); return %s;" % (operand, operand) else: return "return %s;" % operand else: if take_ref: return """{ %s r = %s; return r; }""" % ( cls.getTypeDecl(), cls.getToValueFromObjectExpression(operand), ) else: return """{ %s r = %s; Py_DECREF(%s); return r; }""" % ( cls.getTypeDecl(), cls.getToValueFromObjectExpression(operand), operand, ) @classmethod def getReturnFromLongExpressionCode(cls, operand): if cls.type_name == "object": # TODO: Python3? return "return PyInt_FromLong(%s);" % operand elif cls.type_name == "nbool": return "return %s;" % cls.getToValueFromBoolExpression("%s != 0" % operand) else: assert False, cls @classmethod def getAssignFromLongExpressionCode(cls, result, operand): if cls.type_name == "object": # TODO: Python3? return "%s = PyInt_FromLong(%s);" % (result, operand) elif cls.type_name == "nbool": return "%s = %s;" % ( result, cls.getToValueFromBoolExpression("%s != 0" % operand), ) else: assert False, cls @classmethod def getAssignFromBoolExpressionCode(cls, result, operand, give_ref): if cls.type_name == "object": # TODO: Python3? code = "%s = BOOL_FROM(%s);" % (result, operand) if give_ref: code += "Py_INCREF(%s);" % result return code elif cls.type_name == "nbool": return "%s = %s;" % ( result, cls.getToValueFromBoolExpression("%s" % operand), ) else: assert False, cls @classmethod def getReturnFromFloatExpressionCode(cls, operand): if cls.type_name == "object": return "return PyFloat_FromDouble(%s);" % operand elif cls.type_name == "nbool": return "return %s;" % cls.getToValueFromBoolExpression( "%s == 0.0" % operand ) elif cls.type_name == "float": return "return %s;" % operand else: assert False, cls @classmethod def getAssignFromFloatExpressionCode(cls, result, operand): if cls.type_name in ("object", "int", "float"): return "%s = PyFloat_FromDouble(%s);" % (result, operand) elif cls.type_name == "nbool": return "%s = %s;" % ( result, cls.getToValueFromBoolExpression("%s != 0.0" % operand), ) elif cls.type_name == "float": return "%s = %s;" % (result, operand) else: assert False, cls @classmethod def getReturnFromFloatConstantCode(cls, value): if cls.type_name == "object": const_name = "const_" + nuitka.codegen.Namify.namifyConstant(value) return "Py_INCREF(%(const_name)s); return %(const_name)s;" % { "const_name": const_name } elif cls.type_name in ("nbool", "float"): return cls.getReturnFromFloatExpressionCode(value) else: assert False, cls @classmethod def getAssignFromFloatConstantCode(cls, result, value): if value == "nan": value = float(value) if cls.type_name in ("object", "int"): # TODO: Type checks for value are needed for "int". const_name = "const_" + nuitka.codegen.Namify.namifyConstant(value) return "Py_INCREF(%(const_name)s); %(result)s = %(const_name)s;" % { "result": result, "const_name": const_name, } elif cls.type_name in ("nbool", "float"): if math.isnan(value): value = "Py_NAN" return cls.getAssignFromFloatExpressionCode(result, value) else: assert False, cls @classmethod def getReturnFromIntConstantCode(cls, value): if cls.type_name == "object": const_name = "const_" + nuitka.codegen.Namify.namifyConstant(value) return "Py_INCREF(%(const_name)s); return %(const_name)s;" % { "const_name": const_name } elif cls.type_name in ("nbool", "float"): return cls.getReturnFromLongExpressionCode(value) else: assert False, cls @classmethod def getAssignFromIntConstantCode(cls, result, value): if cls.type_name in ("object", "int"): const_name = "const_" + nuitka.codegen.Namify.namifyConstant(value) return "Py_INCREF(%(const_name)s); %(result)s = %(const_name)s;" % { "result": result, "const_name": const_name, } elif cls.type_name in ("nbool", "float"): return cls.getAssignFromLongExpressionCode(result, value) else: assert False, (cls, cls.type_name) @classmethod def getAssignFromLongConstantCode(cls, result, value): if cls.type_name in ("object", "long"): if str is bytes: # Cannot put "L" in Jinja code for constant value. value = long(value) # The only on we surely know right now. assert value == 0 # TODO: This works for small constants only and only for Python3. const_name2 = "const_" + nuitka.codegen.Namify.namifyConstant(value) const_name3 = ( "Nuitka_Long_SmallValues[NUITKA_TO_SMALL_VALUE_OFFSET(%d)]" % value ) return """\ #if PYTHON_VERSION < 0x300 %(result)s = %(const_name2)s; #else %(result)s = %(const_name3)s; #endif Py_INCREF(%(result)s);""" % { "result": result, "const_name2": const_name2, "const_name3": const_name3, } elif cls.type_name in ("nbool", "float"): return cls.getAssignFromLongExpressionCode(result, value) else: assert False, (cls, cls.type_name) @classmethod def getAssignConversionCode(cls, result, left, value): def _getObjectObject(): code = "%s = %s;" % (result, value) code += cls.getTakeReferenceStatement(result) return code if cls is left: return _getObjectObject() else: if cls.type_name in ("object", "float"): if left.type_name in ("int", "float"): return _getObjectObject() elif left.type_name == "clong": return cls.getAssignFromLongExpressionCode(result, value) else: assert False, left.type_name elif cls.type_name == "nbool": if left.type_name == "int": return "%s = %s;" % ( result, cls.getToValueFromBoolExpression( "%s != 0" % left.getAsLongValueExpression(value) ), ) elif left.type_name == "float": return "%s = %s;" % ( result, cls.getToValueFromBoolExpression( "%s != 0.0" % left.getAsDoubleValueExpression(value) ), ) else: assert False, left.type_name else: assert False, cls.type_name class ConcreteTypeBase(TypeDescBase): type_decl = "PyObject *" def _getSlotValueExpression(self, operand, slot): if slot.startswith("nb_"): return self.getTypeValueExpression(operand)[1:] + ".tp_as_number->" + slot elif slot.startswith("sq_"): return self.getTypeValueExpression(operand)[1:] + ".tp_as_sequence->" + slot elif slot.startswith("tp_"): return self.getTypeValueExpression(operand)[1:] + "." + slot else: assert False, slot def getCheckValueCode(self, operand): return """\ CHECK_OBJECT(%(operand)s); assert(%(type_name)s_CheckExact(%(operand)s));""" % { "operand": operand, "type_name": self.getTypeValueExpression(operand)[1:].split("_")[0], } @abstractmethod def getTypeValueExpression(self, operand): pass @staticmethod def getTakeReferenceStatement(operand): return "" class IntDesc(ConcreteTypeBase): type_name = "int" type_desc = "Python2 'int'" python_requirement = "PYTHON_VERSION < 0x300" @classmethod def getTypeValueExpression(cls, operand): return "&PyInt_Type" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "1" def hasSlot(self, slot): if slot.startswith("nb_inplace"): return False elif slot.startswith("nb_"): return slot != "nb_matrix_multiply" elif slot.startswith("sq_"): return False elif slot == "tp_richcompare": return False elif slot == "tp_compare": return True else: assert False @staticmethod def needsIndexConversion(): return False @staticmethod def getAsLongValueExpression(operand): return "PyInt_AS_LONG(%s)" % operand @staticmethod def getAsObjectValueExpression(operand): return operand @staticmethod def releaseAsObjectValueStatement(operand): # Virtual method, pylint: disable=unused-argument return "" int_desc = IntDesc() class StrDesc(ConcreteTypeBase): type_name = "str" type_desc = "Python2 'str'" python_requirement = "PYTHON_VERSION < 0x300" @classmethod def getTypeValueExpression(cls, operand): return "&PyString_Type" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "1" def hasSlot(self, slot): if slot.startswith("nb_"): return slot == "nb_remainder" elif slot.startswith("sq_"): return "ass" not in slot and "inplace" not in slot elif slot == "tp_richcompare": return True elif slot == "tp_compare": return False else: assert False, (self, slot) str_desc = StrDesc() class UnicodeDesc(ConcreteTypeBase): type_name = "unicode" type_desc = "Python2 'unicode', Python3 'str'" @classmethod def getTypeName3(cls): return "str" @classmethod def getTypeValueExpression(cls, operand): return "&PyUnicode_Type" @classmethod def getCheckValueCode(cls, operand): return """\ CHECK_OBJECT(%(operand)s); assert(PyUnicode_CheckExact(%(operand)s));""" % { "operand": operand } @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "1" def hasSlot(self, slot): if slot.startswith("nb_"): return slot == "nb_remainder" elif slot.startswith("sq_"): return "ass" not in slot and "inplace" not in slot elif slot == "tp_richcompare": return True elif slot == "tp_compare": return True else: assert False, slot unicode_desc = UnicodeDesc() class FloatDesc(ConcreteTypeBase): type_name = "float" type_desc = "Python 'float'" @classmethod def getTypeValueExpression(cls, operand): return "&PyFloat_Type" @staticmethod def getAsDoubleValueExpression(operand): return "PyFloat_AS_DOUBLE(%s)" % operand def hasSlot(self, slot): if slot.startswith("nb_inplace"): return False elif slot.startswith("nb_"): return slot != "nb_matrix_multiply" elif slot.startswith("sq_"): return False elif slot == "tp_richcompare": return True elif slot == "tp_compare": return False else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "1" float_desc = FloatDesc() class TupleDesc(ConcreteTypeBase): type_name = "tuple" type_desc = "Python 'tuple'" @classmethod def getTypeValueExpression(cls, operand): return "&PyTuple_Type" def hasSlot(self, slot): if slot.startswith("nb_"): return False elif slot.startswith("sq_"): return "ass" not in slot and "inplace" not in slot elif slot == "tp_richcompare": return True elif slot == "tp_compare": return False else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" tuple_desc = TupleDesc() class ListDesc(ConcreteTypeBase): type_name = "list" type_desc = "Python 'list'" @classmethod def getTypeValueExpression(cls, operand): return "&PyList_Type" def hasSlot(self, slot): if slot.startswith("nb_"): return False elif slot.startswith("sq_"): return True elif slot == "tp_richcompare": return True elif slot == "tp_compare": return False else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" list_desc = ListDesc() class SetDesc(ConcreteTypeBase): type_name = "set" type_desc = "Python 'set'" @classmethod def getTypeValueExpression(cls, operand): return "&PySet_Type" def hasSlot(self, slot): if slot.startswith("nb_inplace_"): return slot in ( "nb_inplace_subtract", "nb_inplace_and", "nb_inplace_or", "nb_inplace_xor", ) elif slot.startswith("nb_"): return slot in ("nb_subtract", "nb_and", "nb_or", "nb_xor") elif slot.startswith("sq_"): return True else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" set_desc = SetDesc() class DictDesc(ConcreteTypeBase): type_name = "dict" type_desc = "Python 'dict'" @classmethod def getTypeValueExpression(cls, operand): return "&PyDict_Type" def hasSlot(self, slot): if slot.startswith("nb_"): return False elif slot.startswith("sq_"): return True else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" dict_desc = DictDesc() class BytesDesc(ConcreteTypeBase): type_name = "bytes" type_desc = "Python3 'bytes'" python_requirement = "PYTHON_VERSION >= 0x300" @classmethod def getTypeValueExpression(cls, operand): return "&PyBytes_Type" def hasSlot(self, slot): if slot.startswith("nb_"): return slot == "nb_remainder" elif slot.startswith("sq_"): return "ass" not in slot and slot != "sq_slice" and "inplace" not in slot elif slot == "tp_richcompare": return True elif slot == "tp_compare": return False else: assert False, slot @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" bytes_desc = BytesDesc() class LongDesc(ConcreteTypeBase): type_name = "long" type_desc = "Python2 'long', Python3 'int'" @classmethod def getTypeName3(cls): return "int" @classmethod def getTypeValueExpression(cls, operand): return "&PyLong_Type" def hasSlot(self, slot): if slot.startswith("nb_inplace_"): return False elif slot.startswith("nb_"): return slot != "nb_matrix_multiply" elif slot.startswith("sq_"): return False elif slot == "tp_richcompare": assert False # For Python3 it's there though return False elif slot == "tp_compare": # For Python2 it's tp_compare though return True else: assert False, slot def getSlotValueExpression(self, operand, slot): # Python2 long does have "tp_compare", Python3 does have "tp_richcompare", # therefore create code that makes this a conditional expression on the # Python version if slot == "tp_richcompare": return "(PYTHON_VERSION < 0x300 ? NULL : RICHCOMPARE(%s))" % operand return ConcreteTypeBase.getSlotValueExpression(self, operand=operand, slot=slot) @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "1" @staticmethod def needsIndexConversion(): return False long_desc = LongDesc() class ObjectDesc(TypeDescBase): type_name = "object" type_desc = "any Python object" type_decl = "PyObject *" def hasSlot(self, slot): # Don't want to get asked, we cannot know. assert False def getIndexCheckExpression(self, operand): return "PyIndex_Check(%s)" % operand def getNewStyleNumberTypeCheckExpression(self, operand): return "NEW_STYLE_NUMBER_TYPE(%s)" % operand def getSlotValueExpression(self, operand, slot): # Always check. return self._getSlotValueExpression(operand, slot) def getSlotValueCheckExpression(self, operand, slot): return "(%s) != NULL" % self._getSlotValueExpression(operand, slot) @staticmethod def getToValueFromBoolExpression(operand): return "BOOL_FROM(%s)" % operand @staticmethod def getToValueFromObjectExpression(operand): return operand @staticmethod def getExceptionResultIndicatorValue(): return "NULL" object_desc = ObjectDesc() class CLongDesc(TypeDescBase): type_name = "clong" type_desc = "C platform long value" type_decl = "long" @classmethod def getCheckValueCode(cls, operand): return "" @classmethod def getTypeValueExpression(cls, operand): return "NULL" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" def hasSlot(self, slot): return False @staticmethod def getAsLongValueExpression(operand): return operand @staticmethod def getAsObjectValueExpression(operand): return "PyLong_FromLong(%s)" % operand @staticmethod def releaseAsObjectValueStatement(operand): return "Py_DECREF(%s);" % operand clong_desc = CLongDesc() class CBoolDesc(TypeDescBase): type_name = "cbool" type_desc = "C platform bool value" type_decl = "bool" @classmethod def getCheckValueCode(cls, operand): return "" @classmethod def getTypeValueExpression(cls, operand): return "NULL" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" def hasSlot(self, slot): return False @staticmethod def getAsLongValueExpression(operand): return operand @staticmethod def getAsObjectValueExpression(operand): return "BOOL_FROM(%s)" % operand @staticmethod def getToValueFromBoolExpression(operand): return operand @staticmethod def getToValueFromObjectExpression(operand): return "CHECK_IF_TRUE(%s) == 1" % operand @staticmethod def getTakeReferenceStatement(operand): return "" @staticmethod def getExceptionResultIndicatorValue(): return "false" cbool_desc = CBoolDesc() class NBoolDesc(TypeDescBase): type_name = "nbool" type_desc = "Nuitka C bool value" type_decl = "nuitka_bool" @classmethod def getCheckValueCode(cls, operand): return "" @classmethod def getTypeValueExpression(cls, operand): return "NULL" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" def hasSlot(self, slot): return False @staticmethod def getAsLongValueExpression(operand): return operand @staticmethod def getAsObjectValueExpression(operand): return "BOOL_FROM(%s)" % operand @staticmethod def getToValueFromBoolExpression(operand): return "%s ? NUITKA_BOOL_TRUE : NUITKA_BOOL_FALSE" % operand @classmethod def getToValueFromObjectExpression(cls, operand): return cls.getToValueFromBoolExpression("CHECK_IF_TRUE(%s)" % operand) @staticmethod def getTakeReferenceStatement(operand): return "" @staticmethod def getExceptionResultIndicatorValue(): return "NUITKA_BOOL_EXCEPTION" nbool_desc = NBoolDesc() class NVoidDesc(TypeDescBase): type_name = "nvoid" type_desc = "Nuitka C void value" type_decl = "nuitka_void" @classmethod def getCheckValueCode(cls, operand): return "" @classmethod def getTypeValueExpression(cls, operand): return "NULL" @classmethod def getNewStyleNumberTypeCheckExpression(cls, operand): return "0" def hasSlot(self, slot): return False @staticmethod def getAsLongValueExpression(operand): assert False return operand @staticmethod def getAsObjectValueExpression(operand): assert False return "BOOL_FROM(%s)" % operand @staticmethod def getToValueFromBoolExpression(operand): # All values are the same, pylint: disable=unused-argument return "NUITKA_VOID_OK" @classmethod def getToValueFromObjectExpression(cls, operand): # All values are the same, pylint: disable=unused-argument return "NUITKA_VOID_OK" @staticmethod def getTakeReferenceStatement(operand): return "" @staticmethod def getExceptionResultIndicatorValue(): return "NUITKA_VOID_EXCEPTION" nvoid_desc = NVoidDesc() related_types = {clong_desc: (int_desc,), int_desc: (clong_desc,)} class AlternativeTypeBase(object): # TODO: Base class for alternative types pass class AlternativeIntOrClong(AlternativeTypeBase): # TODO: Base class for alternative type int or clong. pass types = ( int_desc, str_desc, unicode_desc, float_desc, tuple_desc, list_desc, set_desc, dict_desc, bytes_desc, long_desc, clong_desc, cbool_desc, nbool_desc, object_desc, ) def findTypeFromCodeName(code_name): for candidate in types: if candidate.getHelperCodeName() == code_name: return candidate op_slot_codes = set() # Reverse operation mapping. reversed_args_compare_op_codes = { "LE": "GE", "LT": "GT", "EQ": "EQ", "NE": "NE", "GT": "LT", "GE": "LE", } def makeCompareSlotCode(operator, op_code, target, left, right, emit): key = operator, op_code, target, left, right if key in op_slot_codes: return if left in (int_desc, clong_desc): template = getDoExtensionUsingTemplateC("HelperOperationComparisonInt.c.j2") elif left == long_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonLong.c.j2") elif left == float_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonFloat.c.j2") elif left == tuple_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonTuple.c.j2") elif left == list_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonList.c.j2") # elif left == set_desc: # template = env.get_template("HelperOperationComparisonSet.c.j2") elif left == bytes_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonBytes.c.j2") elif left == str_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonStr.c.j2") elif left == unicode_desc: template = getDoExtensionUsingTemplateC("HelperOperationComparisonUnicode.c.j2") else: return code = template.render( operand=operator, # TODO: rename target=target, left=left, right=right, op_code=op_code, reversed_args_op_code=reversed_args_compare_op_codes[op_code], name=template.name, ) emit(code) op_slot_codes.add(key) mul_repeats = set() def makeMulRepeatCode(target, left, right, emit): key = right, left if key in mul_repeats: return template = getDoExtensionUsingTemplateC("HelperOperationMulRepeatSlot.c.j2") code = template.render(target=target, left=left, right=right) emit(code) mul_repeats.add(key) def _getNbSlotFromOperand(operand, op_code): # pylint: disable=too-many-branches,too-many-return-statements if operand == "+": return "nb_add" elif operand == "*": return "nb_multiply" elif operand == "-": return "nb_subtract" elif operand == "//": return "nb_floor_divide" elif operand == "/": if op_code == "TRUEDIV": return "nb_true_divide" else: return "nb_divide" elif operand == "%": return "nb_remainder" elif operand == "**": return "nb_power" elif operand == "<<": return "nb_lshift" elif operand == ">>": return "nb_rshift" elif operand == "|": return "nb_or" elif operand == "&": return "nb_and" elif operand == "^": return "nb_xor" elif operand == "@": return "nb_matrix_multiply" elif operand == "divmod": return "nb_divmod" else: assert False, operand def _getNbInplaceSlotFromOperand(operand, op_code): if operand == "divmod": return None nb_slot = _getNbSlotFromOperand(operand, op_code) return nb_slot.replace("nb_", "nb_inplace_") def _parseTypesFromHelper(helper_name): ( target_code, left_code, right_code, ) = nuitka.codegen.HelperDefinitions.parseTypesFromHelper(helper_name) if target_code is not None: target = findTypeFromCodeName(target_code) else: target = None left = findTypeFromCodeName(left_code) right = findTypeFromCodeName(right_code) return target_code, target, left, right def _parseRequirements(op_code, target, left, right, emit): python_requirement = set() # There is an obsolete Python2 operation too, making sure it's guarded in code. if op_code == "OLDDIV": python_requirement.add(int_desc.python_requirement) if op_code == "MATMULT": python_requirement.add("PYTHON_VERSION >= 0x350") if target is not None and target.python_requirement: python_requirement.add(target.python_requirement) if left.python_requirement: python_requirement.add(left.python_requirement) if right.python_requirement: python_requirement.add(right.python_requirement) if python_requirement: assert len(python_requirement) == 1, (target, left, right) python_requirement = python_requirement.pop() emit("#if %s" % python_requirement) return python_requirement def makeHelperOperations( template, inplace, helpers_set, operator, op_code, emit_h, emit_c, emit ): # Complexity comes natural, pylint: disable=too-many-locals emit( '/* C helpers for type %s "%s" (%s) operations */' % ("in-place" if inplace else "specialized", operator, op_code) ) emit() for helper_name in helpers_set: assert helper_name.split("_")[:3] == ["BINARY", "OPERATION", op_code], ( op_code, helper_name, ) target_code, target, left, right = _parseTypesFromHelper(helper_name) assert target is None or not inplace if target is None and not inplace: if target_code == "NILONG": continue assert False, target_code python_requirement = _parseRequirements(op_code, target, left, right, emit) emit( '/* Code referring to "%s" corresponds to %s and "%s" to %s. */' % ( left.getHelperCodeName(), left.type_desc, right.getHelperCodeName(), right.type_desc, ) ) if operator == "+": sq_slot = "sq_concat" elif operator == "*": sq_slot = "sq_repeat" else: sq_slot = None if inplace and sq_slot is not None: sq_islot = sq_slot.replace("sq_", "sq_inplace_") else: sq_islot = None code = template.render( target=target, left=left, right=right, op_code=op_code, operator=operator, nb_slot=_getNbSlotFromOperand(operator, op_code), nb_islot=_getNbInplaceSlotFromOperand(operator, op_code) if inplace else None, sq_slot=sq_slot, sq_islot=sq_islot, object_desc=object_desc, int_desc=int_desc, long_desc=long_desc, float_desc=float_desc, list_desc=list_desc, tuple_desc=tuple_desc, set_desc=set_desc, str_desc=str_desc, unicode_desc=unicode_desc, bytes_desc=bytes_desc, ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) if python_requirement: emit("#endif") emit() def makeHelperComparisons( template, helpers_set, operator, op_code, emit_h, emit_c, emit ): # Details to look for, pylint: disable=too-many-locals emit( '/* C helpers for type specialized "%s" (%s) comparisons */' % (operator, op_code) ) emit() for target in (object_desc, cbool_desc, nbool_desc): python_requirement = _parseRequirements( op_code, target, int_desc, int_desc, emit_c ) makeCompareSlotCode(operator, op_code, target, int_desc, int_desc, emit_c) if python_requirement: emit_c("#endif") for helper_name in helpers_set: assert helper_name.split("_")[:3] == ["RICH", "COMPARE", "xx"], (helper_name,) target_code, target, left, right = _parseTypesFromHelper(helper_name) if target is None: if target_code == "NILONG": continue assert False, target_code python_requirement = _parseRequirements(op_code, target, left, right, emit) code = left.getSameTypeComparisonSpecializationCode( right, op_code, target, "operand1", "operand2" ) if code: cand = left if left is not object_desc else right makeCompareSlotCode(operator, op_code, target, cand, cand, emit_c) emit( '/* Code referring to "%s" corresponds to %s and "%s" to %s. */' % ( left.getHelperCodeName(), left.type_desc, right.getHelperCodeName(), right.type_desc, ) ) if not python_requirement: is_py3_only = False is_py2_only = False elif python_requirement == "PYTHON_VERSION < 0x300": is_py3_only = False is_py2_only = True elif python_requirement == "PYTHON_VERSION >= 0x300": is_py3_only = True is_py2_only = False else: assert False, python_requirement code = template.render( target=target, left=left, right=right, op_code=op_code, reversed_args_op_code=reversed_args_compare_op_codes[op_code], operator=operator, is_py3_only=is_py3_only, is_py2_only=is_py2_only, ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) if python_requirement: emit("#endif") emit() def emitGenerationWarning(emit, template_name): emit( "/* WARNING, this code is GENERATED. Modify the template %s instead! */" % template_name ) def emitIDE(emit): emit( """ /* This file is included from another C file, help IDEs to still parse it on its own. */ #ifdef __IDE_ONLY__ #include "nuitka/prelude.h" #endif """ ) def makeHelpersComparisonOperation(operand, op_code): specialized_cmp_helpers_set = getattr( nuitka.codegen.ComparisonCodes, "specialized_cmp_helpers_set" ) template = getDoExtensionUsingTemplateC("HelperOperationComparison.c.j2") filename_c = "nuitka/build/static_src/HelpersComparison%s.c" % op_code.capitalize() filename_h = "nuitka/build/include/nuitka/helper/comparisons_%s.h" % op_code.lower() with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) emitGenerationWarning(emit, template.name) emitIDE(emit) filename_utils = filename_c[:-2] + "Utils.c" if os.path.exists(filename_utils): emit_c('#include "%s"' % os.path.basename(filename_utils)) makeHelperComparisons( template, specialized_cmp_helpers_set, operand, op_code, emit_h, emit_c, emit, ) def makeHelpersBinaryOperation(operand, op_code): specialized_op_helpers_set = getattr( nuitka.codegen.HelperDefinitions, "specialized_%s_helpers_set" % op_code.lower() ) template = getDoExtensionUsingTemplateC("HelperOperationBinary.c.j2") filename_c = ( "nuitka/build/static_src/HelpersOperationBinary%s.c" % op_code.capitalize() ) filename_h = ( "nuitka/build/include/nuitka/helper/operations_binary_%s.h" % op_code.lower() ) with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) emitGenerationWarning(emit, template.name) emitIDE(emit) filename_utils = filename_c[:-2] + "Utils.c" if os.path.exists(filename_utils): emit_c('#include "%s"' % os.path.basename(filename_utils)) makeHelperOperations( template, False, specialized_op_helpers_set, operand, op_code, emit_h, emit_c, emit, ) def makeHelpersInplaceOperation(operand, op_code): specialized_op_helpers_set = getattr( nuitka.codegen.HelperDefinitions, "specialized_i%s_helpers_set" % op_code.lower(), ) template = getDoExtensionUsingTemplateC("HelperOperationInplace.c.j2") filename_c = ( "nuitka/build/static_src/HelpersOperationInplace%s.c" % op_code.capitalize() ) filename_h = ( "nuitka/build/include/nuitka/helper/operations_inplace_%s.h" % op_code.lower() ) with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) emitGenerationWarning(emit, template.name) emitIDE(emit) filename_utils = filename_c[:-2] + "Utils.c" if os.path.exists(filename_utils): emit_c('#include "%s"' % os.path.basename(filename_utils)) makeHelperOperations( template, True, specialized_op_helpers_set, operand, op_code, emit_h, emit_c, emit, ) def makeHelpersImportHard(): filename_c = "nuitka/build/static_src/HelpersImportHard.c" filename_h = "nuitka/build/include/nuitka/helper/import_hard.h" template = getDoExtensionUsingTemplateC("HelperImportHard.c.j2") with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) emitGenerationWarning(emit, template.name) emitIDE(emit) for module_name in sorted(hard_modules): makeHelperImportModuleHard( template, module_name, emit_h, emit_c, emit, ) def makeHelperImportModuleHard(template, module_name, emit_h, emit_c, emit): emit('/* C helper for hard import of module "%s" import. */' % module_name) emit() if module_name == "_frozen_importlib": python_requirement = "PYTHON_VERSION >= 0x300" elif module_name == "_frozen_importlib_external": python_requirement = "PYTHON_VERSION >= 0x350" else: python_requirement = None if python_requirement: emit("#if %s" % python_requirement) code = template.render( module_name=module_name, name=template.name, target=object_desc ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) if python_requirement: emit("#endif") def makeHelperCalls(): filename_c = "nuitka/build/static_src/HelpersCalling2.c" filename_h = "nuitka/build/include/nuitka/helper/calling2.h" with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): assert args[0] != "extern " writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) template = getTemplateC( "nuitka.codegen", "CodeTemplateCallsPositional.c.j2" ) emitGenerationWarning(emit, template.name) emitIDE(emit) for args_count in range(max_quick_call + 1): code = getQuickCallCode(args_count=args_count, has_tuple_arg=False) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) if args_count >= 1: code = getQuickCallCode(args_count=args_count, has_tuple_arg=True) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) template = getTemplateC("nuitka.codegen", "CodeTemplateCallsMixed.c.j2") # Only keywords, but not positional arguments, via split args. code = getQuickMixedCallCode( args_count=0, has_tuple_arg=False, has_dict_values=True, ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) for args_count in range(1, max_quick_call + 1): for has_tuple_arg in (False, True): for has_dict_values in (False, True): # We do not do that. if not has_dict_values and has_tuple_arg: continue code = getQuickMixedCallCode( args_count=args_count, has_tuple_arg=has_tuple_arg, has_dict_values=has_dict_values, ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) for args_count in range(1, 5): code = getQuickMethodDescrCallCode(args_count=args_count) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) for args_count in range(max_quick_call + 1): code = getQuickMethodCallCode(args_count=args_count) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) def _makeHelperBuiltinTypeAttributes( type_prefix, type_name, python2_methods, python3_methods, emit_c, ): def getVarName(method_name): return "%s_builtin_%s" % (type_prefix, method_name) for method_name in sorted(set(python2_methods + python3_methods)): if method_name in python2_methods and method_name not in python3_methods: emit_c("#if PYTHON_VERSION < 0x300") needs_endif = True elif method_name not in python2_methods and method_name in python3_methods: emit_c("#if PYTHON_VERSION >= 0x300") needs_endif = True else: needs_endif = False emit_c("static PyObject *%s = NULL;" % getVarName(method_name)) if needs_endif: emit_c("#endif") if not python3_methods: emit_c("#if PYTHON_VERSION < 0x300") emit_c("static void _init%sBuiltinMethods() {" % type_prefix.capitalize()) for method_name in sorted(set(python2_methods + python3_methods)): if method_name in python2_methods and method_name not in python3_methods: emit_c("#if PYTHON_VERSION < 0x300") needs_endif = True elif method_name not in python2_methods and method_name in python3_methods: emit_c("#if PYTHON_VERSION >= 0x300") needs_endif = True else: needs_endif = False emit_c( '%s = PyObject_GetAttrString((PyObject *)&%s, "%s");' % (getVarName(method_name), type_name, method_name) ) if needs_endif: emit_c("#endif") emit_c("}") if not python3_methods: emit_c("#endif") generate_builtin_type_operations = [ # TODO: For these, we would need an implementation for adding/deleting dictionary values. That # has turned out to be too hard so far and these are very good friends, not doing hashing # multiple times when reading and writing, so can't do it unless we add something for the # Nuitka-Python eventually. ( "tshape_dict", dict_desc, nuitka.specs.BuiltinDictOperationSpecs, ("pop", "setdefault"), ), # TODO: These are very complex things using stringlib in Python, that we do not have easy access to, # but we might one day for Nuitka-Python expose it for the static linking of it and then we # could in fact call these directly. ( "tshape_str", str_desc, nuitka.specs.BuiltinStrOperationSpecs, ( "strip", "rstrip", "lstrip", "partition", "rpartition", "find", "rfind", "index", "rindex", "capitalize", "upper", "lower", "swapcase", "title", "isalnum", "isalpha", "isdigit", "islower", "isupper", "isspace", "istitle", "split", "rsplit", "startswith", "endswith", "replace", "encode", "decode", ), ), # TODO: This is using Python2 spec module for Python3 strings, that will be a problem down the # road, when version specifics come in. ( "tshape_unicode", unicode_desc, nuitka.specs.BuiltinUnicodeOperationSpecs, ( "strip", "rstrip", "lstrip", "find", "rfind", "index", "rindex", "capitalize", "upper", "lower", "swapcase", "title", "isalnum", "isalpha", "isdigit", "islower", "isupper", "isspace", "istitle", "split", "rsplit", "startswith", "endswith", "replace", "encode", ), ), ] def makeHelperBuiltinTypeMethods(): # Many details, pylint: disable=too-many-locals filename_c = "nuitka/build/static_src/HelpersBuiltinTypeMethods.c" filename_h = "nuitka/build/include/nuitka/helper/operations_builtin_types.h" with withFileOpenedAndAutoformatted(filename_c) as output_c: with withFileOpenedAndAutoformatted(filename_h) as output_h: def emit_h(*args): writeline(output_h, *args) def emit_c(*args): writeline(output_c, *args) def emit(*args): emit_h(*args) emit_c(*args) emitIDE(emit) _makeHelperBuiltinTypeAttributes( "str", "PyString_Type", python2_str_methods, (), emit_c, ) _makeHelperBuiltinTypeAttributes( "unicode", "PyUnicode_Type", python2_unicode_methods, python3_str_methods, emit_c, ) _makeHelperBuiltinTypeAttributes( "dict", "PyDict_Type", python2_dict_methods, python3_dict_methods, emit_c, ) template = getDoExtensionUsingTemplateC("HelperBuiltinMethodOperation.c.j2") for ( shape_name, type_desc, spec_module, method_names, ) in generate_builtin_type_operations: if type_desc.python_requirement: emit("#if %s" % type_desc.python_requirement) for method_name in sorted(method_names): ( present, arg_names, arg_name_mapping, arg_counts, ) = getMethodVariations( spec_module=spec_module, shape_name=shape_name, method_name=method_name, must_exist=True, ) assert present, method_name def formatArgumentDeclaration(arg_types, arg_names, starting): return formatArgs( [ arg_type.getVariableDecl(arg_name) for arg_type, arg_name in zip(arg_types, arg_names) ], starting=starting, ) # Function is used immediately in same loop, pylint: disable=cell-var-from-loop def replaceArgNameForC(arg_name): if arg_name in arg_name_mapping: arg_name = arg_name_mapping[arg_name] if arg_name in ("default", "new"): return arg_name + "_value" else: return arg_name for arg_count in arg_counts: variant_args = [ replaceArgNameForC(arg_name) for arg_name in arg_names[:arg_count] ] code = template.render( object_desc=object_desc, builtin_type=type_desc, builtin_arg_name=type_desc.type_name, method_name=method_name, api_suffix=str(arg_count + 1) if len(arg_counts) > 1 else "", arg_names=variant_args, arg_types=[object_desc] * len(variant_args), formatArgumentDeclaration=formatArgumentDeclaration, zip=zip, len=len, name=template.name, ) emit_c(code) emit_h(getTemplateCodeDeclaredFunction(code)) if type_desc.python_requirement: emit("#endif") def main(): # Cover many things once first, then cover all for quicker turnaround during development. makeHelperBuiltinTypeMethods() makeHelpersComparisonOperation("==", "EQ") makeHelpersBinaryOperation("+", "ADD") makeHelpersInplaceOperation("+", "ADD") makeHelpersImportHard() makeHelperCalls() makeHelpersBinaryOperation("-", "SUB") makeHelpersBinaryOperation("*", "MULT") makeHelpersBinaryOperation("%", "MOD") makeHelpersBinaryOperation("|", "BITOR") makeHelpersBinaryOperation("&", "BITAND") makeHelpersBinaryOperation("^", "BITXOR") makeHelpersBinaryOperation("<<", "LSHIFT") makeHelpersBinaryOperation(">>", "RSHIFT") makeHelpersBinaryOperation("//", "FLOORDIV") makeHelpersBinaryOperation("/", "TRUEDIV") makeHelpersBinaryOperation("/", "OLDDIV") makeHelpersBinaryOperation("divmod", "DIVMOD") makeHelpersBinaryOperation("**", "POW") makeHelpersBinaryOperation("@", "MATMULT") makeHelpersInplaceOperation("-", "SUB") makeHelpersInplaceOperation("*", "MULT") makeHelpersInplaceOperation("%", "MOD") makeHelpersInplaceOperation("|", "BITOR") makeHelpersInplaceOperation("&", "BITAND") makeHelpersInplaceOperation("^", "BITXOR") makeHelpersInplaceOperation("<<", "LSHIFT") makeHelpersInplaceOperation(">>", "RSHIFT") makeHelpersInplaceOperation("//", "FLOORDIV") makeHelpersInplaceOperation("/", "TRUEDIV") makeHelpersInplaceOperation("/", "OLDDIV") makeHelpersInplaceOperation("**", "POW") makeHelpersInplaceOperation("@", "MATMULT") makeHelpersComparisonOperation("!=", "NE") makeHelpersComparisonOperation("<=", "LE") makeHelpersComparisonOperation(">=", "GE") makeHelpersComparisonOperation(">", "GT") makeHelpersComparisonOperation("<", "LT") Nuitka-0.6.19.1/nuitka/tools/specialize/SpecializePython.py0000600000372100037210000001460614166627112030725 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ This tool is generating node variants from Jinja templates. """ import nuitka.Options nuitka.Options.is_fullcompat = False # isort:start import nuitka.codegen.ComparisonCodes import nuitka.codegen.HelperDefinitions import nuitka.codegen.Namify import nuitka.specs.BuiltinDictOperationSpecs import nuitka.specs.BuiltinStrOperationSpecs from nuitka.utils.Jinja2 import getTemplate from .Common import ( formatArgs, getMethodVariations, python2_dict_methods, python2_str_methods, python3_dict_methods, python3_str_methods, withFileOpenedAndAutoformatted, writeline, ) # This defines which attribute nodes are to specialize and how # to do that. attribute_information = {} # Which ones have operations implemented. attribute_shape_operations = {} # Version specific tests for attributes. attribute_shape_versions = {} # Argument count specific operation nodes if used. attribute_shape_variations = {} # Arguments names differences in spec vs. node attribute_shape_node_arg_mapping = {} # Argument names of an operation. attribute_shape_args = {} def processTypeShapeAttribute( shape_name, spec_module, python2_methods, python3_methods ): for method_name in python2_methods: attribute_information.setdefault(method_name, set()).add(shape_name) key = method_name, shape_name if method_name not in python3_methods: attribute_shape_versions[key] = "str is bytes" present, arg_names, arg_name_mapping, arg_counts = getMethodVariations( spec_module=spec_module, shape_name=shape_name, method_name=method_name ) attribute_shape_operations[key] = present if present: attribute_shape_args[key] = arg_names if len(arg_counts) > 1: attribute_shape_variations[key] = arg_counts attribute_shape_node_arg_mapping[key] = arg_name_mapping for method_name in python3_methods: attribute_information.setdefault(method_name, set()).add(shape_name) key = method_name, shape_name if method_name not in python2_methods: attribute_shape_versions[key] = "str is not bytes" present, arg_names, arg_name_mapping, arg_counts = getMethodVariations( spec_module=spec_module, shape_name=shape_name, method_name=method_name ) attribute_shape_operations[key] = present if present: attribute_shape_args[key] = arg_names if len(arg_counts) > 1: attribute_shape_variations[key] = arg_counts attribute_shape_node_arg_mapping[key] = arg_name_mapping processTypeShapeAttribute( "tshape_dict", nuitka.specs.BuiltinDictOperationSpecs, python2_dict_methods, python3_dict_methods, ) processTypeShapeAttribute( "tshape_str", nuitka.specs.BuiltinStrOperationSpecs, python2_str_methods, python3_str_methods, ) def emitGenerationWarning(emit, template_name): emit( '''"""Specialized attribute nodes WARNING, this code is GENERATED. Modify the template %s instead! """ ''' % template_name ) def formatCallArgs(operation_node_arg_mapping, args, starting=True): def mapName(arg): if not operation_node_arg_mapping: return arg else: return operation_node_arg_mapping.get(arg, arg) if args is None: result = "" else: result = ",".join("%s=%s" % (mapName(arg), arg) for arg in args) if not starting and result: result = "," + result # print("args", args, "->", result) return result def makeAttributeNodes(): filename_python = "nuitka/nodes/AttributeNodesGenerated.py" template = getTemplate( package_name=__package__, template_subdir="templates_python", template_name="AttributeNodeFixed.py.j2", ) with withFileOpenedAndAutoformatted(filename_python) as output_python: def emit(*args): writeline(output_python, *args) emitGenerationWarning(emit, template.name) emit("from .AttributeLookupNodes import ExpressionAttributeLookupFixedBase") emit("from nuitka.specs.BuiltinParameterSpecs import extractBuiltinArgs") # TODO: Maybe generate its effect instead of using a base class. emit("from .NodeBases import SideEffectsFromChildrenMixin") emit("attribute_classes = {}") emit("attribute_typed_classes = set()") for attribute_name, shape_names in sorted(attribute_information.items()): # Some attributes lead to different operations for Python3. if attribute_name == "items": python3_operation_name = "iteritems" elif attribute_name == "keys": python3_operation_name = "iterkeys" elif attribute_name == "values": python3_operation_name = "itervalues" else: python3_operation_name = None code = template.render( attribute_name=attribute_name, python3_operation_name=python3_operation_name, shape_names=shape_names, attribute_shape_versions=attribute_shape_versions, attribute_shape_operations=attribute_shape_operations, attribute_shape_variations=attribute_shape_variations, attribute_shape_node_arg_mapping=attribute_shape_node_arg_mapping, attribute_shape_args=attribute_shape_args, formatArgs=formatArgs, formatCallArgs=formatCallArgs, reversed=reversed, name=template.name, ) emit(code) def main(): makeAttributeNodes() Nuitka-0.6.19.1/nuitka/tools/specialize/__init__.py0000600000372100037210000000150114166627112027160 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/specialize/Common.py0000600000372100037210000001515714166627112026665 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Common helper functions for specializing code.""" from nuitka.tools.quality.autoformat.Autoformat import ( # For import from here, pylint: disable=unused-import withFileOpenedAndAutoformatted, ) def writeline(output, *args): if not args: output.write("\n") elif len(args) == 1: output.write(args[0] + "\n") else: assert False, args # Python2 dict methods: python2_dict_methods = ( "clear", # has full dict coverage "copy", # has full dict coverage "fromkeys", "get", # has full dict coverage "has_key", # has full dict coverage "items", # has full dict coverage "iteritems", # has full dict coverage "iterkeys", # has full dict coverage "itervalues", # has full dict coverage "keys", # has full dict coverage "pop", # has full dict coverage "popitem", # has full dict coverage "setdefault", # has full dict coverage "update", # has full dict coverage "values", # has full dict coverage "viewitems", # has full dict coverage "viewkeys", # has full dict coverage "viewvalues", # has full dict coverage ) python3_dict_methods = ( # see Python2 methods, these are only less "clear", "copy", "fromkeys", "get", "items", "keys", "pop", "popitem", "setdefault", "update", "values", ) python2_str_methods = ( "capitalize", # has full str coverage "center", "count", "decode", "encode", "endswith", # has full str coverage "expandtabs", "find", # has full str coverage "format", "index", # has full str coverage "isalnum", # has full str coverage "isalpha", # has full str coverage "isdigit", # has full str coverage "islower", # has full str coverage "isspace", # has full str coverage "istitle", # has full str coverage "isupper", # has full str coverage "join", # has full str coverage "ljust", "lower", # has full str coverage "lstrip", # has full str coverage "partition", # has full str coverage "replace", "rfind", # has full str coverage "rindex", # has full str coverage "rjust", "rpartition", # has full str coverage "rsplit", # has full str coverage "rstrip", # has full str coverage "split", # has full str coverage "splitlines", "startswith", # has full str coverage "strip", # has full str coverage "swapcase", # has full str coverage "title", # has full str coverage "translate", "upper", # has full str coverage "zfill", ) python3_str_methods = ( "capitalize", "casefold", "center", "count", "encode", "endswith", "expandtabs", "find", "format", "format_map", "index", "isalnum", "isalpha", "isascii", "isdecimal", "isdigit", "isidentifier", "islower", "isnumeric", "isprintable", "isspace", "istitle", "isupper", "join", "ljust", "lower", "lstrip", "maketrans", "partition", # TODO: Python3.9 or higher: # "removeprefix", # "removesuffix", "replace", "rfind", "rindex", "rjust", "rpartition", "rsplit", "rstrip", "split", "splitlines", "startswith", "strip", "swapcase", "title", "translate", "upper", "zfill", ) python2_unicode_methods = ( "capitalize", "center", "count", "decode", "encode", "endswith", "expandtabs", "find", "format", "index", "isalnum", "isalpha", "isdecimal", "isdigit", "islower", "isnumeric", "isspace", "istitle", "isupper", "join", "ljust", "lower", "lstrip", "partition", "replace", "rfind", "rindex", "rjust", "rpartition", "rsplit", "rstrip", "split", "splitlines", "startswith", "strip", "swapcase", "title", "translate", "upper", "zfill", ) def getMethodVariations(spec_module, shape_name, method_name, must_exist=False): spec_name = shape_name.split("_")[-1] + "_" + method_name + "_spec" spec = getattr(spec_module, spec_name, None) present = spec is not None if not present and must_exist: assert False, spec_name if present: if spec.isStarListSingleArg(): required = 1 arg_counts = tuple(range(required, required + 2)) arg_names = ( spec.getStarListArgumentName(), spec.getStarDictArgumentName(), ) arg_name_mapping = { "list_args": "iterable", "kw_args": "pairs", } else: required = spec.getArgumentCount() - spec.getDefaultCount() arg_counts = tuple(range(required, spec.getArgumentCount() + 1)) arg_names = spec.getArgumentNames() arg_name_mapping = {} else: arg_names = arg_name_mapping = arg_counts = None return present, arg_names, arg_name_mapping, arg_counts def formatArgs(args, starting=True, finishing=True): result = [] if args: if not starting: result.append(",") for arg in args: result.append(arg) if arg is not args[-1] or not finishing: result.append(",") return "".join(result) def check(): if str is bytes: for method_name in python2_str_methods: assert hasattr("", method_name), method_name for method_name in python2_unicode_methods: assert hasattr(u"", method_name), method_name for method_name in python2_dict_methods: assert hasattr({}, method_name), method_name else: for method_name in python3_str_methods: assert hasattr("", method_name), method_name for method_name in python3_dict_methods: assert hasattr({}, method_name), method_name check() Nuitka-0.6.19.1/nuitka/tools/testing/0000700000372100037210000000000014167275622024403 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/compare_with_cpython/0000700000372100037210000000000014167275622030630 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/compare_with_cpython/__main__.py0000700000372100037210000007053714166627112032733 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tool to compare output of CPython and Nuitka. """ import hashlib import os import pickle import re import subprocess import sys import time from nuitka.PythonVersions import python_version from nuitka.tools.testing.Common import ( addToPythonPath, executeAfterTimePassed, getTempDir, getTestingCPythonOutputsCacheDir, killProcess, withPythonPathChange, ) from nuitka.tools.testing.OutputComparison import compareOutput from nuitka.Tracing import my_print from nuitka.utils.Execution import ( check_output, executeProcess, wrapCommandForDebuggerForSubprocess, ) from nuitka.utils.Importing import getSharedLibrarySuffix from nuitka.utils.Timing import StopWatch def displayOutput(stdout, stderr): if type(stdout) is not str: stdout = stdout.decode("utf-8" if os.name != "nt" else "cp850") stderr = stderr.decode("utf-8" if os.name != "nt" else "cp850") my_print(stdout, end=" ") if stderr: my_print(stderr) def checkNoPermissionError(output): # Forms of permission errors. for candidate in ( b"Permission denied:", b"PermissionError:", b"DBPermissionsError:", ): if candidate in output: return False # These are localized it seems. if re.search( b"(WindowsError|FileNotFoundError|FileExistsError|WinError 145):" b".*(@test|totest|xx|Error 145)", output, ): return False # Give those a retry as well. if b"clcache.__main__.CacheLockException" in output: return False return True def _getCPythonResults(cpython_cmd, send_kill): stop_watch = StopWatch() # Try a coupile of times for permission denied, on Windows it can # be transient. for _i in range(5): stop_watch.start() with withPythonPathChange(os.getcwd()): # want fine grained control, pylint: disable=consider-using-with process = subprocess.Popen( args=cpython_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) if send_kill: # Doing it per loop iteration hopefully, pylint: disable=cell-var-from-loop executeAfterTimePassed( 1.0, lambda: killProcess("Uncompiled Python program", process.pid) ) stdout_cpython, stderr_cpython = process.communicate() exit_cpython = process.returncode stop_watch.stop() if checkNoPermissionError(stdout_cpython) and checkNoPermissionError( stderr_cpython ): break my_print("Retrying CPython due to permission problems after delay.") time.sleep(2) cpython_time = stop_watch.getDelta() return cpython_time, stdout_cpython, stderr_cpython, exit_cpython def getCPythonResults(cpython_cmd, cpython_cached, force_update, send_kill): # Many details, pylint: disable=too-many-locals cached = False if cpython_cached: # TODO: Hashing stuff and creating cache filename is duplicate code # and should be shared. hash_input = " -- ".join(cpython_cmd) if str is not bytes: hash_input = hash_input.encode("utf8") command_hash = hashlib.md5(hash_input) for element in cpython_cmd: if os.path.exists(element): with open(element, "rb") as element_file: command_hash.update(element_file.read()) hash_salt = os.environ.get("NUITKA_HASH_SALT", "") if str is not bytes: hash_salt = hash_salt.encode("utf8") command_hash.update(hash_salt) if os.name == "nt" and python_version < 0x300: curdir = os.getcwdu() else: curdir = os.getcwd() command_hash.update(curdir.encode("utf8")) cache_filename = os.path.join( getTestingCPythonOutputsCacheDir(), command_hash.hexdigest() ) if os.path.exists(cache_filename) and not force_update: try: with open(cache_filename, "rb") as cache_file: ( cpython_time, stdout_cpython, stderr_cpython, exit_cpython, ) = pickle.load(cache_file) except (IOError, EOFError): # Broken cache content. pass else: cached = True if not cached: cpython_time, stdout_cpython, stderr_cpython, exit_cpython = _getCPythonResults( cpython_cmd=cpython_cmd, send_kill=send_kill ) if cpython_cached: with open(cache_filename, "wb") as cache_file: pickle.dump( (cpython_time, stdout_cpython, stderr_cpython, exit_cpython), cache_file, ) return cpython_time, stdout_cpython, stderr_cpython, exit_cpython def main(): # Of course many cases to deal with, pylint: disable=too-many-branches,too-many-locals,too-many-statements filename = sys.argv[1] args = sys.argv[2:] def hasArg(arg): if arg in args: args.remove(arg) return True else: return False def hasArgValue(arg_option, default=None): for arg in args: if arg.startswith(arg_option + "="): args.remove(arg) return arg[len(arg_option) + 1 :] return default def hasArgValues(arg_option): result = [] for arg in tuple(args): if arg.startswith(arg_option + "="): args.remove(arg) result.append(arg[len(arg_option) + 1 :]) return result # For output keep it arguments = list(args) silent_mode = hasArg("silent") ignore_stderr = hasArg("ignore_stderr") ignore_warnings = hasArg("ignore_warnings") expect_success = hasArg("expect_success") expect_failure = hasArg("expect_failure") python_debug = hasArg("python_debug") module_mode = hasArg("--module") coverage_mode = hasArg("coverage") two_step_execution = hasArg("two_step_execution") binary_python_path = hasArg("binary_python_path") keep_python_path = hasArg("keep_python_path") trace_command = ( hasArg("trace_command") or os.environ.get("NUITKA_TRACE_COMMANDS", "0") != "0" ) remove_output = hasArg("remove_output") remove_binary = not hasArg("--keep-binary") standalone_mode = hasArg("--standalone") onefile_mode = hasArg("--onefile") no_site = hasArg("no_site") or coverage_mode report = hasArgValue("--report") nofollow_imports = hasArg("recurse_none") or hasArg("--nofollow-imports") follow_imports = hasArg("recurse_all") or hasArg("--follow-imports") timing = hasArg("timing") original_file = hasArg("original_file") or hasArg( "--file-reference-choice=original" ) runtime_file = hasArg("runtime_file") or hasArg("--file-reference-choice=runtime") no_warnings = not hasArg("warnings") full_compat = not hasArg("improved") cpython_cached = hasArg("cpython_cache") syntax_errors = hasArg("syntax_errors") noprefer_source = hasArg("noprefer_source") noverbose_log = hasArg("noverbose_log") noinclusion_log = hasArg("noinclusion_log") send_kill = hasArg("--send-ctrl-c") output_dir = hasArgValue("--output-dir", None) include_packages = hasArgValues("--include-package") include_modules = hasArgValues("--include-module") python_flag_m = hasArg("--python-flag=-m") plugins_enabled = [] for count, arg in reversed(tuple(enumerate(args))): if arg.startswith("plugin_enable:"): plugins_enabled.append(arg[len("plugin_enable:") :]) del args[count] plugins_disabled = [] for count, arg in reversed(tuple(enumerate(args))): if arg.startswith("plugin_disable:"): plugins_disabled.append(arg[len("plugin_disable:") :]) del args[count] user_plugins = [] for count, arg in reversed(tuple(enumerate(args))): if arg.startswith("user_plugin:"): user_plugins.append(arg[len("user_plugin:") :]) del args[count] recurse_not = [] for count, arg in reversed(tuple(enumerate(args))): if arg.startswith("recurse_not:"): recurse_not.append(arg[len("recurse_not:") :]) del args[count] recurse_to = [] for count, arg in reversed(tuple(enumerate(args))): if arg.startswith("recurse_to:"): recurse_to.append(arg[len("recurse_to:") :]) del args[count] if args: sys.exit("Error, non understood mode(s) '%s'," % ",".join(args)) # In coverage mode, we don't want to execute, and to do this only in one mode, # we enable two step execution, which splits running the binary from the actual # compilation: if coverage_mode: two_step_execution = True # The coverage mode doesn't work with debug mode. if coverage_mode: python_debug = False comparison_mode = not coverage_mode # We need to split it, so we know when to kill. if send_kill: two_step_execution = True assert not standalone_mode or not module_mode assert not follow_imports or not nofollow_imports if "PYTHONHASHSEED" not in os.environ: os.environ["PYTHONHASHSEED"] = "0" os.environ["PYTHONWARNINGS"] = "ignore" if "PYTHON" not in os.environ: os.environ["PYTHON"] = sys.executable extra_options = os.environ.get("NUITKA_EXTRA_OPTIONS", "").split() if "--python-debug" in extra_options or "--python-dbg" in extra_options: python_debug = True if python_debug: if os.path.exists(os.path.join("/usr/bin/", os.environ["PYTHON"] + "-dbg")): os.environ["PYTHON"] += "-dbg" if os.name == "nt": if os.path.exists(os.environ["PYTHON"][:-4] + "_d.exe"): os.environ["PYTHON"] = os.environ["PYTHON"][:-4] + "_d.exe" if os.environ["PYTHON"].endswith("-dbg"): python_debug = True if os.environ["PYTHON"].lower().endswith("_d.exe"): python_debug = True if comparison_mode: my_print( """\ Comparing output of '{filename}' using '{python}' with flags {args} ...""".format( filename=filename, python=os.environ["PYTHON"], args=", ".join(arguments), ) ) else: my_print( """\ Taking coverage of '{filename}' using '{python}' with flags {args} ...""".format( filename=filename, python=os.environ["PYTHON"], args=", ".join(arguments), ) ) if comparison_mode and not silent_mode: my_print("*" * 80) my_print("CPython:") my_print("*" * 80) if two_step_execution: filename = os.path.abspath(filename) if module_mode: module_name = os.path.basename(filename) if module_name.endswith(".py"): module_name = module_name[:-3] cpython_cmd = [ os.environ["PYTHON"], "-c", "import sys; sys.path.append(%s); import %s" % (repr(os.path.dirname(filename)), module_name), ] if no_warnings: cpython_cmd[1:1] = [ "-W", "ignore", ] else: cpython_cmd = [os.environ["PYTHON"]] if no_warnings: cpython_cmd[1:1] = [ "-W", "ignore", ] if python_flag_m: cpython_cmd += ["-m", os.path.basename(filename)] os.chdir(os.path.dirname(filename)) else: cpython_cmd.append(filename) if no_site: cpython_cmd.insert(1, "-S") if "NUITKA" in os.environ: # Would need to extract which "python" this is going to use. assert not coverage_mode, "Not implemented for binaries." nuitka_call = [os.environ["NUITKA"]] else: if comparison_mode: nuitka_call = [ os.environ["PYTHON"], "-m", "nuitka.__main__", # Note: Needed for Python2.6 ] else: assert coverage_mode nuitka_call = [ os.environ["PYTHON"], "-S", "-m", "coverage", "run", "--rcfile", os.devnull, "-a", "-m", "nuitka.__main__", # Note: Needed for Python2.6 ] if python_debug: extra_options.append("--python-debug") if no_warnings: extra_options.append("--python-flag=no_warnings") if remove_output: extra_options.append("--remove-output") if original_file: extra_options.append("--file-reference-choice=original") if runtime_file: extra_options.append("--file-reference-choice=runtime") if full_compat: extra_options.append("--full-compat") if noprefer_source: extra_options.append("--no-prefer-source") if python_flag_m: extra_options.append("--python-flag=-m") if coverage_mode: # Coverage modules hates Nuitka to re-execute, and so we must avoid # that. python_path = check_output( [ os.environ["PYTHON"], "-c", "import sys, os; print(os.pathsep.join(sys.path))", ] ) if sys.version_info >= (3,): python_path = python_path.decode("utf8") os.environ["PYTHONPATH"] = python_path.strip() if binary_python_path: addToPythonPath(os.path.dirname(os.path.abspath(filename))) if keep_python_path or binary_python_path: extra_options.append("--execute-with-pythonpath") if report: extra_options.append("--report=%s" % report) if nofollow_imports: extra_options.append("--nofollow-imports") if follow_imports: extra_options.append("--follow-imports") if recurse_not: extra_options.extend("--nofollow-import-to=" + v for v in recurse_not) if coverage_mode: extra_options.append("--must-not-re-execute") extra_options.append("--generate-c-only") for plugin_enabled in plugins_enabled: extra_options.append("--enable-plugin=" + plugin_enabled) for plugin_disabled in plugins_disabled: extra_options.append("--disable-plugin=" + plugin_disabled) for user_plugin in user_plugins: extra_options.append("--user-plugin=" + user_plugin) if not noverbose_log: extra_options.append("--verbose-output=%s.optimization.log" % filename) if not noinclusion_log: extra_options.append("--show-modules-output=%s.inclusion.log" % filename) if output_dir is not None: extra_options.append("--output-dir=%s" % output_dir) else: # TODO: The run-tests uses NUITKA_EXTRA_OPTIONS still. for extra_option in extra_options: dir_match = re.search(r"--output-dir=(.*?)(\s|$)", extra_option) if dir_match: output_dir = dir_match.group(1) break else: # The default. output_dir = "." for include_package in include_packages: extra_options.append("--include-package=%s" % include_package) for include_module in include_modules: extra_options.append("--include-module=%s" % include_module) # Now build the command to run Nuitka. if not two_step_execution: if module_mode: extra_options.append("--module") elif onefile_mode: extra_options.append("--onefile") elif standalone_mode: extra_options.append("--standalone") nuitka_cmd = nuitka_call + extra_options + ["--run", filename] if no_site: nuitka_cmd.insert(len(nuitka_cmd) - 1, "--python-flag=-S") else: if module_mode: nuitka_cmd1 = ( nuitka_call + extra_options + ["--module", os.path.abspath(filename)] ) elif standalone_mode: nuitka_cmd1 = nuitka_call + extra_options + ["--standalone", filename] else: nuitka_cmd1 = nuitka_call + extra_options + [filename] if no_site: nuitka_cmd1.insert(len(nuitka_cmd1) - 1, "--python-flag=-S") if module_mode: module_name = os.path.basename(filename) if module_name.endswith(".py"): module_name = module_name[:-3] nuitka_cmd2 = [ os.environ["PYTHON"], "-W", "ignore", "-c", "import %s" % module_name, ] else: exe_filename = os.path.basename(filename) if filename.endswith(".py"): exe_filename = exe_filename[:-3] exe_filename = exe_filename.replace(")", "").replace("(", "") if os.name == "nt": exe_filename += ".exe" else: exe_filename += ".bin" nuitka_cmd2 = [os.path.join(output_dir, exe_filename)] pdb_filename = exe_filename[:-4] + ".pdb" if trace_command: my_print("CPython command:", *cpython_cmd) if comparison_mode: cpython_time, stdout_cpython, stderr_cpython, exit_cpython = getCPythonResults( cpython_cmd=cpython_cmd, cpython_cached=cpython_cached, force_update=False, send_kill=send_kill, ) if not silent_mode: displayOutput(stdout_cpython, stderr_cpython) if comparison_mode and not silent_mode: my_print("*" * 80) my_print("Nuitka:") my_print("*" * 80) if two_step_execution: if output_dir: os.chdir(output_dir) else: tmp_dir = getTempDir() os.chdir(tmp_dir) if trace_command: my_print("Going to output directory", os.getcwd()) stop_watch = StopWatch() stop_watch.start() if not two_step_execution: if trace_command: my_print("Nuitka command:", nuitka_cmd) # Try a couple of times for permission denied, on Windows it can # be transient. for _i in range(5): with withPythonPathChange(nuitka_package_dir): process = subprocess.Popen( args=nuitka_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout_nuitka, stderr_nuitka = process.communicate() exit_nuitka = process.returncode if checkNoPermissionError(stdout_nuitka) and checkNoPermissionError( stderr_nuitka ): break my_print("Retrying nuitka exe due to permission problems after delay.") time.sleep(2) else: if trace_command: my_print("Nuitka command 1:", nuitka_cmd1) for _i in range(5): with withPythonPathChange(nuitka_package_dir): stdout_nuitka1, stderr_nuitka1, exit_nuitka1 = executeProcess( nuitka_cmd1 ) if exit_nuitka1 != 0: if ( not expect_failure and not comparison_mode and not os.path.exists(".coverage") ): sys.exit( """\ Error, failed to take coverage with '%s'. Stderr was: %s """ % (os.environ["PYTHON"], stderr_nuitka1) ) exit_nuitka = exit_nuitka1 stdout_nuitka, stderr_nuitka = stdout_nuitka1, stderr_nuitka1 stdout_nuitka2 = b"not run due to compilation error:\n" + stdout_nuitka1 stderr_nuitka2 = stderr_nuitka1 else: # No execution second step for coverage mode. if comparison_mode: if os.path.exists(nuitka_cmd2[0][:-4] + ".cmd"): nuitka_cmd2[0] = nuitka_cmd2[0][:-4] + ".cmd" if trace_command: my_print("Nuitka command 2:", nuitka_cmd2) # Need full manual control, and not all Python versions allow using # context manager here, pylint: disable=consider-using-with process = subprocess.Popen( args=nuitka_cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) if send_kill: # Lambda is used immediately in same loop, pylint: disable=cell-var-from-loop executeAfterTimePassed( 1.0, lambda: killProcess("Nuitka compiled program", process.pid), ) stdout_nuitka2, stderr_nuitka2 = process.communicate() stdout_nuitka = stdout_nuitka1 + stdout_nuitka2 stderr_nuitka = stderr_nuitka1 + stderr_nuitka2 exit_nuitka = process.returncode # In case of segfault or assertion triggered, run in debugger. if exit_nuitka in (-11, -6) and sys.platform != "nt": nuitka_cmd2 = wrapCommandForDebuggerForSubprocess(*nuitka_cmd2) executeProcess(nuitka_cmd2) else: exit_nuitka = exit_nuitka1 stdout_nuitka, stderr_nuitka = stdout_nuitka1, stderr_nuitka1 if checkNoPermissionError(stdout_nuitka) and checkNoPermissionError( stderr_nuitka ): break my_print("Retrying nuitka exe due to permission problems after delay.") time.sleep(2) stop_watch.stop() nuitka_time = stop_watch.getDelta() if not silent_mode: displayOutput(stdout_nuitka, stderr_nuitka) if coverage_mode: assert not stdout_nuitka assert not stderr_nuitka if comparison_mode: def makeComparisons(trace_result): exit_code_stdout = compareOutput( "stdout", stdout_cpython, stdout_nuitka2 if two_step_execution else stdout_nuitka, ignore_warnings, syntax_errors, ) if ignore_stderr: exit_code_stderr = 0 else: exit_code_stderr = compareOutput( "stderr", stderr_cpython, stderr_nuitka2 if two_step_execution else stderr_nuitka, ignore_warnings, syntax_errors, ) exit_code_return = exit_cpython != exit_nuitka if exit_code_return and trace_result: my_print( """Exit codes {exit_cpython:d} (CPython) != {exit_nuitka:d} (Nuitka)""".format( exit_cpython=exit_cpython, exit_nuitka=exit_nuitka ) ) return exit_code_stdout, exit_code_stderr, exit_code_return if cpython_cached: exit_code_stdout, exit_code_stderr, exit_code_return = makeComparisons( trace_result=False ) if not int(os.environ.get("NUITKA_CPYTHON_NO_CACHE_UPDATE", "0")): if exit_code_stdout or exit_code_stderr or exit_code_return: old_stdout_cpython = stdout_cpython old_stderr_cpython = stderr_cpython old_exit_cpython = exit_cpython my_print( "Updating CPython cache by force due to non-matching comparison results.", style="yellow", ) ( cpython_time, stdout_cpython, stderr_cpython, exit_cpython, ) = getCPythonResults( cpython_cmd=cpython_cmd, cpython_cached=cpython_cached, force_update=True, send_kill=send_kill, ) if not silent_mode: if ( old_stdout_cpython != stdout_cpython or old_stderr_cpython != stderr_cpython or old_exit_cpython != exit_cpython ): displayOutput(stdout_cpython, stderr_cpython) exit_code_stdout, exit_code_stderr, exit_code_return = makeComparisons( trace_result=True ) # In case of segfault, also output the call stack by entering debugger # without stdin forwarded. if ( exit_code_return and exit_nuitka in (-11, -6) and sys.platform != "nt" and not module_mode and not two_step_execution ): nuitka_cmd.insert(len(nuitka_cmd) - 1, "--debugger") with withPythonPathChange(nuitka_package_dir): executeProcess(command=nuitka_cmd, needs_stdin=True) exit_code = exit_code_stdout or exit_code_stderr or exit_code_return if exit_code: problems = [] if exit_code_stdout: problems.append("stdout") if exit_code_stderr: problems.append("stderr") if exit_code_return: problems.append("exit_code") sys.exit("Error, results differed (%s)." % ",".join(problems)) if expect_success and exit_cpython != 0: if silent_mode: displayOutput(stdout_cpython, stderr_cpython) sys.exit("Unexpected error exit from CPython.") if expect_failure and exit_cpython == 0: sys.exit("Unexpected success exit from CPython.") if remove_output: if not module_mode: if os.path.exists(nuitka_cmd2[0]) and remove_binary: if os.name == "nt": # It appears there is a tiny lock race that we randomly cause, # likely because --run spawns a subprocess that might still # be doing the cleanup work. if os.path.exists(nuitka_cmd2[0] + ".away"): os.unlink(nuitka_cmd2[0] + ".away") for _i in range(10): try: os.rename(nuitka_cmd2[0], nuitka_cmd2[0] + ".away") except OSError: time.sleep(0.1) continue for _i in range(10): try: os.unlink(nuitka_cmd2[0] + ".away") except OSError: time.sleep(2) continue else: break if os.path.exists(pdb_filename): os.unlink(pdb_filename) else: os.unlink(nuitka_cmd2[0]) else: module_filename = os.path.basename(filename) + getSharedLibrarySuffix( preferred=True ) if os.path.exists(module_filename) and remove_binary: os.unlink(module_filename) if comparison_mode and timing: my_print("CPython took %.2fs vs %0.2fs Nuitka." % (cpython_time, nuitka_time)) if comparison_mode and not silent_mode: my_print("OK, same outputs.") nuitka_package_dir = os.path.normpath( os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")) ) if __name__ == "__main__": # Unchanged, running from checkout, use the parent directory, the nuitka # package ought be there. sys.path.insert(0, nuitka_package_dir) main() Nuitka-0.6.19.1/nuitka/tools/testing/compare_with_cpython/__init__.py0000600000372100037210000000150114166627112032732 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/find_sxs_modules/0000700000372100037210000000000014167275622027750 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/find_sxs_modules/__main__.py0000600000372100037210000000364314166627112032044 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tool to compare output of CPython and Nuitka. """ import os import sys import tempfile from nuitka.tools.testing.Common import ( compileLibraryTest, createSearchMode, setup, ) from nuitka.Tracing import my_print from nuitka.utils.SharedLibraries import getSxsFromDLL def decide(root, filename): return ( filename.endswith((".so", ".pyd")) and not filename.startswith("libpython") and getSxsFromDLL(os.path.join(root, filename)) ) def action(stage_dir, root, path): # We need only the actual path, pylint: disable=unused-argument sxs = getSxsFromDLL(path) if sxs: my_print(path, sxs) def main(): if os.name != "nt": sys.exit("Error, this is only for use on Windows where SxS exists.") setup(needs_io_encoding=True) search_mode = createSearchMode() tmp_dir = tempfile.gettempdir() compileLibraryTest( search_mode=search_mode, stage_dir=os.path.join(tmp_dir, "find_sxs_modules"), decide=decide, action=action, ) my_print("FINISHED, all extension modules checked.") if __name__ == "__main__": main() Nuitka-0.6.19.1/nuitka/tools/testing/find_sxs_modules/__init__.py0000600000372100037210000000150114166627112032052 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/measure_construct_performance/0000700000372100037210000000000014167275622032531 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/measure_construct_performance/__main__.py0000700000372100037210000002067414166627112034631 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Run a construct based comparison test. This executes a program with and without snippet of code and stores the numbers about it, extracted with Valgrind for use in comparisons. """ import hashlib import os import shutil import sys from optparse import OptionParser from nuitka.tools.testing.Common import ( check_output, convertUsing2to3, decideNeeds2to3, getPythonVersionString, getTempDir, my_print, setup, ) from nuitka.tools.testing.Constructs import generateConstructCases from nuitka.tools.testing.Valgrind import runValgrind from nuitka.utils.Execution import check_call from nuitka.utils.FileOperations import ( getFileContentByLine, getFileContents, putTextFileContents, ) def main(): # Complex stuff, not broken down yet # pylint: disable=too-many-branches,too-many-locals,too-many-statements parser = OptionParser() parser.add_option( "--nuitka", action="store", dest="nuitka", default=os.environ.get("NUITKA", "") ) parser.add_option( "--cpython", action="store", dest="cpython", default=os.environ.get("PYTHON", sys.executable), ) parser.add_option("--code-diff", action="store", dest="diff_filename", default="") parser.add_option("--copy-source-to", action="store", dest="target_dir", default="") options, positional_args = parser.parse_args() if len(positional_args) != 1: sys.exit("Error, need to give test case file name as positional argument.") test_case = positional_args[0] if os.path.exists(test_case): test_case = os.path.abspath(test_case) if options.cpython == "no": options.cpython = "" nuitka = options.nuitka if os.path.exists(nuitka): nuitka = os.path.abspath(nuitka) elif nuitka: sys.exit("Error, nuitka binary '%s' not found." % nuitka) setup(silent=True, go_main=False) assert os.path.exists(test_case), (test_case, os.getcwd()) my_print("PYTHON='%s'" % getPythonVersionString()) my_print("PYTHON_BINARY='%s'" % os.environ["PYTHON"]) my_print( "TEST_CASE_HASH='%s'" % hashlib.md5(getFileContents(test_case, "rb")).hexdigest() ) needs_2to3 = decideNeeds2to3(test_case) if options.target_dir: shutil.copyfile( test_case, os.path.join(options.target_dir, os.path.basename(test_case)) ) # First produce two variants. temp_dir = getTempDir() test_case_1 = os.path.join(temp_dir, "Variant1_" + os.path.basename(test_case)) test_case_2 = os.path.join(temp_dir, "Variant2_" + os.path.basename(test_case)) case_1_source, case_2_source = generateConstructCases(getFileContents(test_case)) putTextFileContents(test_case_1, case_1_source) putTextFileContents(test_case_2, case_2_source) if needs_2to3: test_case_1, _needs_delete = convertUsing2to3(test_case_1) test_case_2, _needs_delete = convertUsing2to3(test_case_2) os.environ["PYTHONHASHSEED"] = "0" if nuitka: nuitka_id = check_output( "cd %s; git rev-parse HEAD" % os.path.dirname(nuitka), shell=True ) nuitka_id = nuitka_id.strip() if sys.version_info > (3,): nuitka_id = nuitka_id.decode() my_print("NUITKA_COMMIT='%s'" % nuitka_id) os.chdir(getTempDir()) case_name = os.path.basename(test_case) no_site = "Numpy" not in case_name if nuitka: nuitka_call = [ os.environ["PYTHON"], nuitka, "--quiet", "--no-progress", ] if no_site: nuitka_call.append("--python-flag=-S") nuitka_call.extend(os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()) nuitka_call.append(case_name) # We want to compile under the same filename to minimize differences, and # then copy the resulting files afterwards. shutil.copyfile(test_case_1, case_name) check_call(nuitka_call) if os.path.exists(os.path.basename(test_case).replace(".py", ".exe")): exe_suffix = ".exe" else: exe_suffix = ".bin" os.rename( os.path.basename(test_case).replace(".py", ".build"), os.path.basename(test_case_1).replace(".py", ".build"), ) os.rename( os.path.basename(test_case).replace(".py", exe_suffix), os.path.basename(test_case_1).replace(".py", exe_suffix), ) shutil.copyfile(test_case_2, os.path.basename(test_case)) check_call(nuitka_call) os.rename( os.path.basename(test_case).replace(".py", ".build"), os.path.basename(test_case_2).replace(".py", ".build"), ) os.rename( os.path.basename(test_case).replace(".py", exe_suffix), os.path.basename(test_case_2).replace(".py", exe_suffix), ) if options.diff_filename: suffixes = [".c", ".cpp"] for suffix in suffixes: cpp_1 = os.path.join( test_case_1.replace(".py", ".build"), "module.__main__" + suffix ) if os.path.exists(cpp_1): break else: assert False for suffix in suffixes: cpp_2 = os.path.join( test_case_2.replace(".py", ".build"), "module.__main__" + suffix ) if os.path.exists(cpp_2): break else: assert False import difflib putTextFileContents( options.diff_filename, difflib.HtmlDiff().make_table( getFileContentByLine(cpp_1), getFileContentByLine(cpp_2), "Construct", "Baseline", True, ), ) nuitka_1 = runValgrind( "Nuitka construct", "callgrind", (test_case_1.replace(".py", exe_suffix),), include_startup=True, ) nuitka_2 = runValgrind( "Nuitka baseline", "callgrind", (test_case_2.replace(".py", exe_suffix),), include_startup=True, ) nuitka_diff = nuitka_1 - nuitka_2 my_print("NUITKA_COMMAND='%s'" % " ".join(nuitka_call), file=sys.stderr) my_print("NUITKA_RAW=%s" % nuitka_1) my_print("NUITKA_BASE=%s" % nuitka_2) my_print("NUITKA_CONSTRUCT=%s" % nuitka_diff) if options.cpython: cpython_call = [os.environ["PYTHON"], "-S", test_case_1] if not no_site: cpython_call.remove("-S") cpython_1 = runValgrind( "CPython construct", "callgrind", cpython_call, include_startup=True, ) cpython_call = [os.environ["PYTHON"], "-S", test_case_2] if not no_site: cpython_call.remove("-S") cpython_2 = runValgrind( "CPython baseline", "callgrind", cpython_call, include_startup=True, ) cpython_diff = cpython_1 - cpython_2 my_print("CPYTHON_RAW=%d" % cpython_1) my_print("CPYTHON_BASE=%d" % cpython_2) my_print("CPYTHON_CONSTRUCT=%d" % cpython_diff) if options.cpython and options.nuitka: if nuitka_diff == 0: nuitka_gain = float("inf") else: nuitka_gain = float(100 * cpython_diff) / nuitka_diff my_print("NUITKA_GAIN=%.3f" % nuitka_gain) my_print("RAW_GAIN=%.3f" % (float(100 * cpython_1) / nuitka_1)) my_print("BASE_GAIN=%.3f" % (float(100 * cpython_2) / nuitka_2)) if __name__ == "__main__": main() Nuitka-0.6.19.1/nuitka/tools/testing/measure_construct_performance/__init__.py0000600000372100037210000000150114166627112034633 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/Constructs.py0000600000372100037210000000271314166627112027123 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tools for construct tests. """ def generateConstructCases(construct_source_code): inside = False case = 0 case_1 = [] case_2 = [] for line in construct_source_code.splitlines(): if not inside or case == 1: case_1.append(line) else: case_1.append("") if "# construct_end" in line: inside = False if "# construct_alternative" in line: case = 2 if not inside or case == 2: case_2.append(line) else: case_2.append("") if "# construct_begin" in line: inside = True case = 1 return "\n".join(case_1), "\n".join(case_2) Nuitka-0.6.19.1/nuitka/tools/testing/Virtualenv.py0000600000372100037210000000665214166627112027121 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Creating virtualenvs and running commands in them. """ import os import sys from contextlib import contextmanager from nuitka.__past__ import unicode from nuitka.utils.Execution import check_call, executeProcess from nuitka.utils.FileOperations import removeDirectory, withDirectoryChange from .Common import my_print class Virtualenv(object): def __init__(self, env_dir): self.env_dir = os.path.abspath(env_dir) def runCommand(self, commands, style=None): if type(commands) in (str, unicode): commands = [commands] with withDirectoryChange(self.env_dir): if os.name == "nt": commands = [r"call scripts\activate.bat"] + commands else: commands = [". bin/activate"] + commands command = " && ".join(commands) if style is not None: my_print("Executing: %s" % command, style=style) assert os.system(command) == 0, command def runCommandWithOutput(self, commands, style=None): """ Returns the stdout,stderr,exit_code from running command """ if type(commands) in (str, unicode): commands = [commands] with withDirectoryChange(self.env_dir): if os.name == "nt": commands = [r"call scripts\activate.bat"] + commands else: commands = [". bin/activate"] + commands # Build shell command. command = " && ".join(commands) if style is not None: my_print("Executing: %s" % command, style=style) # Use subprocess and also return outputs, stdout, stderr, result return executeProcess( command=command, shell=True, ) def getVirtualenvDir(self): return self.env_dir @contextmanager def withVirtualenv(env_name, base_dir=None, python=None, delete=True, style=None): """Create a virtualenv and change into it. Activating for actual use will be your task. """ if style is not None: my_print("Creating a virtualenv:") if python is None: python = sys.executable if base_dir is not None: env_dir = os.path.join(base_dir, env_name) else: env_dir = env_name removeDirectory(env_dir, ignore_errors=False) with withDirectoryChange(base_dir, allow_none=True): command = [python, "-m", "virtualenv", env_name] if style is not None: my_print("Executing: %s" % " ".join(command), style=style) check_call(command) yield Virtualenv(env_dir) if delete: removeDirectory(env_dir, ignore_errors=False) Nuitka-0.6.19.1/nuitka/tools/testing/OutputComparison.py0000600000372100037210000001771214166627112030314 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tools to compare outputs of compiled and not compiled programs. There is a couple of replacements to be done for compiled programs to make the diff meaningful. The compiled type representations are just an example. """ import difflib import os import re from nuitka.Tracing import my_print ran_tests_re = re.compile(r"^(Ran \d+ tests? in )\-?\d+\.\d+s$") instance_re = re.compile(r"at (?:0x)?[0-9a-fA-F]+(;?\s|\>)") thread_re = re.compile(r"[Tt]hread 0x[0-9a-fA-F]+") compiled_types_re = re.compile( r"compiled_(module|function|generator|method|frame|coroutine|async_generator|cell)" ) module_repr_re = re.compile(r"(\)") global_name_error_re = re.compile(r"global (name ')(.*?)(' is not defined)") non_ascii_error_rt = re.compile(r"(SyntaxError: Non-ASCII character.*? on line) \d+") python_win_lib_re = re.compile(r"[a-zA-Z]:\\\\?[Pp]ython(.*?\\\\?)[Ll]ib") local_port_re = re.compile(r"(127\.0\.0\.1):\d{2,5}") traceback_re = re.compile(r'(F|f)ile "(.*?)", line (\d+)') def traceback_re_callback(match): return r'%sile "%s", line %s' % ( match.group(1), os.path.realpath(os.path.abspath(match.group(2))), match.group(3), ) importerror_re = re.compile( r"""(ImportError(?:\("|: )cannot import name '\w+' from '.*?' )\((.*?)\)""" ) def import_re_callback(match): # print (match.groups(), os.path.abspath(match.group(2))) return r"%s( >> %s)" % ( match.group(1), os.path.realpath(os.path.abspath(match.group(2))), ) tempfile_re = re.compile(r"/tmp/tmp[a-z0-9_]*") logging_info_re = re.compile(r"^Nuitka.*?:INFO") logging_warning_re = re.compile(r"^Nuitka.*?:WARNING") def normalizeTimeDiff(outputStr): """ use regular expression to normalize the time output e.g. =================== 1059 passed, 8 warnings in 7.99 seconds =================== becomes =================== 1059 passed, 8 warnings in x.xx seconds =================== """ match = re.search(b"in [0-9]+.[0-9][0-9](s| seconds)", outputStr) if match: return ( outputStr[: match.start()] + b"in x.xx seconds" + outputStr[match.end() :] ) return outputStr def makeDiffable(output, ignore_warnings, syntax_errors): # Of course many cases to deal with, # pylint: disable=too-many-branches,too-many-statements # do not compare time differences output = normalizeTimeDiff(output) result = [] # Fix import "readline" because output sometimes starts with "\x1b[?1034h" m = re.match(b"\\x1b\\[[^h]+h", output) if m: output = output[len(m.group()) :] lines = output.split(b"\n") if syntax_errors: for line in lines: if line.startswith(b"SyntaxError:"): lines = [line] break for line in lines: if type(line) is not str: try: line = line.decode("utf-8" if os.name != "nt" else "cp850") except UnicodeDecodeError: line = repr(line) if line.endswith("\r"): line = line[:-1] if line.startswith("REFCOUNTS"): first_value = line[line.find("[") + 1 : line.find(",")] last_value = line[line.rfind(" ") + 1 : line.rfind("]")] line = line.replace(first_value, "xxxxx").replace(last_value, "xxxxx") if line.startswith("[") and line.endswith("refs]"): continue if ignore_warnings and logging_warning_re.match(line): continue # Infos are always ignored. if logging_info_re.match(line): continue if line.startswith("Nuitka-Recursion:WARNING: Cannot follow import to module"): continue line = instance_re.sub(r"at 0xxxxxxxxx\1", line) line = thread_re.sub(r"Thread 0xXXXXXXXX", line) line = compiled_types_re.sub(r"\1", line) line = global_name_error_re.sub(r"\1\2\3", line) line = module_repr_re.sub(r"\1xxxxx\2", line) line = non_ascii_error_rt.sub(r"\1 xxxx", line) # Windows has a different "os.path", update according to it. line = line.replace("ntpath", "posixpath") # This URL is updated, and Nuitka outputs the new one, but we test # against versions that don't have that. line = line.replace( "http://www.python.org/peps/pep-0263.html", "http://python.org/dev/peps/pep-0263/", ) line = ran_tests_re.sub(r"\1x.xxxs", line) line = traceback_re.sub(traceback_re_callback, line) line = importerror_re.sub(import_re_callback, line) line = tempfile_re.sub(r"/tmp/tmpxxxxxxx", line) # This is a bug potentially, occurs only for CPython when re-directed, # we are going to ignore the issue as Nuitka is fine. if ( line == """\ Exception RuntimeError: 'maximum recursion depth \ exceeded while calling a Python object' in \ ignored""" ): continue # TODO: Harmonize exception ignored in function or method. if re.match("Exception ignored in:.*__del__", line): continue # This is also a bug potentially, but only visible under # CPython line = python_win_lib_re.sub(r"C:\\Python\1Lib", line) # Port numbers can be random, lets ignore them line = local_port_re.sub(r"\1:xxxxx", line) # This is a bug with clang potentially, can't find out why it says that. if line == "/usr/bin/ld: warning: .init_array section has zero size": continue # This is for NetBSD and OpenBSD, which seems to build "libpython" so # that it gives such warnings. if "() possibly used unsafely" in line or "() is almost always misused" in line: continue # This is for CentOS5, where the linker says this, and it's hard to # disable if "skipping incompatible /usr/lib/libpython2.6.so" in line: continue # This is for self compiled Python with default options, gives this # harmless option for every time we link to "libpython". if ( "is dangerous, better use `mkstemp'" in line or "In function `posix_tempnam'" in line or "In function `posix_tmpnam'" in line ): continue # Ignore spurious clcache warning. if "clcache: persistent json file" in line or "clcache: manifest file" in line: continue result.append(line) return result def compareOutput( kind, out_cpython, out_nuitka, ignore_warnings, syntax_errors, trace_result=True ): fromdate = "" todate = "" diff = difflib.unified_diff( makeDiffable(out_cpython, ignore_warnings, syntax_errors), makeDiffable(out_nuitka, ignore_warnings, syntax_errors), "{program} ({detail})".format(program=os.environ["PYTHON"], detail=kind), "{program} ({detail})".format(program="nuitka", detail=kind), fromdate, todate, n=3, ) result = list(diff) if result: if trace_result: for line in result: my_print(line, end="\n" if not line.startswith("---") else "") return 1 else: return 0 Nuitka-0.6.19.1/nuitka/tools/testing/__init__.py0000600000372100037210000000150114166627112026505 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/Common.py0000600000372100037210000014174014166627112026210 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Common test infrastructure functions. To be used by test runners. """ import ast import atexit import gc import hashlib import os import shutil import signal import sys import tempfile import threading import time from contextlib import contextmanager from optparse import OptionGroup, OptionParser from nuitka.__past__ import subprocess from nuitka.PythonVersions import ( getPartiallySupportedPythonVersions, getSupportedPythonVersions, ) from nuitka.Tracing import OurLogger, my_print from nuitka.tree.SourceReading import readSourceCodeFromFilename from nuitka.utils.AppDirs import getCacheDir from nuitka.utils.Execution import check_output, getNullInput, getNullOutput from nuitka.utils.FileOperations import ( areSamePaths, getExternalUsePath, getFileContentByLine, getFileContents, getFileList, isPathBelowOrSameAs, makePath, openTextFile, removeDirectory, ) from nuitka.utils.Jinja2 import getTemplate from nuitka.utils.Utils import getOS from .SearchModes import ( SearchModeAll, SearchModeByPattern, SearchModeCoverage, SearchModeImmediate, SearchModeOnly, SearchModeResume, ) test_logger = OurLogger("", base_style="blue") def check_result(*popenargs, **kwargs): if "stdout" in kwargs: raise ValueError("stdout argument not allowed, it will be overridden.") process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) _unused_output, _unused_err = process.communicate() retcode = process.poll() if retcode: return False else: return True def goMainDir(): # Go its own directory, to have it easy with path knowledge. os.chdir(os.path.dirname(os.path.abspath(sys.modules["__main__"].__file__))) _python_version_str = None _python_version = None _python_arch = None _python_executable = None _python_vendor = None def setup(suite="", needs_io_encoding=False, silent=False, go_main=True): if go_main: goMainDir() if "PYTHON" not in os.environ: os.environ["PYTHON"] = sys.executable # Allow test code to use this to make caching specific. os.environ["NUITKA_TEST_SUITE"] = suite # Allow providing 33, 27, and expand that to python2.7 if ( len(os.environ["PYTHON"]) == 2 and os.environ["PYTHON"].isdigit() and os.name != "nt" ): os.environ["PYTHON"] = "python%s.%s" % ( os.environ["PYTHON"][0], os.environ["PYTHON"][1], ) if needs_io_encoding and "PYTHONIOENCODING" not in os.environ: os.environ["PYTHONIOENCODING"] = "utf-8" version_output = check_output( ( os.environ["PYTHON"], "-c", """\ import sys, os;\ print(".".join(str(s) for s in list(sys.version_info)[:3]));\ print(("x86_64" if "AMD64" in sys.version else "x86") if os.name == "nt" else os.uname()[4]);\ print(sys.executable);\ print("Anaconda" if os.path.exists(os.path.join(sys.prefix, 'conda-meta')) else "Unknown")\ """, ), stderr=subprocess.STDOUT, ) global _python_version_str, _python_version, _python_arch, _python_executable, _python_vendor # singleton, pylint: disable=global-statement _python_version_str = version_output.split(b"\n")[0].strip() _python_arch = version_output.split(b"\n")[1].strip() _python_executable = version_output.split(b"\n")[2].strip() _python_vendor = version_output.split(b"\n")[3].strip() if str is not bytes: _python_version_str = _python_version_str.decode("utf8") _python_arch = _python_arch.decode("utf8") _python_executable = _python_executable.decode("utf8") _python_vendor = _python_vendor.decode("utf8") assert type(_python_version_str) is str, repr(_python_version_str) assert type(_python_arch) is str, repr(_python_arch) assert type(_python_executable) is str, repr(_python_executable) if not silent: my_print("Using concrete python", _python_version_str, "on", _python_arch) if "COVERAGE_FILE" not in os.environ: os.environ["COVERAGE_FILE"] = os.path.join( os.path.dirname(__file__), "..", "..", "..", ".coverage" ) _python_version = tuple(int(d) for d in _python_version_str.split(".")) return _python_version def getPythonArch(): return _python_arch def getPythonVendor(): return _python_vendor def getPythonVersionString(): return _python_version_str tmp_dir = None def getTempDir(): # Create a temporary directory to work in, automatically remove it in case # it is empty in the end. global tmp_dir # singleton, pylint: disable=global-statement if tmp_dir is None: tmp_dir = tempfile.mkdtemp( prefix=os.path.basename( os.path.dirname(os.path.abspath(sys.modules["__main__"].__file__)) ) + "-", dir=tempfile.gettempdir() if not os.path.exists("/var/tmp") else "/var/tmp", ) def removeTempDir(): removeDirectory(path=tmp_dir, ignore_errors=True) atexit.register(removeTempDir) return tmp_dir def convertUsing2to3(path, force=False): command = [os.environ["PYTHON"], "-m", "py_compile", path] if not force: if "xrange" not in getFileContents(path): if check_result(command, stderr=getNullOutput()): return path, False filename = os.path.basename(path) new_path = os.path.join(getTempDir(), filename) # This may already be a temp file, e.g. because of construct creation. try: shutil.copy(path, new_path) except shutil.Error: pass # For Python2.6 and 3.2 the -m lib2to3 was not yet supported. use_binary = sys.version_info[:2] in ((2, 6), (3, 2)) if use_binary: # On Windows, we cannot rely on 2to3 to be in the path. if os.name == "nt": command = [ sys.executable, os.path.join(os.path.dirname(sys.executable), "Tools/Scripts/2to3.py"), ] else: command = ["2to3"] else: command = [sys.executable, "-m", "lib2to3"] command += ("-w", "-n", "--no-diffs", new_path) try: check_output(command, stderr=getNullOutput()) except subprocess.CalledProcessError: if os.name == "nt": raise command[0:3] = ["2to3"] check_output(command, stderr=getNullOutput()) data = getFileContents(new_path) with openTextFile(new_path, "w") as result_file: result_file.write("__file__ = %r\n" % os.path.abspath(path)) result_file.write(data) return new_path, True def decideFilenameVersionSkip(filename): """Make decision whether to skip based on filename and Python version. This codifies certain rules that files can have as suffixes or prefixes to make them be part of the set of tests executed for a version or not. Generally, an ening of ".py" indicates that it must be that Python version or higher. There is no need for ending in "26.py" as this is the minimum version anyway. The "_2.py" indicates a maxmimum version of 2.7, i.e. not Python 3.x, for language syntax no more supported. """ # This will make many decisions with immediate returns. # pylint: disable=too-many-branches,too-many-return-statements assert type(filename) is str, repr(filename) # Skip runner scripts by default. if filename.startswith("run_"): return False if filename.endswith(".j2"): filename = filename[:-3] # Skip tests that require Python 2.7 at least. if filename.endswith("27.py") and _python_version < (2, 7): return False # Skip tests that require Python 2 at maximum. if filename.endswith("_2.py") and _python_version >= (3,): return False # Skip tests that require Python 3.7 at maximum. if filename.endswith("_37.py") and _python_version >= (3, 8): return False # Skip tests that require Python 3.2 at least. if filename.endswith("32.py") and _python_version < (3, 2): return False # Skip tests that require Python 3.3 at least. if filename.endswith("33.py") and _python_version < (3, 3): return False # Skip tests that require Python 3.4 at least. if filename.endswith("34.py") and _python_version < (3, 4): return False # Skip tests that require Python 3.5 at least. if filename.endswith("35.py") and _python_version < (3, 5): return False # Skip tests that require Python 3.6 at least. if filename.endswith("36.py") and _python_version < (3, 6): return False # Skip tests that require Python 3.7 at least. if filename.endswith("37.py") and _python_version < (3, 7): return False # Skip tests that require Python 3.8 at least. if filename.endswith("38.py") and _python_version < (3, 8): return False # Skip tests that require Python 3.9 at least. if filename.endswith("39.py") and _python_version < (3, 9): return False # Skip tests that require Python 3.10 at least. if filename.endswith("310.py") and _python_version < (3, 10): return False return True def decideNeeds2to3(filename): return _python_version >= (3,) and not filename.endswith( ( "32.py", "33.py", "34.py", "35.py", "36.py", "37.py", "38.py", "39.py", "310.py", ) ) def _removeCPythonTestSuiteDir(): # Cleanup, some tests apparently forget that. try: if os.path.isdir("@test"): removeDirectory("@test", ignore_errors=False) elif os.path.isfile("@test"): os.unlink("@test") except OSError: # TODO: Move this into removeDirectory maybe. Doing an external # call as last resort could be a good idea. # This seems to work for broken "lnk" files. if os.name == "nt": os.system("rmdir /S /Q @test") if os.path.exists("@test"): raise def compareWithCPython( dirname, filename, extra_flags, search_mode, needs_2to3, on_error=None ): """Call the comparison tool. For a given directory filename. The search mode decides if the test case aborts on error or gets extra flags that are exceptions. """ # Many cases to consider here, pylint: disable=too-many-branches if dirname is None: path = filename else: path = os.path.join(dirname, filename) # Apply 2to3 conversion if necessary. if needs_2to3: path, converted = convertUsing2to3(path) else: converted = False if os.getenv("NUITKA_TEST_INSTALLED", "") == "1": command = [ sys.executable, "-m", "nuitka.tools.testing.compare_with_cpython", path, "silent", ] else: compare_with_cpython = os.path.join("..", "..", "bin", "compare_with_cpython") if os.path.exists(compare_with_cpython): command = [sys.executable, compare_with_cpython, path, "silent"] else: test_logger.sysexit("Error, cannot locate Nuitka comparison runner.") if extra_flags is not None: command += extra_flags command += search_mode.getExtraFlags(dirname, filename) # Cleanup before and after test stage directory. _removeCPythonTestSuiteDir() try: result = subprocess.call(command) except KeyboardInterrupt: result = 2 # Cleanup before and after test stage directory. _removeCPythonTestSuiteDir() if result != 0 and result != 2 and search_mode.abortOnFinding(dirname, filename): if on_error is not None: on_error(dirname, filename) search_mode.onErrorDetected("Error exit! %s" % result) if converted: os.unlink(path) if result == 2: test_logger.sysexit("Interrupted, with CTRL-C\n", exit_code=2) def checkCompilesNotWithCPython(dirname, filename, search_mode): if dirname is None: path = filename else: path = os.path.join(dirname, filename) command = [_python_executable, "-mcompileall", path] try: result = subprocess.call(command) except KeyboardInterrupt: result = 2 if result != 1 and result != 2 and search_mode.abortOnFinding(dirname, filename): search_mode.onErrorDetected("Error exit! %s" % result) def checkSucceedsWithCPython(filename): command = [_python_executable, filename] result = subprocess.call(command, stdout=getNullOutput(), stderr=subprocess.STDOUT) return result == 0 def hasDebugPython(): # On Debian systems, these work. debug_python = os.path.join("/usr/bin/", os.environ["PYTHON"] + "-dbg") if os.path.exists(debug_python): return True # On Windows systems, these work. debug_python = os.environ["PYTHON"] if debug_python.lower().endswith(".exe"): debug_python = debug_python[:-4] debug_python = debug_python + "_d.exe" if os.path.exists(debug_python): return True # For other Python, if it's the one also executing the runner, which is # very probably the case, we check that. We don't check the provided # binary here, this could be done as well. if sys.executable == os.environ["PYTHON"] and hasattr(sys, "gettotalrefcount"): return True # Otherwise no. return False def displayRuntimeTraces(logger, path): if not os.path.exists(path): # TODO: Have a logger package passed. logger.sysexit("Error, cannot find %r (%r)." % (path, os.path.abspath(path))) path = os.path.abspath(path) # TODO: Merge code for building command with below function, this is otherwise # horribly bad. if os.name == "posix": # Run with traces to help debugging, specifically in CI environment. if getOS() in ("Darwin", "FreeBSD"): test_logger.info("dtruss:") os.system("sudo dtruss %s" % path) else: test_logger.info("strace:") os.system("strace -s4096 -e file %s" % path) def hasModule(module_name): result = subprocess.call( (os.environ["PYTHON"], "-c", "import %s" % module_name), stdout=getNullOutput(), stderr=subprocess.STDOUT, ) return result == 0 m1 = {} m2 = {} def cleanObjRefCntMaps(): m1.clear() m2.clear() # Warm out repr for x in gc.get_objects(): try: str(x) except Exception: # Catch all the things, pylint: disable=broad-except pass def snapObjRefCntMap(before): # Inherently complex, pylint: disable=too-many-branches if before: m = m1 else: m = m2 m.clear() gc.collect() for x in gc.get_objects(): # The dictionary is cyclic, and contains itself, avoid that. if x is m1 or x is m2: continue if type(x) is str and (x in m1 or x in m2): continue if type(x) is not str and isinstance(x, str): k = "str_overload_" + x.__class__.__name__ + str(x) elif type(x) is dict: if "__builtins__" in x: k = "" % x["__name__"] elif "__spec__" in x and "__name__" in x: k = "" % x["__name__"] else: k = str(x) elif x.__class__.__name__ == "compiled_frame": k = " 0 result = False for count in range(max_rounds): if explain and count == max_rounds - 1: snapObjRefCntMap(before=True) ref_count1 = getTotalReferenceCount() checked_function() ref_count2 = getTotalReferenceCount() # Not allowed, but happens when bugs occur. assert sys.exc_info() == (None, None, None), sys.exc_info() if ref_count1 == ref_count2: result = True break if explain and count == max_rounds - 1: snapObjRefCntMap(before=False) reenablePrinting() if result: my_print("PASSED") else: my_print( "FAILED %d %d leaked %d" % (ref_count1, ref_count2, ref_count2 - ref_count1) ) if explain: print("REPORT of differences:") assert m1 assert m2 # Using items will unwanted usages, pylint: disable=consider-using-dict-items for key in m1: if key not in m2: my_print("*" * 80) my_print("extra:", m1[key], key) elif m1[key] != m2[key]: my_print("*" * 80) my_print(m1[key], "->", m2[key], key) else: pass for key in m2: if key not in m1: my_print("*" * 80) my_print("missing:", m2[key], key) # print m1[key] assert sys.exc_info() == (None, None, None), sys.exc_info() gc.collect() sys.stdout.flush() return result def createSearchMode(): # Dealing with many options, pylint: disable=too-many-branches parser = OptionParser() select_group = OptionGroup(parser, "Select Tests") select_group.add_option( "--pattern", action="store", dest="pattern", default="", help="""\ Execute only tests matching the pattern. Defaults to all tests.""", ) select_group.add_option( "--all", action="store_true", dest="all", default=False, help="""\ Execute all tests, continue execution even after failure of one.""", ) parser.add_option_group(select_group) debug_group = OptionGroup(parser, "Test features") debug_group.add_option( "--debug", action="store_true", dest="debug", default=False, help="""\ Executing all self checks possible to find errors in Nuitka, good for test coverage. Defaults to off.""", ) debug_group.add_option( "--commands", action="store_true", dest="show_commands", default=False, help="""Output commands being done in output comparison. Defaults to off.""", ) parser.add_option_group(debug_group) options, positional_args = parser.parse_args() if options.debug: addExtendedExtraOptions("--debug") if options.show_commands: os.environ["NUITKA_TRACE_COMMANDS"] = "1" # Default to searching. mode = positional_args[0] if positional_args else "search" # Avoid having to use options style. if mode in ("search", "only"): if len(positional_args) >= 2 and not options.pattern: options.pattern = positional_args[1] if mode == "search": if options.all: return SearchModeAll() elif options.pattern: pattern = options.pattern.replace("/", os.path.sep) return SearchModeByPattern(pattern) else: return SearchModeImmediate() elif mode == "resume": return SearchModeResume(sys.modules["__main__"].__file__) elif mode == "only": if options.pattern: pattern = options.pattern.replace("/", os.path.sep) return SearchModeOnly(pattern) else: assert False elif mode == "coverage": return SearchModeCoverage() else: test_logger.sysexit("Error, using unknown search mode %r" % mode) def reportSkip(reason, dirname, filename): case = os.path.join(dirname, filename) case = os.path.normpath(case) my_print("Skipped, %s (%s)." % (case, reason)) def executeReferenceChecked(prefix, names, tests_skipped, tests_stderr, explain=False): gc.disable() extract_number = lambda name: int(name.replace(prefix, "")) # Find the function names. matching_names = tuple( name for name in names if name.startswith(prefix) and name[-1].isdigit() ) old_stderr = sys.stderr # Everything passed result = True for name in sorted(matching_names, key=extract_number): number = extract_number(name) # print(tests_skipped) if number in tests_skipped: my_print(name + ": SKIPPED (%s)" % tests_skipped[number]) continue # Avoid unraisable output. try: if number in tests_stderr: sys.stderr = getNullOutput() except OSError: # Windows if not checkReferenceCount(names[name], explain=explain): result = False else: if not checkReferenceCount(names[name], explain=explain): result = False if number in tests_stderr: new_stderr = sys.stderr sys.stderr = old_stderr new_stderr.close() gc.enable() return result def addToPythonPath(python_path, in_front=False): if type(python_path) in (tuple, list): python_path = os.pathsep.join(python_path) if python_path: if "PYTHONPATH" in os.environ: if in_front: os.environ["PYTHONPATH"] = ( python_path + os.pathsep + os.environ["PYTHONPATH"] ) else: os.environ["PYTHONPATH"] += os.pathsep + python_path else: os.environ["PYTHONPATH"] = python_path @contextmanager def withPythonPathChange(python_path): if python_path: if type(python_path) not in (tuple, list): python_path = python_path.split(os.pathsep) python_path = [ os.path.normpath(os.path.abspath(element)) for element in python_path ] python_path = os.pathsep.join(python_path) if "PYTHONPATH" in os.environ: old_path = os.environ["PYTHONPATH"] os.environ["PYTHONPATH"] += os.pathsep + python_path else: old_path = None os.environ["PYTHONPATH"] = python_path yield if python_path: if old_path is None: del os.environ["PYTHONPATH"] else: os.environ["PYTHONPATH"] = old_path def addExtendedExtraOptions(*args): old_value = os.environ.get("NUITKA_EXTRA_OPTIONS") value = old_value for arg in args: if value is None: value = arg else: value += " " + arg os.environ["NUITKA_EXTRA_OPTIONS"] = value return old_value @contextmanager def withExtendedExtraOptions(*args): assert args old_value = addExtendedExtraOptions(*args) yield if old_value is None: del os.environ["NUITKA_EXTRA_OPTIONS"] else: os.environ["NUITKA_EXTRA_OPTIONS"] = old_value def indentedCode(codes, count): """Indent code, used for generating test codes.""" return "\n".join(" " * count + line if line else "" for line in codes) def convertToPython(doctests, line_filter=None): """Convert give doctest string to static Python code.""" # This is convoluted, but it just needs to work, pylint: disable=too-many-branches import doctest code = doctest.script_from_examples(doctests) if code.endswith("\n"): code += "#\n" else: assert False output = [] inside = False def getPrintPrefixed(evaluated, line_number): try: node = ast.parse(evaluated.lstrip(), "eval") except SyntaxError: return evaluated if node.body[0].__class__.__name__ == "Expr": count = 0 while evaluated.startswith(" " * count): count += 1 if sys.version_info < (3,): modified = (count - 1) * " " + "print " + evaluated return ( (count - 1) * " " + ("print 'Line %d'" % line_number) + "\n" + modified ) else: modified = (count - 1) * " " + "print(" + evaluated + "\n)\n" return ( (count - 1) * " " + ("print('Line %d'" % line_number) + ")\n" + modified ) else: return evaluated def getTried(evaluated, line_number): if sys.version_info < (3,): return """ try: %(evaluated)s except Exception as __e: print "Occurred", type(__e), __e """ % { "evaluated": indentedCode( getPrintPrefixed(evaluated, line_number).split("\n"), 4 ) } else: return """ try: %(evaluated)s except Exception as __e: print("Occurred", type(__e), __e) """ % { "evaluated": indentedCode( getPrintPrefixed(evaluated, line_number).split("\n"), 4 ) } def isOpener(evaluated): evaluated = evaluated.lstrip() if evaluated == "": return False return evaluated.split()[0] in ( "def", "with", "class", "for", "while", "try:", "except", "except:", "finally:", "else:", ) chunk = None for line_number, line in enumerate(code.split("\n")): # print "->", inside, line if line_filter is not None and line_filter(line): continue if inside and line and line[0].isalnum() and not isOpener(line): output.append(getTried("\n".join(chunk), line_number)) chunk = [] inside = False if inside and not (line.startswith("#") and line.find("SyntaxError:") != -1): chunk.append(line) elif line.startswith("#"): if line.find("SyntaxError:") != -1: # print "Syntax error detected" if inside: # print "Dropping chunk", chunk chunk = [] inside = False else: del output[-1] elif isOpener(line): inside = True chunk = [line] elif line.strip() == "": output.append(line) else: output.append(getTried(line, line_number)) return "\n".join(output).rstrip() + "\n" def compileLibraryPath(search_mode, path, stage_dir, decide, action): my_print("Checking standard library path:", path) for root, dirnames, filenames in os.walk(path): dirnames_to_remove = [dirname for dirname in dirnames if "-" in dirname] for dirname in dirnames_to_remove: dirnames.remove(dirname) dirnames.sort() filenames = [filename for filename in filenames if decide(root, filename)] for filename in sorted(filenames): if not search_mode.consider(root, filename): continue full_path = os.path.join(root, filename) my_print(full_path, ":", end=" ") sys.stdout.flush() action(stage_dir, path, full_path) def compileLibraryTest(search_mode, stage_dir, decide, action): if not os.path.exists(stage_dir): os.makedirs(stage_dir) my_dirname = os.path.join(os.path.dirname(__file__), "../../..") my_dirname = os.path.normpath(my_dirname) paths = [path for path in sys.path if not path.startswith(my_dirname)] my_print("Using standard library paths:") for path in paths: my_print(path) for path in paths: print("Checking path:", path) compileLibraryPath( search_mode=search_mode, path=path, stage_dir=stage_dir, decide=decide, action=action, ) search_mode.finish() def run_async(coro): """Execute a coroutine until it's done.""" values = [] result = None while True: try: values.append(coro.send(None)) except StopIteration as ex: result = ex.args[0] if ex.args else None break return values, result def async_iterate(g): """Execute async generator until it's done.""" # Test code for Python3, catches all kinds of exceptions. # pylint: disable=broad-except # Also Python3 only, pylint: disable=I0021,undefined-variable res = [] while True: try: g.__anext__().__next__() except StopAsyncIteration: res.append("STOP") break except StopIteration as ex: if ex.args: res.append("ex arg %s" % ex.args[0]) else: res.append("EMPTY StopIteration") break except Exception as ex: res.append(str(type(ex))) return res def getTestingCacheDir(): cache_dir = getCacheDir() result = os.path.join(cache_dir, "tests_state") makePath(result) return result def getTestingCPythonOutputsCacheDir(): cache_dir = getCacheDir() result = os.path.join( cache_dir, "cpython_outputs", os.environ.get("NUITKA_TEST_SUITE", "") ) makePath(result) return result def scanDirectoryForTestCases(dirname, template_context=None): filenames = os.listdir(dirname) filenames = [ filename for filename in filenames if (filename.endswith(".py") and not filename + ".j2" in filenames) or filename.endswith(".j2") ] for filename in sorted(filenames): if not decideFilenameVersionSkip(filename): continue if filename.endswith(".j2"): # Needs to be a dictionary with template arguments. assert template_context is not None template = getTemplate( package_name=None, template_name=filename, template_subdir=dirname ) code = template.render(name=template.name, **template_context) filename = filename[:-3] with openTextFile(filename, "w") as output: output.write( "'''Automatically generated test, not part of releases or git.\n\n'''\n" ) output.write(code) yield filename def scanDirectoryForTestCaseFolders(dirname): filenames = os.listdir(dirname) for filename in sorted(filenames): filename = os.path.join(dirname, filename) filename = os.path.relpath(filename) if ( not os.path.isdir(filename) or filename.endswith(".build") or filename.endswith(".dist") ): continue filename_main = getMainProgramFilename(filename) yield filename, filename_main def setupCacheHashSalt(test_code_path): assert os.path.exists(test_code_path) if os.path.exists(os.path.join(test_code_path, ".git")): git_cmd = ["git", "ls-tree", "-r", "HEAD", test_code_path] process = subprocess.Popen( args=git_cmd, stdin=getNullInput(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout_git, stderr_git = process.communicate() assert process.returncode == 0, stderr_git salt_value = hashlib.md5(stdout_git) else: salt_value = hashlib.md5() for filename in getFileList(test_code_path): if filename.endswith(".py"): salt_value.update(getFileContents(filename, mode="rb")) os.environ["NUITKA_HASH_SALT"] = salt_value.hexdigest() def displayFolderContents(name, path): test_logger.info("Listing of %s %r:" % (name, path)) if os.path.exists(path): if os.name == "nt": command = "dir /b /s /a:-D %s" % path else: command = "ls -Rla %s" % path os.system(command) else: test_logger.info("Does not exist.") def displayFileContents(name, path): test_logger.info("Contents of %s %r:" % (name, path)) if os.path.exists(path): for line in getFileContentByLine(path): my_print(line) else: test_logger.info("Does not exist.") def someGenerator(): yield 1 yield 2 yield 3 def someGeneratorRaising(): yield 1 raise TypeError(2) # checks requirements needed to run each test module, according to the specified special comment # special comments are in the following formats: # "# nuitka-skip-unless-expression: expression to be evaluated" # OR # "# nuitka-skip-unless-imports: module1,module2,..." def checkRequirements(filename): for line in readSourceCodeFromFilename(None, filename).splitlines(): if line.startswith("# nuitka-skip-unless-"): if line[21:33] == "expression: ": expression = line[33:] result = subprocess.call( ( os.environ["PYTHON"], "-c", "import sys, os; sys.exit(not bool(%s))" % expression, ), stdout=getNullOutput(), stderr=subprocess.STDOUT, ) if result != 0: return (False, "Expression '%s' evaluated to false" % expression) elif line[21:30] == "imports: ": imports_needed = line[30:].rstrip().split(",") for i in imports_needed: if not hasModule(i): return ( False, i + " not installed for this Python version, but test needs it", ) # default return value return (True, "") class DelayedExecutionThread(threading.Thread): def __init__(self, timeout, func): threading.Thread.__init__(self) self.timeout = timeout self.func = func def run(self): time.sleep(self.timeout) self.func() def executeAfterTimePassed(timeout, func): alarm = DelayedExecutionThread(timeout=timeout, func=func) alarm.start() def killProcess(name, pid): """Kill a process in a portable way. Right now SIGINT is used, unclear what to do on Windows with Python2 or non-related processes. """ if str is bytes and os.name == "nt": test_logger.info("Using taskkill on test process %r." % name) os.system("taskkill.exe /PID %d" % pid) else: test_logger.info("Killing test process %r." % name) os.kill(pid, signal.SIGINT) def checkLoadedFileAccesses(loaded_filenames, current_dir): # Many details to consider, pylint: disable=too-many-branches,too-many-statements current_dir = os.path.normpath(current_dir) current_dir = os.path.normcase(current_dir) current_dir_ext = os.path.normcase(getExternalUsePath(current_dir)) illegal_accesses = [] for loaded_filename in loaded_filenames: orig_loaded_filename = loaded_filename loaded_filename = os.path.normpath(loaded_filename) loaded_filename = os.path.normcase(loaded_filename) loaded_basename = os.path.basename(loaded_filename) if os.name == "nt": if areSamePaths( os.path.dirname(loaded_filename), os.path.normpath(os.path.join(os.environ["SYSTEMROOT"], "System32")), ): continue if areSamePaths( os.path.dirname(loaded_filename), os.path.normpath(os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")), ): continue if r"windows\winsxs" in loaded_filename: continue # Github actions have these in PATH overriding SYSTEMROOT if r"windows performance toolkit" in loaded_filename: continue if r"powershell" in loaded_filename: continue if r"azure dev spaces cli" in loaded_filename: continue if r"tortoisesvn" in loaded_filename: continue if loaded_filename.startswith(current_dir): continue if loaded_filename.startswith(os.path.abspath(current_dir)): continue if loaded_filename.startswith(current_dir_ext): continue ignore = True for ignored_dir in ( # System configuration is OK "/etc", "/usr/etc", "/usr/local/etc", # Runtime user state and kernel information is OK. "/proc", "/dev", "/run", "/sys", "/tmp", "/var", # Locals may of course be loaded. "/usr/lib/locale", "/usr/share/locale", "/usr/share/X11/locale", # Themes may of course be loaded. "/usr/share/themes", # Terminal info files are OK too. "/lib/terminfo", ): if isPathBelowOrSameAs(ignored_dir, loaded_filename): ignore = False break if not ignore: continue # Themes may of course be loaded. if loaded_filename.startswith("/usr/share/themes"): continue if "gtk" in loaded_filename and "/engines/" in loaded_filename: continue if loaded_filename in ( "/usr", "/usr/local", "/usr/local/lib", "/usr/share", "/usr/local/share", "/usr/lib64", ): continue # TCL/tk for tkinter for non-Windows is OK. if loaded_filename.startswith( ( "/usr/lib/tcltk/", "/usr/share/tcltk/", "/usr/lib/tcl/", "/usr/lib64/tcl/", ) ): continue if loaded_filename in ( "/usr/lib/tcltk", "/usr/share/tcltk", "/usr/lib/tcl", "/usr/lib64/tcl", ): continue if loaded_filename in ( "/lib", "/lib64", "/lib/sse2", "/lib/tls", "/lib64/tls", "/usr/lib/sse2", "/usr/lib/tls", "/usr/lib64/tls", ): continue if loaded_filename in ("/usr/share/tcl8.6", "/usr/share/tcl8.5"): continue if loaded_filename in ( "/usr/share/tcl8.6/init.tcl", "/usr/share/tcl8.5/init.tcl", ): continue if loaded_filename in ( "/usr/share/tcl8.6/encoding", "/usr/share/tcl8.5/encoding", ): continue # System SSL config on Linux. TODO: Should this not be included and # read from dist folder. if loaded_basename == "openssl.cnf": continue # Taking these from system is harmless and desirable if loaded_basename.startswith(("libz.so", "libgcc_s.so")): continue # System C libraries are to be expected. if loaded_basename.startswith( ( "ld-linux-x86-64.so", "libc.so.", "libpthread.so.", "libm.so.", "libdl.so.", "libBrokenLocale.so.", "libSegFault.so", "libanl.so.", "libcidn.so.", "libcrypt.so.", "libmemusage.so", "libmvec.so.", "libnsl.so.", "libnss_compat.so.", "libnss_db.so.", "libnss_dns.so.", "libnss_files.so.", "libnss_hesiod.so.", "libnss_nis.so.", "libnss_nisplus.so.", "libpcprofile.so", "libresolv.so.", "librt.so.", "libthread_db-1.0.so", "libthread_db.so.", "libutil.so.", ) ): continue # System C++ standard library is also OK. if loaded_basename.startswith("libstdc++."): continue # Curses library is OK from system too. if loaded_basename.startswith("libtinfo.so."): continue # Loaded by C library potentially for DNS lookups. if loaded_basename.startswith( ( "libnss_", "libnsl", # Some systems load a lot more, this is CentOS 7 on OBS "libattr.so.", "libbz2.so.", "libcap.so.", "libdw.so.", "libelf.so.", "liblzma.so.", # Some systems load a lot more, this is Fedora 26 on OBS "libselinux.so.", "libpcre.so.", # And this is Fedora 29 on OBS "libblkid.so.", "libmount.so.", "libpcre2-8.so.", # CentOS 8 on OBS "libuuid.so.", ) ): continue # Loaded by dtruss on macOS X. if loaded_filename.startswith("/usr/lib/dtrace/"): continue # Loaded by cowbuilder and pbuilder on Debian if loaded_basename == ".ilist": continue if "cowdancer" in loaded_filename: continue if "eatmydata" in loaded_filename: continue # Loading from home directories is OK too. if ( loaded_filename.startswith("/home/") or loaded_filename.startswith("/data/") or loaded_filename.startswith("/root/") or loaded_filename in ("/home", "/data", "/root") ): continue # For Debian builders, /build is OK too. if loaded_filename.startswith("/build/") or loaded_filename == "/build": continue # TODO: Unclear, loading gconv from filesystem of installed system # may be OK or not. I think it should be. if loaded_basename == "gconv-modules.cache": continue if "/gconv/" in loaded_filename: continue if loaded_basename.startswith("libicu"): continue if loaded_filename.startswith("/usr/share/icu/"): continue # Loading from caches is OK. if loaded_filename.startswith("/var/cache/"): continue # At least Python3.7 considers the default Python3 path and checks it. if loaded_filename == "/usr/bin/python3": continue # Accessing the versioned Python3.x binary is also happening. if loaded_filename in ( "/usr/bin/python3." + version for version in ("5", "6", "7", "8", "9", "10") ): continue binary_path = _python_executable found = False while binary_path: if loaded_filename == binary_path: found = True break if binary_path == os.path.dirname(binary_path): break binary_path = os.path.dirname(binary_path) if loaded_filename == os.path.join( binary_path, "python" + ("%d%d" % (_python_version[0], _python_version[1])), ): found = True break if found: continue lib_prefix_dir = "/usr/lib/python%d.%s" % ( _python_version[0], _python_version[1], ) # PySide accesses its directory. if loaded_filename == os.path.join(lib_prefix_dir, "dist-packages/PySide"): continue # GTK accesses package directories only. if loaded_filename == os.path.join(lib_prefix_dir, "dist-packages/gtk-2.0/gtk"): continue if loaded_filename == os.path.join(lib_prefix_dir, "dist-packages/glib"): continue if loaded_filename == os.path.join(lib_prefix_dir, "dist-packages/gtk-2.0/gio"): continue if loaded_filename == os.path.join(lib_prefix_dir, "dist-packages/gobject"): continue # PyQt5 and PySide6 seems to do this, but won't use contents then. if loaded_filename in ( "/usr/lib/qt6/plugins", "/usr/lib/qt6", "/usr/lib64/qt6/plugins", "/usr/lib64/qt6", "/usr/lib/qt5/plugins", "/usr/lib/qt5", "/usr/lib64/qt5/plugins", "/usr/lib64/qt5", "/usr/lib/x86_64-linux-gnu/qt5/plugins", "/usr/lib/x86_64-linux-gnu/qt5", "/usr/lib/x86_64-linux-gnu", "/usr/lib", ): continue # Can look at the interpreters of the system. if loaded_basename in "python3": continue if loaded_basename in ( "python%s" + supported_version for supported_version in ( getSupportedPythonVersions() + getPartiallySupportedPythonVersions() ) ): continue # Current Python executable can actually be a symlink and # the real executable which it points to will be on the # loaded_filenames list. This is all fine, let's ignore it. # Also, because the loaded_filename can be yet another symlink # (this is weird, but it's true), let's better resolve its real # path too. if os.path.realpath(loaded_filename) == os.path.realpath(sys.executable): continue # Accessing SE-Linux is OK. if loaded_filename in ("/sys/fs/selinux", "/selinux"): continue # Looking at device is OK. if loaded_filename.startswith("/sys/devices/"): continue # Allow reading time zone info of local system. if loaded_filename.startswith("/usr/share/zoneinfo/"): continue # The access to .pth files has no effect. if loaded_filename.endswith(".pth"): continue # Looking at site-package dir alone is alone. if loaded_filename.endswith(("site-packages", "dist-packages")): continue # QtNetwork insist on doing this it seems. if loaded_basename.startswith(("libcrypto.so", "libssl.so")): continue # macOS uses these: if loaded_basename in ( "libcrypto.1.0.0.dylib", "libssl.1.0.0.dylib", "libcrypto.1.1.dylib", ): continue # Linux onefile uses this if loaded_basename.startswith("libfuse.so."): continue # MSVC run time DLLs, due to SxS come from system. if loaded_basename.upper() in ("MSVCRT.DLL", "MSVCR90.DLL"): continue illegal_accesses.append(orig_loaded_filename) return illegal_accesses def getMainProgramFilename(filename): for filename_main in os.listdir(filename): if filename_main.endswith(("Main.py", "Main")): return filename_main test_logger.sysexit( """\ Error, no file ends with 'Main.py' or 'Main' in '%s', incomplete test case.""" % (filename) ) Nuitka-0.6.19.1/nuitka/tools/testing/check_reference_counts/0000700000372100037210000000000014167275622031071 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/check_reference_counts/__main__.py0000600000372100037210000000573114166627112033165 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tool to compare reference counting behaviour of CPython and Nuitka. """ import os import sys from optparse import OptionParser from nuitka.tools.testing.Common import checkReferenceCount, getTempDir from nuitka.Tracing import my_print from nuitka.utils.Execution import check_call from nuitka.utils.Importing import importFileAsModule def main(): parser = OptionParser() parser.add_option( "--checked-module", action="store", dest="checked_module", help="""\ Module with main() function to be checked for reference count stability.""", ) parser.add_option( "--explain", action="store_true", dest="explain", default=False, help="""\ Try to explain the differences by comparing object counts.""", ) options, positional_args = parser.parse_args() if positional_args and options.checked_module is None: options.checked_module = positional_args.pop() if positional_args and options.checked_module: parser.print_help() sys.exit("\nError, no positional argument allowed.") # First with pure Python. checked_module = importFileAsModule(options.checked_module) my_print("Using %s" % checked_module.main, style="blue") checkReferenceCount(checked_module.main, explain=options.explain) temp_dir = getTempDir() command = [ sys.executable, "-m", "nuitka", "--module", options.checked_module, "--output-dir=%s" % temp_dir, ] if hasattr(sys, "gettotalrefcount"): command.append("--python-debug") check_call(command) module_name = os.path.basename(options.checked_module).split(".")[0] sys.path.insert(0, temp_dir) checked_module = __import__(module_name) my_print("Using %s" % checked_module.main, style="blue") checkReferenceCount(checked_module.main) if __name__ == "__main__": nuitka_package_dir = os.path.normpath( os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")) ) # Unchanged, running from checkout, use the parent directory, the nuitka # package ought be there. sys.path.insert(0, nuitka_package_dir) main() Nuitka-0.6.19.1/nuitka/tools/testing/check_reference_counts/__init__.py0000600000372100037210000000150114166627112033173 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/run_nuitka_tests/0000700000372100037210000000000014167275622030004 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/testing/run_nuitka_tests/__main__.py0000700000372100037210000010411314166627112032073 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Main front-end to the tests of Nuitka. Has many options, read --help output. """ import os import subprocess import sys from optparse import OptionParser from nuitka.freezer.Onefile import checkOnefileReadiness from nuitka.tools.Basics import goHome from nuitka.tools.testing.Common import ( getTempDir, my_print, withExtendedExtraOptions, ) from nuitka.utils.Execution import ( check_call, check_output, getExecutablePath, getNullOutput, getPythonExePathWindows, ) from nuitka.utils.FileOperations import ( getFileContents, openTextFile, putTextFileContents, withDirectoryChange, ) from nuitka.utils.Timing import TimerReport from nuitka.utils.Utils import hasOnefileSupportedOS, hasStandaloneSupportedOS def parseOptions(): # There are freaking many options to honor, # pylint: disable=too-many-branches,too-many-statements parser = OptionParser() parser.add_option( "--skip-basic-tests", action="store_false", dest="basic_tests", default=True, help="""\ The basic tests, execute these to check if Nuitka is healthy. Default is %default.""", ) parser.add_option( "--skip-syntax-tests", action="store_false", dest="syntax_tests", default=True, help="""\ The syntax tests, execute these to check if Nuitka handles Syntax errors fine. Default is %default.""", ) parser.add_option( "--skip-program-tests", action="store_false", dest="program_tests", default=True, help="""\ The programs tests, execute these to check if Nuitka handles programs, e.g. import recursions, etc. fine. Default is %default.""", ) parser.add_option( "--skip-package-tests", action="store_false", dest="package_tests", default=True, help="""\ The packages tests, execute these to check if Nuitka handles packages, e.g. import recursions, etc. fine. Default is %default.""", ) parser.add_option( "--skip-plugins-tests", action="store_false", dest="plugin_tests", default=True, help="""\ The plugins tests, execute these to check if Nuitka handles its own plugin interfaces, e.g. user plugins, etc. fine. Default is %default.""", ) parser.add_option( "--skip-optimizations-tests", action="store_false", dest="optimization_tests", default=True, help="""\ The optimization tests, execute these to check if Nuitka does optimize certain constructs fully away. Default is %default.""", ) parser.add_option( "--skip-standalone-tests", action="store_false", dest="standalone_tests", default=hasStandaloneSupportedOS(), help="""\ The standalone tests, execute these to check if Nuitka standalone mode, e.g. not referring to outside, important 3rd library packages like PyQt fine. Default is %default.""", ) parser.add_option( "--skip-onefile-tests", action="store_false", dest="onefile_tests", default=hasOnefileSupportedOS(), help="""\ The onefile tests, execute these to check if Nuitka works in onefile mode, e.g. not referring to outside, important 3rd library packages like PyQt fine. Default is %default.""", ) parser.add_option( "--skip-reflection-test", action="store_false", dest="reflection_test", default=True, help="""\ The reflection test compiles Nuitka with Nuitka, and then Nuitka with the compile Nuitka and compares the outputs. Default is %default.""", ) parser.add_option( "--skip-cpython26-tests", action="store_false", dest="cpython26", default=True, help="""\ The standard CPython2.6 test suite. Execute this for all corner cases to be covered. With Python 2.7 this covers exception behavior quite well. Default is %default.""", ) parser.add_option( "--skip-cpython27-tests", action="store_false", dest="cpython27", default=True, help="""\ The standard CPython2.7 test suite. Execute this for all corner cases to be covered. With Python 2.6 these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython32-tests", action="store_false", dest="cpython32", default=True, help="""\ The standard CPython3.2 test suite. Execute this for all corner cases to be covered. With Python 2.6 these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython33-tests", action="store_false", dest="cpython33", default=True, help="""\ The standard CPython3.3 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython34-tests", action="store_false", dest="cpython34", default=True, help="""\ The standard CPython3.4 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython35-tests", action="store_false", dest="cpython35", default=True, help="""\ The standard CPython3.5 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython36-tests", action="store_false", dest="cpython36", default=True, help="""\ The standard CPython3.6 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython37-tests", action="store_false", dest="cpython37", default=True, help="""\ The standard CPython3.7 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython38-tests", action="store_false", dest="cpython38", default=True, help="""\ The standard CPython3.8 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython39-tests", action="store_false", dest="cpython39", default=True, help="""\ The standard CPython3.9 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-cpython310-tests", action="store_false", dest="cpython310", default=True, help="""\ The standard CPython3.10 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is %default.""", ) parser.add_option( "--skip-other-cpython-tests", action="store_true", dest="cpython_no_other", default=False, help="""\ Do not execute any CPython test suite other than the one matching the running Python. Default is %default.""", ) parser.add_option( "--skip-all-cpython-tests", action="store_true", dest="cpython_none", default=False, help="""\ Do not execute any CPython test suite other than the one matching the running Python. Default is %default.""", ) parser.add_option( "--no-other-python", action="store_true", dest="no_other", default=False, help="""\ Do not use any other Python than the one running, even if available on the system. Default is %default.""", ) parser.add_option( "--no-python2.6", action="store_true", dest="no26", default=False, help="""\ Do not use Python2.6 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python2.7", action="store_true", dest="no27", default=False, help="""\ Do not use Python2.7 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.3", action="store_true", dest="no33", default=False, help="""\ Do not use Python3.3 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.4", action="store_true", dest="no34", default=False, help="""\ Do not use Python3.4 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.5", action="store_true", dest="no35", default=False, help="""\ Do not use Python3.5 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.6", action="store_true", dest="no36", default=False, help="""\ Do not use Python3.6 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.7", action="store_true", dest="no37", default=False, help="""\ Do not use Python3.7 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.8", action="store_true", dest="no38", default=False, help="""\ Do not use Python3.8 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.9", action="store_true", dest="no39", default=False, help="""\ Do not use Python3.9 even if available on the system. Default is %default.""", ) parser.add_option( "--no-python3.10", action="store_true", dest="no310", default=False, help="""\ Do not use Python3.10 even if available on the system. Default is %default.""", ) parser.add_option( "--coverage", action="store_true", dest="coverage", default=False, help="""\ Make a coverage analysis, that does not really check. Default is %default.""", ) parser.add_option( "--no-debug", action="store_false", dest="debug", default=True, help="""\ Make a coverage analysis, that does not really check. Default is %default.""", ) parser.add_option( "--assume-yes-for-downloads", action="store_true", dest="assume_yes_for_downloads", default=False, help="""\ Allow Nuitka to download code if necessary, e.g. dependency walker on Windows. Default is %default.""", ) parser.add_option( "--mingw64", action="store_true", dest="mingw64", default=False, help="""\ Enforce the use of MinGW64 on Windows. Defaults to off.""", ) options, positional_args = parser.parse_args() if positional_args: parser.print_help() sys.exit("\nError, no positional argument allowed.") if options.no_other: if sys.version_info[0:2] != (2, 6): options.no26 = True if sys.version_info[0:2] != (2, 7): options.no27 = True if sys.version_info[0:2] != (3, 3): options.no33 = True if sys.version_info[0:2] != (3, 4): options.no34 = True if sys.version_info[0:2] != (3, 5): options.no35 = True if sys.version_info[0:2] != (3, 6): options.no36 = True if sys.version_info[0:2] != (3, 7): options.no37 = True if sys.version_info[0:2] != (3, 8): options.no38 = True if sys.version_info[0:2] != (3, 9): options.no39 = True if sys.version_info[0:2] != (3, 10): options.no310 = True if options.cpython_no_other: if sys.version_info[0:2] != (2, 6): options.cpython26 = False if sys.version_info[0:2] != (2, 7): options.cpython27 = False if sys.version_info[0:2] != (3, 2): options.cpython32 = False if sys.version_info[0:2] != (3, 3): options.cpython33 = False if sys.version_info[0:2] != (3, 4): options.cpython34 = False if sys.version_info[0:2] != (3, 5): options.cpython35 = False if sys.version_info[0:2] != (3, 6): options.cpython36 = False if sys.version_info[0:2] != (3, 7): options.cpython37 = False if sys.version_info[0:2] != (3, 8): options.cpython38 = False if sys.version_info[0:2] != (3, 9): options.cpython39 = False if sys.version_info[0:2] != (3, 10): options.cpython310 = False if options.cpython_none: options.cpython26 = False options.cpython27 = False options.cpython32 = False options.cpython33 = False options.cpython34 = False options.cpython35 = False options.cpython36 = False options.cpython37 = False options.cpython38 = False options.cpython39 = False options.cpython310 = False if options.coverage and os.path.exists(".coverage"): os.unlink(".coverage") return options def publishCoverageData(): def copyToGlobalCoverageData(source, target): coverage_dir = os.environ.get("COVERAGE_DIR") if coverage_dir is None: return check_call(("scp", source, os.path.join(coverage_dir, target))) if os.name == "nt": suffix = "win" else: import platform suffix = platform.uname()[0] + "." + platform.uname()[4] with openTextFile("data.coverage", "w") as data_file: source_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) with withDirectoryChange(source_dir): nuitka_id = check_output("git rev-parse HEAD".split()) nuitka_id = nuitka_id.strip() if sys.version_info > (3,): nuitka_id = nuitka_id.decode() data_file.write("NUITKA_SOURCE_DIR=%r\n" % source_dir) data_file.write("NUITKA_COMMIT=%r\n" % nuitka_id) copyToGlobalCoverageData("data.coverage", "meta.coverage." + suffix) def makeCoverageRelative(filename): """Normalize coverage data.""" data = getFileContents(filename) data = data.replace( (os.path.abspath(".") + os.path.sep).replace("\\", "\\\\"), "" ) if os.path.sep != "/": data.replace(os.path.sep, "/") putTextFileContents(filename, contents=data) coverage_file = os.environ.get("COVERAGE_FILE", ".coverage") makeCoverageRelative(coverage_file) copyToGlobalCoverageData(coverage_file, "data.coverage." + suffix) def main(): # There are many cases to deal with, # pylint: disable=too-many-branches,too-many-statements # Lets honor this Debian option here. if "nocheck" in os.environ.get("DEB_BUILD_OPTIONS", "").split(): my_print("Skipped all tests as per DEB_BUILD_OPTIONS environment.") sys.exit(0) # Make sure our resolving of "python2" to "python" doesn't get in the way. os.environ["PYTHON_DISALLOW_AMBIGUOUS_VERSION"] = "0" goHome() options = parseOptions() # Add the local bin directory to search path start. os.environ["PATH"] = ( os.path.join(os.getcwd(), "bin") + os.pathsep + os.environ["PATH"] ) def checkExecutableCommand(command): """Check if a command is executable.""" # Many cases, pylint: disable=too-many-branches,too-many-return-statements # Do respect given options to disable specific Python versions if command == "python2.6" and options.no26: return False if command == "python2.7" and options.no27: return False if command == "python3.3" and options.no33: return False if command == "python3.4" and options.no34: return False if command == "python3.5" and options.no35: return False if command == "python3.6" and options.no36: return False if command == "python3.7" and options.no37: return False if command == "python3.8" and options.no38: return False if command == "python3.9" and options.no39: return False if command == "python3.10" and options.no310: return False # Shortcuts for python versions, also needed for Windows as it won't have # the version number in the Python binaries at all. if command == "python2.6" and sys.version_info[0:2] == (2, 6): return True if command == "python2.7" and sys.version_info[0:2] == (2, 7): return True if command == "python3.3" and sys.version_info[0:2] == (3, 3): return True if command == "python3.4" and sys.version_info[0:2] == (3, 4): return True if command == "python3.5" and sys.version_info[0:2] == (3, 5): return True if command == "python3.6" and sys.version_info[0:2] == (3, 6): return True if command == "python3.7" and sys.version_info[0:2] == (3, 7): return True if command == "python3.8" and sys.version_info[0:2] == (3, 8): return True if command == "python3.9" and sys.version_info[0:2] == (3, 9): return True if command == "python3.10" and sys.version_info[0:2] == (3, 10): return True path = os.environ["PATH"] suffixes = (".exe",) if os.name == "nt" else ("",) for part in path.split(os.pathsep): if not part: continue for suffix in suffixes: if os.path.exists(os.path.join(part, command + suffix)): return True if os.name == "nt": if command.startswith("python"): remainder = command[6:] if len(remainder) == 3 and remainder[1] == ".": command = getPythonExePathWindows(search=remainder, arch=None) return True return False def getExtraFlags(where, name, flags): if options.assume_yes_for_downloads and name in ("onefile", "standalone"): yield "--assume-yes-for-downloads" if os.name == "nt" and options.mingw64: yield "--mingw64" if where is not None: tmp_dir = getTempDir() where = os.path.join(tmp_dir, name, where) if not os.path.exists(where): os.makedirs(where) yield "--output-dir=%s" % where yield flags def executeSubTest(command, hide_output=False): with TimerReport( message="Overall execution of %r took %%.2f seconds" % command ): _executeSubTest(command, hide_output) def _executeSubTest(command, hide_output): if options.coverage and "search" in command: command = command.replace("search", "coverage") parts = command.split() parts[0] = parts[0].replace("/", os.path.sep) # The running Python will be good enough, on some platforms there is no # "python", and we need to pass this alone then. parts.insert(0, sys.executable) my_print("Run '%s' in '%s'." % (" ".join(parts), os.getcwd())) if hide_output: result = subprocess.call(parts, stdout=getNullOutput()) else: result = subprocess.call(parts) if result != 0: sys.exit(result) def execute_tests(where, use_python, flags): # Many cases, pylint: disable=too-many-branches,too-many-statements my_print( "Executing test case called '%s' with CPython '%s' and extra flags '%s'." % (where, use_python, flags) ) intended_version = use_python[6:] if sys.version.startswith(intended_version): os.environ["PYTHON"] = sys.executable else: if os.name == "nt": os.environ["PYTHON"] = getPythonExePathWindows( search=intended_version, arch=None ) else: os.environ["PYTHON"] = getExecutablePath(use_python) if options.basic_tests: my_print( "Running the basic tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(where, "basics", flags)): executeSubTest("./tests/basics/run_all.py search") if options.syntax_tests: my_print( "Running the syntax tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(where, "syntax", flags)): executeSubTest("./tests/syntax/run_all.py search") if options.program_tests: my_print( "Running the program tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(where, "programs", flags)): executeSubTest("./tests/programs/run_all.py search") if options.package_tests: my_print( "Running the package tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(where, "packages", flags)): executeSubTest("./tests/packages/run_all.py search") if options.plugin_tests: my_print( "Running the plugin tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(where, "plugins", flags)): executeSubTest("./tests/plugins/run_all.py search") # At least one Debian Jessie, these versions won't have lxml installed, so # don't run them there. Also these won't be very version dependent in their # results. if use_python != "python2.6": if options.optimization_tests: my_print( "Running the optimizations tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions( *getExtraFlags(where, "optimizations", flags) ): executeSubTest("./tests/optimizations/run_all.py search") if options.standalone_tests and not options.coverage: my_print( "Running the standalone tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(None, "standalone", flags)): executeSubTest("./tests/standalone/run_all.py search") if options.onefile_tests and not options.coverage: if checkOnefileReadiness( assume_yes_for_downloads=options.assume_yes_for_downloads ): my_print( "Running the onefile tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(None, "onefile", flags)): executeSubTest("./tests/onefile/run_all.py search") else: my_print("The onefile tests are not run due to missing requirements.") if options.reflection_test and not options.coverage: my_print( "Running the reflection test with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions(*getExtraFlags(None, "reflected", flags)): executeSubTest("./tests/reflected/compile_itself.py search") if not use_python.startswith("python3"): if os.path.exists("./tests/CPython26/run_all.py"): if options.cpython26: my_print( "Running the CPython 2.6 tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions( *getExtraFlags(where, "26tests", flags) ): executeSubTest("./tests/CPython26/run_all.py search") else: my_print("The CPython2.6 tests are not present, not run.") # Running the Python 2.7 test suite with CPython 2.6 gives little # insight, because "importlib" will not be there and that's it. if use_python != "python2.6": if os.path.exists("./tests/CPython27/run_all.py"): if options.cpython27: my_print( "Running the CPython 2.7 tests with options '%s' with '%s':" % (flags, use_python) ) with withExtendedExtraOptions( *getExtraFlags(where, "27tests", flags) ): executeSubTest("./tests/CPython27/run_all.py search") else: my_print("The CPython2.7 tests are not present, not run.") if "--debug" not in flags: # Not running the Python 3.2 test suite with CPython2.6, as that's about # the same as CPython2.7 and won't have any new insights. if use_python not in ("python2.6", "python2.7") or not options.coverage: if options.cpython32: if os.path.exists("./tests/CPython32/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "32tests", flags) ): executeSubTest("./tests/CPython32/run_all.py search") else: my_print("The CPython3.2 tests are not present, not run.") # Running the Python 3.3 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython33: if os.path.exists("./tests/CPython33/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "33tests", flags) ): executeSubTest("./tests/CPython33/run_all.py search") else: my_print("The CPython3.3 tests are not present, not run.") # Running the Python 3.4 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython34: if os.path.exists("./tests/CPython34/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "34tests", flags) ): executeSubTest("./tests/CPython34/run_all.py search") else: my_print("The CPython3.4 tests are not present, not run.") # Running the Python 3.5 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython35: if os.path.exists("./tests/CPython35/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "35tests", flags) ): executeSubTest("./tests/CPython35/run_all.py search") else: my_print("The CPython3.5 tests are not present, not run.") # Running the Python 3.6 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython36: if os.path.exists("./tests/CPython36/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "36tests", flags) ): executeSubTest("./tests/CPython36/run_all.py search") else: my_print("The CPython3.6 tests are not present, not run.") # Running the Python 3.7 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython37: if os.path.exists("./tests/CPython37/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "37tests", flags) ): executeSubTest("./tests/CPython37/run_all.py search") else: my_print("The CPython3.7 tests are not present, not run.") # Running the Python 3.8 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython38: if os.path.exists("./tests/CPython38/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "38tests", flags) ): executeSubTest("./tests/CPython38/run_all.py search") else: my_print("The CPython3.8 tests are not present, not run.") # Running the Python 3.9 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython39: if os.path.exists("./tests/CPython39/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "39tests", flags) ): executeSubTest("./tests/CPython39/run_all.py search") else: my_print("The CPython3.9 tests are not present, not run.") # Running the Python 3.10 test suite only with CPython3.x. if not use_python.startswith("python2"): if options.cpython310: if os.path.exists("./tests/CPython310/run_all.py"): with withExtendedExtraOptions( *getExtraFlags(where, "310tests", flags) ): executeSubTest("./tests/CPython310/run_all.py search") else: my_print("The CPython3.10 tests are not present, not run.") assert ( checkExecutableCommand("python2.6") or checkExecutableCommand("python2.7") or checkExecutableCommand("python3.3") or checkExecutableCommand("python3.4") or checkExecutableCommand("python3.5") or checkExecutableCommand("python3.6") or checkExecutableCommand("python3.7") or checkExecutableCommand("python3.8") or checkExecutableCommand("python3.9") or checkExecutableCommand("python3.10") ) if options.debug: if checkExecutableCommand("python2.6"): execute_tests("python2.6-debug", "python2.6", "--debug") else: my_print("Cannot execute tests with Python 2.6, disabled or not installed.") if checkExecutableCommand("python2.7"): execute_tests("python2.7-debug", "python2.7", "--debug") else: my_print("Cannot execute tests with Python 2.7, disabled or not installed.") if checkExecutableCommand("python2.6"): execute_tests("python2.6-nodebug", "python2.6", "") else: my_print("Cannot execute tests with Python 2.6, disabled or not installed.") if checkExecutableCommand("python2.7"): execute_tests("python2.7-nodebug", "python2.7", "") else: my_print("Cannot execute tests with Python 2.7, disabled or not installed.") if checkExecutableCommand("python3.3"): execute_tests("python3.3-nodebug", "python3.3", "") else: my_print("Cannot execute tests with Python 3.3, disabled or not installed.") if checkExecutableCommand("python3.4"): execute_tests("python3.4-nodebug", "python3.4", "") else: my_print("Cannot execute tests with Python 3.4, disabled or not installed.") if checkExecutableCommand("python3.5"): execute_tests("python3.5-nodebug", "python3.5", "") else: my_print("Cannot execute tests with Python 3.5, disabled or not installed.") if checkExecutableCommand("python3.6"): execute_tests("python3.6-nodebug", "python3.6", "") else: my_print("Cannot execute tests with Python 3.6, disabled or not installed.") if checkExecutableCommand("python3.7"): execute_tests("python3.7-nodebug", "python3.7", "") else: my_print("Cannot execute tests with Python 3.7, disabled or not installed.") if checkExecutableCommand("python3.8"): execute_tests("python3.8-nodebug", "python3.8", "") else: my_print("Cannot execute tests with Python 3.8, disabled or not installed.") if checkExecutableCommand("python3.9"): execute_tests("python3.9-nodebug", "python3.9", "") else: my_print("Cannot execute tests with Python 3.9, disabled or not installed.") if checkExecutableCommand("python3.10"): execute_tests("python3.10-nodebug", "python3.10", "") else: my_print("Cannot execute tests with Python 3.10, disabled or not installed.") if options.coverage: publishCoverageData() my_print("OK.") if __name__ == "__main__": main() Nuitka-0.6.19.1/nuitka/tools/testing/run_nuitka_tests/__init__.py0000600000372100037210000000150114166627112032106 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/testing/SearchModes.py0000600000372100037210000001303314166627112027146 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Search modes for Nuitka's test runner. The test runner can handle found errors, skip tests, etc. with search modes, which are implemented here. """ import hashlib import os import sys from nuitka.utils.FileOperations import ( areSamePaths, getFileContents, putTextFileContents, ) class SearchModeBase(object): def __init__(self): self.may_fail = [] def consider(self, dirname, filename): # Virtual method, pylint: disable=no-self-use,unused-argument return True def finish(self): pass def abortOnFinding(self, dirname, filename): for candidate in self.may_fail: if self._match(dirname, filename, candidate): return False return True def getExtraFlags(self, dirname, filename): # Virtual method, pylint: disable=no-self-use,unused-argument return [] def mayFailFor(self, *names): self.may_fail += names @classmethod def _match(cls, dirname, filename, candidate): parts = [dirname, filename] while None in parts: parts.remove(None) assert parts path = os.path.join(*parts) candidates = ( dirname, filename, filename.rsplit(".", 1)[0], filename.rsplit(".", 1)[0].replace("Test", ""), path, path.rsplit(".", 1)[0], path.rsplit(".", 1)[0].replace("Test", ""), ) candidate2 = os.path.relpath( candidate, os.path.dirname(sys.modules["__main__"].__file__) ) return candidate.rstrip("/") in candidates or candidate2 in candidates def exit(self, message): # Virtual method, pylint: disable=no-self-use sys.exit(message) def isCoverage(self): # Virtual method, pylint: disable=no-self-use return False def onErrorDetected(self, message): self.exit(message) class SearchModeImmediate(SearchModeBase): pass class SearchModeByPattern(SearchModeBase): def __init__(self, start_at): SearchModeBase.__init__(self) self.active = False self.start_at = start_at def consider(self, dirname, filename): if self.active: return True self.active = self._match(dirname, filename, self.start_at) return self.active def finish(self): if not self.active: sys.exit("Error, became never active.") class SearchModeResume(SearchModeBase): def __init__(self, tests_path): SearchModeBase.__init__(self) tests_path = os.path.normcase(os.path.abspath(tests_path)) version = sys.version if str is not bytes: tests_path = tests_path.encode("utf8") version = version.encode("utf8") case_hash = hashlib.md5(tests_path) case_hash.update(version) from .Common import getTestingCacheDir cache_filename = os.path.join(getTestingCacheDir(), case_hash.hexdigest()) self.cache_filename = cache_filename if os.path.exists(cache_filename): self.resume_from = getFileContents(cache_filename) or None else: self.resume_from = None self.active = not self.resume_from def consider(self, dirname, filename): parts = [dirname, filename] while None in parts: parts.remove(None) assert parts path = os.path.join(*parts) if self.active: putTextFileContents(self.cache_filename, contents=path) return True if areSamePaths(path, self.resume_from): self.active = True return self.active def finish(self): os.unlink(self.cache_filename) if not self.active: sys.exit("Error, became never active, restarting next time.") class SearchModeCoverage(SearchModeBase): def getExtraFlags(self, dirname, filename): return ["coverage"] def isCoverage(self): return True class SearchModeOnly(SearchModeByPattern): def __init__(self, start_at): SearchModeByPattern.__init__(self, start_at=start_at) self.done = False def consider(self, dirname, filename): if self.done: return False else: active = SearchModeByPattern.consider( self, dirname=dirname, filename=filename ) if active: self.done = True return active class SearchModeAll(SearchModeBase): def __init__(self): SearchModeBase.__init__(self) self.total_errors = 0 def updateTotalErrors(self): self.total_errors += 1 def onErrorDetected(self, message): self.updateTotalErrors() def finish(self): self.exit("Total " + str(self.total_errors) + " error(s) found.") Nuitka-0.6.19.1/nuitka/tools/testing/Valgrind.py0000600000372100037210000000645114166627112026525 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Valgrind tool usage. We are using it for benchmarking purposes, as it's an analysis tool at the same time and gives deterministic results. """ import shutil import sys from nuitka.Tracing import my_print from nuitka.utils.Execution import check_output, executeProcess from nuitka.utils.FileOperations import getFileContentByLine, withTemporaryFile from nuitka.utils.Utils import isWin32Windows def runValgrind(descr, tool, args, include_startup, save_logfilename=None): # Many cases to deal with, pylint: disable=too-many-branches if isWin32Windows(): sys.exit("Error, valgrind is not available on Windows.") if descr: my_print(descr, tool, file=sys.stderr, end="... ") with withTemporaryFile() as log_file: log_filename = log_file.name command = ["valgrind", "-q"] if tool == "callgrind": command += ("--tool=callgrind", "--callgrind-out-file=%s" % log_filename) elif tool == "massif": command += ("--tool=massif", "--massif-out-file=%s" % log_filename) else: sys.exit("Error, no support for tool '%s' yet." % tool) # Do not count things before main module starts its work. if not include_startup: command += ( "--zero-before=init__main__()", "--zero-before=init__main__", "--zero-before=PyInit___main__", "--zero-before=PyInit___main__()", ) command.extend(args) _stdout_valgrind, stderr_valgrind, exit_valgrind = executeProcess(command) assert exit_valgrind == 0, stderr_valgrind if descr: my_print("OK", file=sys.stderr) if save_logfilename is not None: shutil.copyfile(log_filename, save_logfilename) max_mem = None for line in getFileContentByLine(log_filename): if tool == "callgrind" and line.startswith("summary:"): return int(line.split()[1]) elif tool == "massif" and line.startswith("mem_heap_B="): mem = int(line.split("=")[1]) if max_mem is None: max_mem = 0 max_mem = max(mem, max_mem) if tool == "massif" and max_mem is not None: return max_mem sys.exit("Error, didn't parse Valgrind log file successfully.") def getBinarySizes(filename): command = ["size", filename] sizes = check_output(command).strip() sizes = sizes.split(b"\n")[-1].replace(b"\t", b"").split() return int(sizes[0]), int(sizes[1]) Nuitka-0.6.19.1/nuitka/tools/general/0000700000372100037210000000000014167275622024343 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/general/dll_report/0000700000372100037210000000000014167275622026511 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/general/dll_report/__main__.py0000600000372100037210000000444714166627112030610 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Main program for DLL checker tool. """ import os import sys from optparse import OptionParser from nuitka.freezer.Standalone import ( detectBinaryPathDLLsWindowsDependencyWalker, ) from nuitka.Tracing import my_print from nuitka.utils.SharedLibraries import getSxsFromDLL, getWindowsDLLVersion from nuitka.utils.Timing import TimerReport def main(): parser = OptionParser() _options, positional_args = parser.parse_args() if not positional_args: sys.exit("No DLLs given.") for filename in positional_args: my_print("Filename: %s" % filename) my_print("Version Information: %s" % getWindowsDLLVersion(filename)) my_print("SXS information (manifests):") sxs = getSxsFromDLL(filename=filename, with_data=True) if sxs: my_print(sxs) my_print("DLLs recursively dependended (depends.exe):") with TimerReport( message="Finding dependencies for %s took %%.2f seconds" % filename ): r = detectBinaryPathDLLsWindowsDependencyWalker( is_main_executable=False, source_dir="notexist", original_dir=os.path.dirname(filename), binary_filename=filename, package_name=None, use_cache=False, update_cache=False, ) for dll_filename in sorted(r): my_print(" %s" % dll_filename) my_print("Total: %d" % len(r)) if __name__ == "__main__": main() Nuitka-0.6.19.1/nuitka/tools/general/dll_report/__init__.py0000600000372100037210000000150114166627112030613 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/general/__init__.py0000600000372100037210000000150114166627112026445 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/Basics.py0000600000372100037210000000310314166627112024475 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Basics for Nuitka tools. """ import os import sys def goHome(): """Go its own directory, to have it easy with path knowledge.""" os.chdir(getHomePath()) my_abs_path = os.path.abspath(__file__) def getHomePath(): return os.path.normpath(os.path.join(os.path.dirname(my_abs_path), "..", "..")) def setupPATH(): """Make sure installed tools are in PATH. For Windows, add this to the PATH, so pip installed PyLint will be found near the Python executing this script. """ os.environ["PATH"] = ( os.environ["PATH"] + os.pathsep + os.path.join(os.path.dirname(sys.executable), "scripts") ) def addPYTHONPATH(path): python_path = os.environ.get("PYTHONPATH", "") os.environ["PYTHONPATH"] = os.pathsep.join(python_path.split(os.pathsep) + [path]) Nuitka-0.6.19.1/nuitka/tools/profiler/0000700000372100037210000000000014167275622024550 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/profiler/__main__.py0000600000372100037210000000474314166627112026646 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Profiling for Nuitka and CPython. This provides the capability of comparing performance results of Nuitka and CPython relatively to one another. """ # Note: This is currently severely broken. import runpy import sys import tempfile from nuitka.Tracing import my_print def _namelen(e): if e.startswith("py:"): return len(e.split(":")[1]) else: return len(e) def show(stats): p = stats.top_profile() if not p: my_print("no stats") return p.sort(key=lambda x: x[1], reverse=True) top = p[0][1] max_len = max([_namelen(e[0]) for e in p]) my_print(" vmprof output:") my_print(" %: name:" + " " * (max_len - 3) + "location:") for k, v in p: v = "%.1f%%" % (float(v) / top * 100) if v == "0.0%": v = "<0.1%" if k.startswith("py:"): _, func_name, lineno, filename = k.split(":", 3) lineno = int(lineno) my_print( " %s %s %s:%d" % (v.ljust(7), func_name.ljust(max_len + 1), filename, lineno) ) else: my_print(" %s %s" % (v.ljust(7), k.ljust(max_len + 1))) def main(): import vmprof # pylint: disable=I0021,import-error with tempfile.NamedTemporaryFile() as prof_file: vmprof.enable(prof_file.fileno(), 0.001) try: program = sys.argv[1] del sys.argv[1] # sys.argv = [args.program] + args.args runpy.run_path(program, run_name="__main__") except (KeyboardInterrupt, SystemExit): pass vmprof.disable() stats = vmprof.read_profile(prof_file.name) show(stats) if __name__ == "__main__": main() Nuitka-0.6.19.1/nuitka/tools/profiler/__init__.py0000600000372100037210000000150114166627112026652 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/commercial/0000700000372100037210000000000014167275622025041 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/commercial/__init__.py0000600000372100037210000000246214166627112027152 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Commercial tools package. This may load code from the commercial Nuitka repository """ # Auto extend to a Nuitka commercial installation, by adding it to the package # path. That aims at making extending Nuitka with these plugins easier. import os if "NUITKA_COMMERCIAL" in os.environ: path = os.environ["NUITKA_COMMERCIAL"] candidate = os.path.join(path, __name__.replace(".", os.path.sep)) if os.path.isdir(candidate) and os.path.isfile( os.path.join(candidate, "__init__.py") ): __path__.append(candidate) Nuitka-0.6.19.1/nuitka/tools/data_composer/0000700000372100037210000000000014167275622025546 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/tools/data_composer/__main__.py0000600000372100037210000000243214166627112027635 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Internal tool, assemble a constants blob for Nuitka from module constants. """ import os import sys if __name__ == "__main__": sys.path.insert(0, os.environ["NUITKA_PACKAGE_HOME"]) import nuitka # just to have it loaded from there, pylint: disable=unused-import del sys.path[0] sys.path = [ path_element for path_element in sys.path if os.path.dirname(os.path.abspath(__file__)) != path_element ] from nuitka.tools.data_composer.DataComposer import main main() Nuitka-0.6.19.1/nuitka/tools/data_composer/DataComposer.py0000600000372100037210000003377514166627112030514 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Data composer, crunch constants into binary blobs to load. """ import binascii import ctypes import math import os import re import struct import sys from nuitka.__past__ import ( BytesIO, GenericAlias, long, to_byte, unicode, xrange, ) from nuitka.build.DataComposerInterface import deriveModuleConstantsBlobName from nuitka.Builtins import builtin_exception_values_list, builtin_named_values from nuitka.constants.Serialization import ( BlobData, BuiltinAnonValue, BuiltinSpecialValue, BuiltinUnionTypeValue, ConstantStreamReader, ) from nuitka.PythonVersions import python_version from nuitka.Tracing import datacomposer_logger from nuitka.utils.FileOperations import listDir def scanConstFiles(build_dir): result = [] for fullpath, filename in listDir(build_dir): if not filename.endswith(".const"): continue result.append((fullpath, filename)) return result sizeof_clong = ctypes.sizeof(ctypes.c_long) max_signed_long = 2 ** (sizeof_clong * 7) - 1 min_signed_long = -(2 ** (sizeof_clong * 7)) sizeof_clonglong = ctypes.sizeof(ctypes.c_longlong) max_signed_longlong = 2 ** (sizeof_clonglong * 8 - 1) - 1 min_signed_longlong = -(2 ** (sizeof_clonglong * 8 - 1)) # TODO: The determination of this should already happen in Building or in a # helper not during code generation. _match_attribute_names = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") def _isAttributeName(value): # TODO: The exception is to make sure we intern the ".0" argument name # used for generator expressions, iterator value. return _match_attribute_names.match(value) or value == ".0" _last_written = None def _writeConstantValue(output, constant_value): # Massively many details per value, pylint: disable=too-many-branches,too-many-statements # We are a singleton, pylint: disable=global-statement global _last_written constant_type = type(constant_value) if constant_value is None: output.write(b"n") elif constant_value is _last_written: output.write(b"p") elif constant_value is True: output.write(b"t") elif constant_value is False: output.write(b"F") elif constant_type is tuple: # TODO: Optimize for size of tuple to be < 256 with dedicated value output.write(b"T" + struct.pack("i", len(constant_value))) _last_written = None for element in constant_value: _writeConstantValue(output, element) elif constant_type is list: # TODO: Optimize for size of tuple to be < 256 with dedicated value output.write(b"L" + struct.pack("i", len(constant_value))) _last_written = None for element in constant_value: _writeConstantValue(output, element) elif constant_type is dict: # TODO: Optimize for size of tuple to be < 256 with dedicated value output.write(b"D" + struct.pack("i", len(constant_value))) # Write keys first, and values second, such that we allow for the # last_writte to have an impact. items = constant_value.items() _last_written = None for key, value in items: _writeConstantValue(output, key) _last_written = None for key, value in items: _writeConstantValue(output, value) elif constant_type is set: # TODO: Optimize for size of tuple to be < 256 with dedicated value output.write(b"S" + struct.pack("i", len(constant_value))) _last_written = None for element in constant_value: _writeConstantValue(output, element) elif constant_type is frozenset: # TODO: Optimize for size of tuple to be < 256 with dedicated value output.write(b"P" + struct.pack("i", len(constant_value))) _last_written = None for element in constant_value: _writeConstantValue(output, element) elif constant_type is long: if min_signed_long <= constant_value <= max_signed_long: output.write(b"l" + struct.pack("l", constant_value)) elif min_signed_longlong <= constant_value <= max_signed_longlong: output.write(b"q" + struct.pack("q", constant_value)) else: output.write(b"g") if constant_value < 0: abs_constant_value = abs(constant_value) output.write(b"-") else: abs_constant_value = constant_value output.write(b"+") parts = [] mod_value = 2 ** (sizeof_clonglong * 8) while abs_constant_value > 0: parts.append(abs_constant_value % mod_value) abs_constant_value >>= sizeof_clonglong * 8 output.write(struct.pack("i", len(parts))) for part in reversed(parts): output.write(struct.pack("Q", part)) elif constant_type is int: # This is Python2 then. TODO: Special case smaller values. output.write(b"i" + struct.pack("l", constant_value)) elif constant_type is float: if constant_value == 0.0: if math.copysign(1, constant_value) == 1: output.write(b"Z" + to_byte(0)) else: output.write(b"Z" + to_byte(1)) elif math.isnan(constant_value): if math.copysign(1, constant_value) == 1: output.write(b"Z" + to_byte(2)) else: output.write(b"Z" + to_byte(3)) elif math.isinf(constant_value): if math.copysign(1, constant_value) == 1: output.write(b"Z" + to_byte(4)) else: output.write(b"Z" + to_byte(5)) else: output.write(b"f" + struct.pack("d", constant_value)) elif constant_type is unicode: if str is not bytes: encoded = constant_value.encode("utf8", "surrogatepass") else: encoded = constant_value.encode("utf8") if len(encoded) == 1: output.write(b"w" + encoded) # Zero termination if possible. elif b"\0" in encoded: output.write(b"v" + struct.pack("i", len(encoded))) output.write(encoded) else: if str is not bytes and _isAttributeName(constant_value): indicator = b"a" else: indicator = b"u" output.write(indicator + encoded + b"\0") elif constant_type is bytes: if len(constant_value) == 1: output.write(b"d" + constant_value) # Zero termination if possible. elif b"\0" in constant_value: output.write(b"b" + struct.pack("i", len(constant_value))) output.write(constant_value) else: if str is bytes and _isAttributeName(constant_value): indicator = b"a" else: indicator = b"c" output.write(indicator + constant_value + b"\0") elif constant_type is slice: output.write(b":") _last_written = None _writeConstantValue(output, constant_value.start) _writeConstantValue(output, constant_value.stop) _writeConstantValue(output, constant_value.step) elif constant_type is range: output.write(b";") _last_written = None _writeConstantValue(output, constant_value.start) _writeConstantValue(output, constant_value.stop) _writeConstantValue(output, constant_value.step) elif constant_type is xrange: output.write(b";") range_args = [ int(v) for v in str(constant_value)[7 if str is bytes else 6 : -1].split(",") ] # Default start. if len(range_args) == 1: range_args.insert(0, 0) # Default step if len(range_args) < 3: range_args.append(1) output.write(struct.pack("iii", *range_args)) elif constant_type is complex: # Some float values do not transport well, use float streaming then. if ( constant_value.real == 0 or constant_value.imag == 0 or math.isnan(constant_value.real) or math.isnan(constant_value.imag) or math.isinf(constant_value.real) or math.isinf(constant_value.imag) ): output.write(b"J") _last_written = None _writeConstantValue(output, constant_value.real) _writeConstantValue(output, constant_value.imag) else: output.write(b"j") output.write(struct.pack("dd", constant_value.real, constant_value.imag)) elif constant_type is bytearray: output.write(b"B" + struct.pack("i", len(constant_value))) if python_version < 0x270: constant_value = constant_value.decode("latin1") output.write(constant_value) elif constant_type is BuiltinAnonValue: output.write(b"M") output.write(constant_value.getStreamValueByte()) elif constant_type is BuiltinSpecialValue: output.write(b"Q") output.write(constant_value.getStreamValueByte()) elif constant_type is BlobData: constant_value = constant_value.getData() output.write(b"X") output.write(struct.pack("i", len(constant_value))) output.write(constant_value) elif constant_value in builtin_named_values: output.write(b"O") output.write(builtin_named_values[constant_value].encode("utf8")) output.write(b"\0") elif constant_value in builtin_exception_values_list: output.write(b"E") output.write(constant_value.__name__.encode("utf8")) output.write(b"\0") elif constant_type is GenericAlias: output.write(b"G") _last_written = None _writeConstantValue(output, constant_value.__origin__) _writeConstantValue(output, constant_value.__args__) elif constant_type is BuiltinUnionTypeValue: output.write(b"H") _last_written = None _writeConstantValue(output, constant_value.args) else: assert False, constant_value _last_written = constant_value def _writeConstantStream(constants_reader): result = BytesIO() # We are a singleton, pylint: disable=global-statement global _last_written _last_written = None count = 0 while 1: try: constant_value = constants_reader.readConstantValue() except EOFError: break old_size = result.tell() _writeConstantValue(result, constant_value) if not datacomposer_logger.is_quiet: new_size = result.tell() result.seek(old_size) type_char = result.read(1) result.seek(new_size) datacomposer_logger.info( "Size of constant %r is %d with type %r" % (constant_value, new_size - old_size, type_char) ) count += 1 # Dirty end of things marker that would trigger an assertion in the decoder. # TODO: Debug mode only? result.write(b".") return count, struct.pack("h", count) + result.getvalue() crc32 = 0 def _writeConstantsBlob(output_filename, desc): global crc32 # singleton, pylint: disable=global-statement with open(output_filename, "w+b") as output: output.write(b"\0" * 8) def write(data): global crc32 # singleton, pylint: disable=global-statement output.write(data) crc32 = binascii.crc32(data, crc32) for name, part in desc: write(name + b"\0") write(struct.pack("I", len(part))) write(part) data_size = output.tell() - 8 if str is bytes: # Python2 is doing signed CRC32, but we want unsigned. crc32 %= 1 << 32 output.seek(0) output.write(struct.pack("II", crc32, data_size)) assert output.tell() == 8 datacomposer_logger.info( "Total constants blob size without header %d." % data_size ) datacomposer_logger.info("Total constants blob CRC32 is %d." % crc32) def main(): datacomposer_logger.is_quiet = ( os.environ.get("NUITKA_DATACOMPOSER_VERBOSE", "0") != "1" ) # Internal tool, most simple command line handling. This is the build directory # where main Nuitka put the .const files. build_dir = sys.argv[1] output_filename = sys.argv[2] const_files = scanConstFiles(build_dir) total = 0 desc = [] names = set() for fullpath, filename in const_files: datacomposer_logger.info("Working on constant file %r." % filename) with open(fullpath, "rb") as const_file: constants_reader = ConstantStreamReader(const_file) count, part = _writeConstantStream(constants_reader) total += count name = deriveModuleConstantsBlobName(filename) # Make sure that is not repeated. assert name not in names, name names.add(name) datacomposer_logger.info( "Storing %r chunk with %s values size %r." % (name, count, len(part)) ) if str is not bytes: # Encoding needs to match generated source code output. name = name.encode("latin1") desc.append((name, part)) datacomposer_logger.info("Total amount of constants is %d." % total) _writeConstantsBlob(output_filename=output_filename, desc=desc) sys.exit(0) Nuitka-0.6.19.1/nuitka/tools/data_composer/__init__.py0000600000372100037210000000150114166627112027650 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/tools/__init__.py0000600000372100037210000000150114166627112025030 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/constants/0000700000372100037210000000000014167275622023602 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/nuitka/constants/__init__.py0000600000372100037210000000150114166627112025704 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Dummy file to make this directory a package. """ Nuitka-0.6.19.1/nuitka/constants/Serialization.py0000600000372100037210000001762614166627112027001 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Write and read constants data files and provide identifiers. """ import os import pickle import sys from nuitka import OutputDirectories from nuitka.__past__ import UnionType, basestring, to_byte, xrange from nuitka.Builtins import ( builtin_anon_codes, builtin_anon_values, builtin_exception_values_list, ) # TODO: Move to constants from nuitka.codegen.Namify import namifyConstant from nuitka.containers.oset import OrderedSet from nuitka.PythonVersions import python_version from nuitka.utils.FileOperations import openTextFile class BuiltinAnonValue(object): """Used to pickle anonymous values.""" # Python3 values has no index, turn into a tuple. anon_values = tuple(builtin_anon_values.values()) def __init__(self, anon_name): self.anon_name = anon_name def getStreamValueByte(self): """Return byte value, encoding the anon built-in value.""" return to_byte(self.anon_values.index(self.anon_name)) class BuiltinUnionTypeValue(object): def __init__(self, args): self.args = args class BuiltinSpecialValue(object): """Used to pickle special values.""" def __init__(self, value): self.value = value def getStreamValueByte(self): """Return byte value, encoding the special built-in value.""" # Currently the only one. if self.value == "Ellipsis": return to_byte(0) elif self.value == "NotImplemented": return to_byte(1) elif self.value == "Py_SysVersionInfo": return to_byte(2) else: assert False, self.value class BlobData(object): """Used to pickle bytes to become raw pointers.""" def __init__(self, data): self.data = data def getData(self): return self.data def _pickleAnonValues(pickler, value): if value in builtin_anon_values: pickler.save(BuiltinAnonValue(builtin_anon_values[value])) elif value is Ellipsis: pickler.save(BuiltinSpecialValue("Ellipsis")) elif value is NotImplemented: pickler.save(BuiltinSpecialValue("NotImplemented")) elif value is sys.version_info: pickler.save(BuiltinSpecialValue("Py_SysVersionInfo")) else: pickler.save_global(value) def _pickeUnionType(picker, value): picker.save(BuiltinUnionTypeValue(value.__args__)) class ConstantStreamWriter(object): """Write constants to a stream and return numbers for them.""" def __init__(self, filename): self.count = 0 filename = os.path.join(OutputDirectories.getSourceDirectoryPath(), filename) self.file = openTextFile(filename, "wb") if python_version < 0x300: self.pickle = pickle.Pickler(self.file, -1) else: self.pickle = pickle._Pickler( # pylint: disable=I0021,protected-access self.file, -1 ) self.pickle.dispatch[type] = _pickleAnonValues self.pickle.dispatch[type(Ellipsis)] = _pickleAnonValues self.pickle.dispatch[type(NotImplemented)] = _pickleAnonValues if type(sys.version_info) is not tuple: self.pickle.dispatch[type(sys.version_info)] = _pickleAnonValues # Standard pickling doesn't work with our necessary wrappers. if python_version >= 0x3A0: self.pickle.dispatch[UnionType] = _pickeUnionType def addConstantValue(self, constant_value): self.pickle.dump(constant_value) self.count += 1 def addBlobData(self, data): self.pickle.dump(BlobData(data)) self.count += 1 def close(self): self.file.close() class ConstantStreamReader(object): def __init__(self, const_file): self.count = 0 self.pickle = pickle.Unpickler(const_file) def readConstantValue(self): return self.pickle.load() class ConstantAccessor(object): def __init__(self, data_filename, top_level_name): self.constants = OrderedSet() self.constants_writer = ConstantStreamWriter(data_filename) self.top_level_name = top_level_name def getConstantCode(self, constant): # Use in user code, or for constants building code itself, many # constant types get special code immediately. # pylint: disable=too-many-branches,too-many-statements if constant is None: key = "Py_None" elif constant is True: key = "Py_True" elif constant is False: key = "Py_False" elif constant is Ellipsis: key = "Py_Ellipsis" elif constant is NotImplemented: key = "Py_NotImplemented" elif constant is sys.version_info: key = "Py_SysVersionInfo" elif type(constant) is type: # TODO: Maybe make this a mapping in nuitka.Builtins if constant is None: key = "(PyObject *)Py_TYPE(Py_None)" elif constant is object: key = "(PyObject *)&PyBaseObject_Type" elif constant is staticmethod: key = "(PyObject *)&PyStaticMethod_Type" elif constant is classmethod: key = "(PyObject *)&PyClassMethod_Type" elif constant is bytearray: key = "(PyObject *)&PyByteArray_Type" elif constant is enumerate: key = "(PyObject *)&PyEnum_Type" elif constant is frozenset: key = "(PyObject *)&PyFrozenSet_Type" elif python_version >= 0x270 and constant is memoryview: key = "(PyObject *)&PyMemoryView_Type" elif python_version < 0x300 and constant is basestring: key = "(PyObject *)&PyBaseString_Type" elif python_version < 0x300 and constant is xrange: key = "(PyObject *)&PyRange_Type" elif constant in builtin_anon_values: key = "(PyObject *)" + builtin_anon_codes[builtin_anon_values[constant]] elif constant in builtin_exception_values_list: key = "(PyObject *)PyExc_%s" % constant.__name__ else: type_name = constant.__name__ if constant is int and python_version >= 0x300: type_name = "long" elif constant is str: type_name = "string" if python_version < 0x300 else "unicode" key = "(PyObject *)&Py%s_Type" % type_name.capitalize() else: key = "const_" + namifyConstant(constant) if key not in self.constants: self.constants.add(key) self.constants_writer.addConstantValue(constant) key = "%s[%d]" % (self.top_level_name, self.constants.index(key)) # TODO: Make it returning, more clear. return key def getBlobDataCode(self, data): key = "blob_" + namifyConstant(data) if key not in self.constants: self.constants.add(key) self.constants_writer.addBlobData(data) key = "%s[%d]" % (self.top_level_name, self.constants.index(key)) return key def getConstantsCount(self): # Make sure to add no more after asking this. self.constants_writer.close() return len(self.constants) Nuitka-0.6.19.1/nuitka/PythonOperators.py0000600000372100037210000000745614166627112025330 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Python operator tables These are mostly used to resolve the operator in the module operator and to know the list of operations allowed. """ import operator from nuitka.PythonVersions import python_version binary_operator_functions = { "Add": operator.add, "Sub": operator.sub, "Pow": operator.pow, "Mult": operator.mul, "FloorDiv": operator.floordiv, "TrueDiv": operator.truediv, "Mod": operator.mod, "LShift": operator.lshift, "RShift": operator.rshift, "BitAnd": operator.and_, "BitOr": operator.or_, "BitXor": operator.xor, "Divmod": divmod, "IAdd": operator.iadd, "ISub": operator.isub, "IPow": operator.ipow, "IMult": operator.imul, "IFloorDiv": operator.ifloordiv, "ITrueDiv": operator.itruediv, "IMod": operator.imod, "ILShift": operator.ilshift, "IRShift": operator.irshift, "IBitAnd": operator.iand, "IBitOr": operator.ior, "IBitXor": operator.ixor, } # Python 2 only operator if python_version < 0x300: binary_operator_functions["OldDiv"] = operator.div binary_operator_functions["IOldDiv"] = operator.idiv # Python 3.5 only operator if python_version >= 0x350: binary_operator_functions["MatMult"] = operator.matmul binary_operator_functions["IMatMult"] = operator.imatmul unary_operator_functions = { "UAdd": operator.pos, "USub": operator.neg, "Invert": operator.invert, "Repr": repr, # Boolean not is treated an unary operator. "Not": operator.not_, "Abs": operator.abs, } rich_comparison_functions = { "Lt": operator.lt, "LtE": operator.le, "Eq": operator.eq, "NotEq": operator.ne, "Gt": operator.gt, "GtE": operator.ge, } other_comparison_functions = { "Is": operator.is_, "IsNot": operator.is_not, "In": lambda value1, value2: value1 in value2, "NotIn": lambda value1, value2: value1 not in value2, } comparison_inversions = { "Is": "IsNot", "IsNot": "Is", "In": "NotIn", "NotIn": "In", "Lt": "GtE", "GtE": "Lt", "Eq": "NotEq", "NotEq": "Eq", "Gt": "LtE", "LtE": "Gt", "exception_match": "exception_mismatch", "exception_mismatch": "exception_match", } all_comparison_functions = dict(rich_comparison_functions) all_comparison_functions.update(other_comparison_functions) def matchException(left, right): if python_version >= 0x300: if type(right) is tuple: for element in right: if not isinstance(BaseException, element): raise TypeError( "catching classes that do not inherit from BaseException is not allowed" ) elif not isinstance(BaseException, right): raise TypeError( "catching classes that do not inherit from BaseException is not allowed" ) # This doesn't yet work, make it error exit. and silence PyLint for now. # pylint: disable=protected-access import os os._exit(16) assert False, left all_comparison_functions["exception_match"] = matchException Nuitka-0.6.19.1/nuitka/Caching.py0000600000372100037210000000724214166627112023475 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Caching of compiled code. Initially this deals with preserving compiled module state after bytecode demotion such that it allows to restore it directly. """ import hashlib import os from nuitka import Options from nuitka.importing.Importing import getPackageSearchPath, isPackageDir from nuitka.utils.AppDirs import getCacheDir from nuitka.utils.FileOperations import ( getFileContents, listDir, makePath, openTextFile, ) from nuitka.utils.Importing import getAllModuleSuffixes from nuitka.utils.ModuleNames import ModuleName def _getCacheDir(): module_cache_dir = os.path.join(getCacheDir(), "module-cache") makePath(module_cache_dir) return module_cache_dir def _getCacheFilename(module_name, extension): return os.path.join(_getCacheDir(), "%s.%s" % (module_name, extension)) def getSourceCodeHash(source_code): if str is not bytes: source_code = source_code.encode("utf8") return hashlib.md5(source_code).hexdigest() def makeCacheName(module_name, source_code): module_importables_hash = getModuleImportableFilesHash(module_name) return ( module_name.asString() + "@" + module_importables_hash + "@" + getSourceCodeHash(source_code) ) def hasCachedImportedModulesNames(module_name, source_code): cache_name = makeCacheName(module_name, source_code) # TODO: Disabled using cache results for now. if not Options.isExperimental("bytecode-cache"): return False return os.path.exists(_getCacheFilename(cache_name, "txt")) def getCachedImportedModulesNames(module_name, source_code): cache_name = makeCacheName(module_name, source_code) return [ ModuleName(line) for line in getFileContents(_getCacheFilename(cache_name, "txt")) .strip() .split("\n") ] def writeImportedModulesNamesToCache(module_name, source_code, used_modules): cache_name = makeCacheName(module_name, source_code) with openTextFile(_getCacheFilename(cache_name, "txt"), "w") as modules_cache_file: for used_module_name, _filename, _finding, _level, _source_ref in used_modules: modules_cache_file.write(used_module_name.asString() + "\n") def getModuleImportableFilesHash(full_name): package_name = full_name.getPackageName() paths = getPackageSearchPath(None) if package_name is not None: paths += getPackageSearchPath(package_name) all_suffixes = getAllModuleSuffixes() result_hash = hashlib.md5() for count, path in enumerate(paths): if not os.path.isdir(path): continue for fullname, filename in listDir(path): if isPackageDir(fullname) or filename.endswith(all_suffixes): entry = "%s:%s" % (count, filename) if str is not bytes: entry = entry.encode("utf8") result_hash.update(entry) return result_hash.hexdigest() Nuitka-0.6.19.1/lib/0000700000372100037210000000000014167275622021041 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/lib/hints.py0000600000372100037210000001023214166627112022532 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ The hints module should contain functions to call in your code. In reality, right now it does only contain an import tracing mechanism that helps us with debugging. """ from __future__ import print_function import os import sys import traceback try: import __builtin__ as builtins except ImportError: import builtins original_import = __import__ _indentation = 0 def _normalizePath(path): path = os.path.abspath(path) best = None paths = list(sys.path) # Nuitka standalone mode. try: paths.append(__nuitka_binary_dir) paths.append(os.getcwd()) except NameError: pass for path_entry in paths: path_entry = os.path.normcase(path_entry) if os.path.normcase(path).startswith(path_entry): if best is None or len(path_entry) > len(best): best = path_entry if best is not None: path = "$PYTHONPATH" + path[len(best) :] return path def _moduleRepr(module): try: module_file = module.__file__ module_file = module_file.replace(".pyc", ".py") if module_file.endswith(".so"): module_file = os.path.join( os.path.dirname(module_file), os.path.basename(module_file).split(".")[0] + ".so", ) file_desc = "file " + _normalizePath(module_file).replace(".pyc", ".py") except AttributeError: file_desc = "built-in" return "" % (module.__name__, file_desc) normalize_paths = None show_source = None def _ourimport( name, globals=None, locals=None, fromlist=None, level=-1 if sys.version_info[0] < 3 else 0, ): builtins.__import__ = original_import # Singleton, pylint: disable=global-statement global _indentation try: _indentation += 1 print( _indentation * " " + "called with: name=%r level=%d fromlist=%s" % (name, level, fromlist) ) for entry in traceback.extract_stack()[:-1]: if entry[2] == "_ourimport": print(_indentation * " " + "by __import__") else: entry = list(entry) if not show_source: del entry[-1] del entry[-1] if normalize_paths: entry[0] = _normalizePath(entry[0]) print(_indentation * " " + "by " + "|".join(str(s) for s in entry)) print(_indentation * " " + "*" * 40) builtins.__import__ = _ourimport try: result = original_import(name, globals, locals, fromlist, level) except ImportError as e: print(_indentation * " " + "EXCEPTION:", e) raise finally: builtins.__import__ = original_import print(_indentation * " " + "RESULT:", _moduleRepr(result)) print(_indentation * " " + "*" * 40) builtins.__import__ = _ourimport return result finally: _indentation -= 1 def enableImportTracing(normalize_paths=True, show_source=False): global do_normalize_paths, do_show_source do_normalize_paths = normalize_paths do_show_source = show_source # pylint: disable=redefined-builtin builtins.__import__ = _ourimport # Since we swap this around, prevent it from releasing by giving it a global # name too, not only a local one. global _ourimport_reference _ourimport Nuitka-0.6.19.1/Changelog.rst0000600000372100037210000232664314166627112022730 0ustar nuitka-buildslavenuitka-buildslave00000000000000################## Nuitka Changelog ################## In this document, we track the per version changes and comments. This becomes a document on the website, as well as individual posts on the Nuitka blog. *********************** Nuitka Release 0.6.19 *********************** This release adds support for 3.10 while also adding very many new optimization, and doing a lot of bug fixes. Bug Fixes ========= - Calls to ``importlib.import_module`` with expressions that need releases, i.e. are not constant values, could crash the compilation. Fixed in 0.6.18.1 already. - After a fix for the previous release, modules that fail to import are attempted again when another import is executed. However, during this initialization for top level module in ``--module`` mode, this was was done repeatedly, and could cause issues. Fixed in 0.6.18.1 already. - Standalone: Ignore warning given by ``patchelf`` on Linux with at least newer OpenSUSE. Fixed in 0.6.18.1 already. - Standalone: Add needed datafile for ``cv2`` package. - Fix, need to avoid computing large values out of ``<<`` operation as well. Fixed in 0.6.18.2 already. .. code:: python # This large value was computed at runtime and then if used, also # converted to a string and potentially hashed, taking a long time. 1 << sys.maxint - Standalone: Ignore warning given by ``patchelf`` on Linux about a workaround being applied. - Fix, calls to ``importlib.import_module`` were not correctly creating code for dynamic argument values that need to be released, causing the compilation to report the error. Fixed in 0.6.18.1 already. - MSYS2: Fix, the console scripts are actually good for it as opposed to CPython, and the batch scripts should not be installed. Fixed in 0.6.18.2 already. - Setuptools: Added support older version of ``setuptools`` in meta ``build`` integration of Nuitka. - Fix, calls to ``importlib.import_module`` with 2 arguments that are dynamic, were not working at all. Fixed in 0.6.18.2 already. - Windows: Compiling with MinGW64 without ``ccache`` was not working due to issues in Scons. Fixed in 0.6.18.2 already. - Fix, the ``repr`` built-in was falsely annotated as producing a ``str`` value, but it can be also derived or ``unicode`` in Python2. - Fix, attribute nodes were not considering the value they are looking up on. Now that more values will know to have the attributes, that was causing errors. Fixed in 0.6.18.2 already. - Standalone: Added datafile for ``cv2`` package. Fixed in 0.6.18.2 already. - Fix, left shifting can also produce large values and needs to be avoided in that case, similar to what we do for multiplications already. Fixed in 0.6.18.2 already. - UI: The new option ``--disable-ccache`` didn't really have the intended effect. Fixed in 0.6.18.3 already. - UI: The progress bar was causing tearing and corrupted outputs, when outputs were made, now using proper ``tqdm`` API for doing it, this has been solved. Fixed in 0.6.18.4 already. - Fix, the constant value ``sys.version_info`` didn't yet have support for its type to be also a compile time constant in e.g. tuples. Fixed in 0.6.18.4 already. - Onefile: Assertions were not disabled, and on Windows with MinGW64 this lead to including the C filenames of the ``zstd`` inline copy files and obviously less optimal code. Fixed in 0.6.18.4 already. - Standalone: Added support for ``bottle.ext`` loading extensions to resolve at compile time. Fixed in 0.6.18.5 already. - Standalone: Added support for ``seedir`` required data file. Fixed in 0.6.18.5 already. - MSYS2: Failed to link when using the static libpython, which is also now the default for MSYS2. Fixed in 0.6.18.5 already. - Python3.6+: Fix, the intended finalizer of compiled ``asyncgen`` was not present and in fact associated to help type. This could have caused corruption, but that was also very unlikely. Fixed in 0.6.18.5 already. - Python3: Fix, need to set ``__file__`` before executing modules, as some modules, e.g. newer PyWin32 use them to locate things during their initialization already. - Standalone: Handle all PyWin32 modules that need the special DLLs and not just a few. - Fix, some ``.pth`` files create module namespaces with ``__path__`` that does not exist, ignore these in module importing. - Python2.6-3.4: Fix, modules with an error could use their module name after it was released. - Distutils: When providing arguments, the method suggested in the docs is not compatible with all other systems, e.g. not ``setuptools_rust`` for which a two elemented tuple form needs to be used for values. Added support for that and documented its use as well in the User Manual. - Python3.7+: Do no longer allow deleting cell values, this can lead to corruption and should be avoided, it seems unlikely outside of tests anyway. - Standalone: Added support for more ciphers and hashes with ``pycryptodome`` and ``pycryptodomex``, while also only including Ciphers when needed. - Distutils: Was not including modules or packages only referenced in the entry point definition, but not in the list of packages. That is not compatible and has been fixed. - Fix, must not expose the constants blob from extension modules, as loading these into a compiled binary can cause issues in this case. - Standalone: Added support for including OpenGL and SSL libraries with ``PySide2`` and ``PySide6`` packages. - Windows: Fix, the ``cmd`` files created for uninstalled Python and accelerated programs to find the Python installation were not passing command line arguments. - Windows: Executing modules with ``--run`` was not working properly due to missing escaping of file paths. - Fix, parsing ``.pyi`` files that make relative imports was not resolving them correctly. - Python3: Fix, when disabling the console on Windows, make sure the file handles still work and are not ``None``. - Windows: Fix, need to claim all OS versions of Windows as supported, otherwise e.g. high DPI features are not available. New Features ============ - Programs that are to be executed with the ``-m`` flag, can now be compiled with ``--python-flag=-m`` and will then behave in a compatible way, i.e. load the containing package first, and have a proper ``__package__`` value at run time. - We now can write XML reports with information about the compilation. This is initially for use in PGO tests, to decide if the expected forms of inclusions have happened and should grow into a proper reporting tool over time. At this point, the report is not very useful yet. - Added support for Python 3.10, only ``match`` statements are not completely supported. Variantion with ``|`` matches that also assign are not allowed currently. - Windows: Allow using ``--clang`` with ``--mingw64`` to e.g. use the ``clang.exe`` that is contained in the Nuitka automatic download rather than ``gcc.exe``. - Added support for Kivy. Works through a plugin that is automatically enabled and needs no other inputs, detecting everything from using Kivy at compile time. - Added initial support for Haiku OS, a clone of BeOS with a few differences in their Python installation. - Added experimental plugin ``trio`` that works around issues with that package. Optimization ============ - Also trust hard imports made on the module level in function level code, this unlocks many more static optimization e.g. with ``sys.version_info`` when the import and the use are not on the same level. - For the built-in type method calls with generic implementation, we now do faster method descriptor calls. These avoid creating a temporary ``PyCFunction`` object, that the normal call slot would, this should make these calls faster. Checking them for compiled function, etc. was only wasteful, so this makes it more direct. - Loop and normal merge traces were keeping assignments made before the loop or inside a branch, that was otherwise unused alive. This should enable more optimization for code with branches and loops. Also unused loop traces are now recognized and removed as well. - Avoiding merges of escaped traces with the unescaped trace, there is no point in them. This was actually happening a lot and should mean a scalability improvement and unlock new optimization as well. - Avoid escaping uninit traces. Unset values need not be considered as potentially modified as that cannot be done. - The ``str`` shape is now detected through variables, this enables many optimization on the function level. - Added many ``str`` operation nodes. These are specifically all methods with no arguments, as these are very generic to add, introduced a base class for them, where we know they all have no effect or raise, as these functions are all guarantueed to succeed and can be served by a common base class. This covers the ``str.capitalize``, ``str.upper``, ``str.lower``, ``str.swapcase``, ``str.title``, ``str.isalnum``, ``str.isalpha``, ``str.isdigit``, ``str.islower``, ``str.isupper``, ``str.isspace``, and ``str.istitle`` functions. For static optimization ``str.find`` and ``str.rfind`` were added, as they are e.g. used in a ``sys.version.find(...)`` style in the ``os`` module, helping to decide to not consider ``OS/2`` only modules. Then, support for ``str.index`` and ``str.rindex`` was added, as these are very similar to ``str.find`` forms, only that these may raise an exception. Also add support for ``str.split`` and ``str.rsplit`` which will be used sometimes for code needed to be compile time computed, to e.g. detect imports. .. note:: Status The ``endswith`` and ``startswith`` functions are missing and would also be relatively important, otherwise the important ones seem covered. With time we will achieve "all" of them, but that may not happen in this release. - Added trust for ``sys.builtin_module_names`` as well. The ``os`` module is using it to make platform determinations. - When writing constant values, esp. ``tuple``, ``list``, or ``dict`` values, an encoding of "last value" has been added, avoiding the need to repeat the same value again, making many values more compact. - When starting Nuitka, it usually restarts itself with information collected in a mode without the ``site`` module loaded, and with hash randomization disabled, for deterministic behaviour. There is a option to prevent this from happening, where the goal is to avoid it, e.g. in testing, say for the coverage taking, but that meant to parse the options twice, which also loads a lot of code. Now only a minimal amount of code is used, and the options are parsed only on the restart, and then an error is raised when it notices, it was not allowed to do so. This also makes code a lot cleaner. - Specialized comparison code for Python2 ``long`` and Python3 ``int`` code, making these operations much faster to use. - Specialized comparison code for Python2 ``unicode`` and Python3 ``str`` code, making these operations much faster to use, currently only ``==`` and ``!=`` are fully accelerated, the other comparisons will follow. - Enable static libpython with Python3 Debian packages too. As with Python2, this will improve the performance of the created binary a lot and reduce size for standalone distribution. - Comparisons with ``in`` and ``not in`` also consider value traces and go through variables as well where possible. So far only the rich comparisons and ``is`` and ``is not`` did that. - Create fixed import nodes in re-formulations rather than ``__import__`` nodes, avoiding later optimization doing that, and of course that's simpler code too. - Python 3.10: Added support for ``union`` types as compiled time constants. - Modules are now fully optimized before considering which modules they are in turn using, this avoids temporary dependencies, that later turn out unused, and can shorten the compilation in some cases by a lot of time. - On platforms without a static link library, in LTO mode, and with gcc, we can use the ``-O3`` mode, which doesn't work for ``libpython``, but that's not used there. This also includes fake static libpython, as used by MinGW64 and Anaconda on Windows. - The ``anti-bloat`` plugin now also handles newer ``sklearn`` and knows more about the standard library, and its runners which it will exclude from compilation if use for it. Currently that is not the default, but it should become that. Organisational ============== - Migrated the Nuitka blog from Nikola to Sphinx based ABlog and made the whole site render with Sphinx, making it a lot more usable. - Added a small presentation about Nuitka on the Download page, to make sure people are aware of core features. - The ``gi`` plugin is now always on. The copying of the typelib when ``gi`` is imported is harmless and people can disable the plugin if that's not needed. - The ``matplotlib`` plugin is new and also always on. It previously was part of the ``numpy`` plugin, which is doing too many unrelated things. Moving this one out is part of a plan to split it up and have it on by default without causing issues. - MSYS2: Detecting ``MinGW`` and ``POSIX`` flavors of this Python. For the ``MinGW`` flavor of MSYS2, the option ``--mingw64`` is now the default, before it could attempt to use MSVC, which is not going to work for it. And also the Tcl and Tk installations of it are being detected automatically for the ``tk-inter`` plugin. - Added Windows version to Nuitka version output, so we have this for bug reports. - User Manual: Added example explaining how to access values from your code in Nuitka project options. - UI: For Python flavors where we expect a static libpython, the error message will now point out how to achieve it for each flavor. - UI: Disable progress bar when ``--show-scons`` is used, it makes capturing the output from the terminal only harder. - UI: Catch error of specifying both ``--msvc=`` and ``--mingw64`` options. - Distutils: Improved error messages when using ``setuptools`` or ``build`` integration and failing to provide packages to compile. - Plugins: Removed now unused feature to rename modules on import, as it was only making the code more complex, while being no more needed after recently adding a place for meta path based importers to be accounted for. - Twitter: Use embedded Tweet in Credits, and regular follow button in User Manual. - Warnings about imports not done, are now only given when optimization can not remove the usage, and no options relatved to following have been given. - Added Windows version to ``--version`` output of Nuitka. This is to more clearly recognize Windows 10 from Windows 11 report, and also the odd Windows 7 report, where tool chain will be different. - In Visual Code, the default Python used is now 3.9 in the "Linux" C configuration. This matches Debian Bullseye. - Nicer outputs from check mode of the autoformat as run for CI testing, displays problematic files more clearly. - Remove broken links to old bug tracker that is no longer online from the Changelog. - UI: When hitting CTRL-C during initial technical import detection, no longer ask to submit a bug report with the exception stack, instead exit cleanly. - Windows: Enable LTO mode for MinGW64 and other gcc by default. We require a version that can do it, so take advantage of that. - For cases, where code generation of a module takes long, make sure its name is output when CTRL-C is hit. - Windows: Splash screen only works with MSVC, added error indicator for MinGW64 that states that and asks for porting help. Cleanups ======== - Generate all existing C code for generic builtin type method calls automatically, and use those for method attribute lookups, making it easier to add more. - Changed ``TkInter`` module to data file providing interface, yielding the 2 directories in question, with a filter for ``demos``. - The importing code got a major overhaul and no longer works with relative filenames, or filenames combined with package names, and module names, but always only with module names and absolute filenames. This cleans up some of the oldest and most complex code in Nuitka, that had grown to address various requirements discovered over time. - Major cleanup of Jinja2 template organisation Renamed all C templates from ``.j2`` to ``.c.j2`` for clarity, this was not done fully consistent before. Also move all C templates to ``nuitka.codegen`` package data, it will be confusing to make a difference between ones used during compile time and for the static generation, and the lines are going to become blurry. Added Jinja2 new macro ``CHECK_OBJECTS`` to avoid branches on argument count in the call code templates. More of these things should be added. Cleanup of code that generates header declarations, there was some duplication going on, that made it hard to generate consistent code. - Removed ``nuitka.finalizatios.FinalizationBase``, we only have one final visitor that does everything, and that of course makes a lot of sense for its performance. - Major cleanup of the Scons C compiler configuration setup. Moved things to the dedicate function, and harmonized it more. - Resolved deprecation warnings given by with ``--python-debug`` for Nuitka. Tests ===== - Started test suite for Python PGO, not yet completely working though, it's not yet doing what is needed though. - Added generated test that exercises str methods in multiple variations. - Revived ``reflected`` test suite, that had been removed, because of Nuitka special needs. This one is not yet passing again though, due to a few details not yet being as compatible as needed. - Added test suite for CPython 3.10 and enable execution of tests with this version on Github actions. Summary ======= This release is another big step forward. The amount of optimization added is again very large, some of which yet again unlocks more static optimization of module imports, that previously would have to be considered implicit. Now analysing these on the function level as well, we can start searching for cases, where it could be done, but is not done yet. After starting with ``dict``, method optimization has focused on ``str`` which is esp. important for static optimization of imports. The next goal will here be to cover ``list`` which are important for run time performance and currently not yet optimized. Future releases will progress there, and also add more types. The C type specialization for Python3 has finally progressed, such that it is also covering the ``long`` and ``unicode`` and as such not limited to Python2 as much. The focus now needs to turn back to not working with ``PyObject *`` for these types, but e.g. with ``+= 1`` to make it directly work with ``CLONG`` rather than ``LONG`` for which structural changes in code generation will be needed. For scalability, the ``anti-bloat`` work has not yet progressed as much as to be able to enable it by default. It needs to be more possible to disable it where it causes problems, e.g. when somebody really wants to include ``pytest`` and test frameworks generally, that's something that needs to be doable. Compiling without ``anti-bloat`` plugin is something that is immediately noticeable in exploding module amounts. It is very urgently recommended to enable it for your compilations. The support for Windows has been further refined, actually fixing a few important issues, esp. for the Qt bindings too. This release adds support for 3.10 outside of very special ``match`` statements, bringing Nuitka back to where it works great with recent Python. Unfortunately ``orderedset`` is not available for it yet, which means it will be slower than 3.9 during compilation. Overall, Nuitka is closing many open lines of action with this. The ``setuptools`` support has yet again improved and at this point should be very good. *********************** Nuitka Release 0.6.18 *********************** This release has a focus on new features of all kinds, and then also new kinds of performance improvements, some of which enable static optimization of what normally would be dynamic imports, while also polishing plugins and adding also many new features and a huge amount of organisational changes. Bug Fixes ========= - Python3.6+: Fixes to asyncgen, need to raise ``StopAsyncInteration`` rather than ``StopIteration`` in some situations to be fully compatible. - Onefile: Fix, LTO mode was always enabled for onefile compilation, but not all compilers support it yet, e.g. MinGW64 did not. Fixed in 0.6.17.1 already. - Fix, ``type`` calls with 3 arguments didn't annotate their potential exception exit. Fixed in 0.6.17.2 already. - Fix, trusted module constants were not working properly in all cases. Fixed in 0.6.17.2 already. - Fix, ``pkg-resources`` exiting with error at compile time for unresolved requirements in compiled code, but these can of course still be optional, i.e. that code would never run. Instead give only a warning, and runtime fail on these. Fixed in 0.6.17.2 already. - Standalone: Prevent the inclusion of ``drm`` libraries on Linux, they have to come from the target OS at runtime. Fixed in 0.6.17.2 already. - Standalone: Added missing implicit dependency for ``ipcqueue`` module. Fixed in 0.6.17.3 already. - Fix, Qt webengine support for everything but ``PySide2`` wasn't working properly. Partially fixed in 0.6.17.3 already. - Windows: Fix, bootstrap splash screen code for Windows was missing in release packages. Fixed in 0.6.17.3 already. - Fix, could crash on known implicit data directories not present. Fixed in 0.6.17.3 already. - macOS: Disable download of ``ccache`` binary for M1 architecture and systems before macOS 10.14 as it doesn't work on these. Fixed in 0.6.17.3 already. - Standalone: The ``pendulum.locals`` handling for Python 3.6 was regressed. Fixed in 0.6.17.4 already. - Onefile: Make sure the child process is cleaned up even after its successful exit. Fixed in 0.6.17.4 already. - Standalone: Added support for ``xmlschema``. Fixed in 0.6.17.4 already. - Standalone: Added support for ``curses`` on Windows. Fixed in 0.6.17.4 already. - Standalone: Added support for ``coincurve`` module. Fixed in 0.6.17.5 already. - Python3.4+: Up until Python3.7 inclusive, a workaround for stream encoding (was ASCII), causing crashes on output of non-ASCII, other Python versions are not affected. Fixed in 0.6.17.5 already. - Python2: Workaround for LTO error messages from older gcc versions. Fixed in 0.6.17.5 already. - Standalone: Added support for ``win32print``. Fixed in 0.6.17.6 already. - Fix, need to prevent usage of static ``libpython`` in module mode or else on some Python versions, linker errors can happen. Fixed in 0.6.17.6 already. - Standalone: Do not load ``site`` module early anymore. This might have caused issues in some configurations, but really only would be needed for loading ``inspect`` which doesn`t depend on it in standalone mode. Fixed in 0.6.17.6 already. - Fix, could crash with generator expressions in finally blocks of tried blocks that return. Fixed in 0.6.17.7 already. .. code:: python try: return 9 finally: "".join(x for x in b"some_iterable") - Python3.5+: Compatibility of comparisons with ``types.CoroutineType`` and ``types.AsyncGeneratorType`` types was not yet implemented. Fixed in 0.6.17.7 already. .. code:: python # These already worked: assert isinstance(compiledCoroutine(), types.CoroutineType) is True assert isinstance(compiledAsyncgen(), types.AsyncGeneratorType) is True # These now work too: assert type(compiledCoroutine()) == types.CoroutineType assert type(compiledAsyncgen()) == types.AsyncGeneratorType - Standalone: Added support for ``ruamel.yaml``. Fixed in 0.6.17.7 already. - Distutils: Fix, when building more than one package, things could go wrong. Fixed in 0.6.17.7 already. - Fix, for module mode filenames are used, and for packages, you can specify a directory, however, a trailing slash was not working. Fixed in 0.6.17.7 already. - Compatibility: Fix, when locating modules, a package directory and an extension module of the same name were not used according to priority. Fixed in 0.6.17.7 already. - Standalone: Added workaround ``importlib_resources`` insisting on Python source files to exist to be able to load datafiles. Fixed in 0.6.17.7 already. - Standalone: Properly detect usage of hard imports from standard library in ``--follow-stdlib`` mode. - Standalone: Added data files for ``opensapi_spec_validator``. - MSYS2: Fix, need to normalize compiler paths before comparing. - Anaconda: For accelerated binaries, the created ``.cmd`` file wasn't containing all needed environment. - macOS: Set minimum OS version derived from the Python executable used, this should make it work on all supported platforms (of that Python). - Standalone: Added support for automatic inclusion of ``xmlschema`` package datafiles. - Standalone: Added support for automatic inclusion of ``eel`` package datafiles. - Standalone: Added support for ``h5py`` package. - Standalone: Added support for ``phonenumbers`` package. - Standalone: Added support for ``feedparser`` package, this currently depends on the ``anti-bloat`` plugin to be enabled, which will become enabled by default in the future. - Standalone: Added ``gi`` plugin for said package that copies ``typelib`` files and sets the search path for them in standalone mode. - Standalone: Added necessary datafiles for ``eel`` package. - Standalone: Added support for ``QtWebEngine`` to all Qt bindings and also make it work on Linux. Before only PySide2 on Windows was supported. - Python3: Fix, the ``all`` built-in was wrongly assuming that bytes values could not be false, but in fact they are if they contain ``\0`` which is actually false. The same does not happen for string values, but that's a difference to be considered. - Windows: The LTO was supposed to be used automatically on with MSVC 14.2 or higher, but that was regressed and has been repaired now. - Standalone: Extension modules contained in packages, depending on their mode of loading had the ``__package__`` value set to a wrong value, which at least impacted new matplotlib detection of Qt backend. - Windows: The ``python setup.py install`` was installing binaries for no good reason. New Features ============ - Setuptools support. Documented ``bdist_nuitka`` and ``bdist_wheel`` integration and added support for Nuitka as a ``build`` package backend in ``pyproject.toml`` files. Using Nuitka to build your wheels is supposed to be easy now. - Added experimental support for Python 3.10, there are however still important issues with compatibility with the CPython 3.9 test suite with at least asyncgen and coroutines. - macOS: For app bundles, version information can be provided with the new option ``--macos-app-version``. - Added Python vendor detection of ``Anaconda``, ``pyenv``, ``Apple Python``, and ``pyenv`` and output the result in version output, this should make it easiert to analyse reported issues. - Plugins: Also handle the usage of ``__name__`` for metadata version resolution of the ``pkg-resources`` standard plugin. - Plugins: The ``data-files`` standard plugin now reads configuration from a Yaml file that ``data-files.yml`` making it more accessible for contributions. - Windows: Allow enforcing usage of MSVC with ``--msvc=latest``. This allows you to prevent accidental usage of MinGW64 on Windows, when MSVC is intended, but achieves that without fixing the version to use. - Windows: Added support for LTO with MinGW64 on Windows, this was previously limited to the MSVC compiler only. - Windows: Added support for using ``--debugger`` with the downloaded MinGW64 provided ``gdb.exe``. .. note:: It doesn`t work when executed from a Git bash prompt, but e.g. from a standard command prompt. - Added new experimental flag for compiled types to inherit from uncompiled types. This should allow easier and more complete compatibility, making even code in extension modules that uses ``PyObject_IsInstance`` work, providing support for packages like ``pydanctic``. - Plugins: The Qt binding plugins now resolve ``pyqtgraph`` selection of binding by hard coding ``QT_LIB``. This will allow to resolve its own dynamic imports depending on that variable at compile time. At this time, the compile time analysis is not covering all cases yet, but we hope to get there. - macOS: Provide ``minOS`` for standalone builds, derived from the setting of the Python used to create it. - UI: Added new option ``--disable-ccache`` to prevent Nuitka from injecting ``ccache`` (Clang, gcc) and ``clcache`` (MSVC) for caching the C results of the compilation. - Plugins: Added experimental support for ``PyQt6``. While using ``PySide2`` or ``PySide6`` is very much recommended with Nuitka, this allows its use. - UI: Added option ``--low-memory`` to allow the user to specify that the compilation should attempt to use less memory where possible, this increases compile times, but might enable compilation on some weaker machines. Optimization ============ - Added dedicated attribute nodes for attribute values that match names of dictionary operations. These are optimized into dedicate nodes for methods of dictionaries should their expression have an exact dictionary shape. These in turn optimize calls on them statically into dictionary operations. This is done for all methods of ``dict`` for both Python2 and Python3, namely ``get``, ``items``, ``iteritems``, ``itervalues``, ``iterkeys``, ``viewvalues``, ``viewkeys``, ``pop``, ``setdefault``, ``has_key``, ``clear``, ``copy``, ``update``. The new operation nodes also add compile time optimization for being used on constant values where possible. - Also added dedicated attribute nodes for string operations. For operations, currently only part of the methods are done. These are currently only ``join``, ``strip``, ``lstrip``, ``rstrip``, ``partition``, ``rpartition``. Besides performance, this subset was enough to cover compile time evaluation of module name computation for ``importlib.import_module`` as done by SWIG bindings, allowing these implicit dependencies to be discovered at compile time without any help, marking a significant improvement for standalone usage. - Annotate type shape for dictionary ``in``/``not in`` nodes, this was missing unlike in the generic ``in``/``not in`` nodes. - Faster processing of "expression only" statement nodes. These are nodes, where a value is computed, but then not used, it still needs to be accounted for though, representing the value release. .. code:: python something() # ignores return value, means statement only node - Windows: Enabled LTO by default with MinGW64, which makes it produce much faster results. It now yield faster binaries than MSVC 2019 with pystone. - Windows: Added support for C level PGO (Profile Guided Optimization) with MSVC and MinGW64, allowing extra speed boosts from the C compilation on Windows as well. - Standalone: Better handling of ``requests.packages`` and ``six.moves``. The old handling could duplicate their code. Now uses a new mechanism to resolve metapath based importer effects at compile time. - Avoid useless exception checks in our dictionary helpers, as these could only occur when working with dictionary overloads, which we know to not be the case. - For nodes, have dedicated child mixin classes for nodes with a single child value and for nodes with a tuple of children, so that these common kind of nodes operate faster and don't have to check at runtime what type they are during access. - Actually make use of the egg cache. Nuitka was unpacking eggs in every compilation, but in wheel installs, these can be quite common and should be faster. - Star arguments annotated their type shape, but the methods to check for dictionary exactly were not affected by this preventing optimization in some cases. - Added ``anti-bloat`` configuration for main programs present in the modules of the standard library, these can be removed from the compilation and should lower dependencies detected. - Using static libpython with ``pyenv`` automatically. This should give both smaller (standalone mode) and faster results as is the case when using this feature.. - Plugins: Added improvements to the ``anti-bloat`` plugin for ``gevent`` to avoid including its testing framework. - Python3.9+: Faster calls into uncompiled functions from compiled code using newly introduced API of that version. - Statically optimize ``importlib.import_module`` calls with constant args into fixed name imports. - Added support for ``sys.version_info`` to be used as a compile time constant. This should enable many checks to be done at compile time. - Added hard import and static optimization for ``typing.TYPE_CHECKING``. - Also compute named import lookup through variables, expanding their use to more cases, e.g. like this: .. code:: import sys ... if sys.version_info.major >= 3: ... - Also optimize compile time comparisons through variable names if possible, i.e. the value cannot have changed. - Faster calls of uncompiled code with Python3.9 or higher avoiding DLL call overhead. Organisational ============== - Commercial: There are ``Buy Now`` buttons available now for the direct purchase of the `Nuitka Commercial `__ offering. Finally Credit Card, Google Pay, and Apple Pay are all possible. This is using Stripe. Get in touch with me if you want to use bank transfer, which is of course still best for me. - The main script runners for Python2 have been renamed to ``nuitka2`` and ``nuitka2-run``, which is consistent with what we do for Python3, and avoids issues where ``bin`` folder ends up in ``sys.path`` and prevents the loading of ``nuitka`` package. - Windows: Added support for Visual Studio 2022 by updating the inline copy of Scons used for Windows to version 4.3.0, on non Windows, the other ones will keep being used. - Windows: Requiring latest MinGW64 with version 11.2 as released by winlibs, because this is known to allow LTO, where previous releases were missing needed binaries. - Reject standalone mode usage with Apple Python, as it works only with the other supported Pythons, avoiding pitfalls in attempting to distribute it. - Move hosting of documentation to Sphinx, added Changelog and some early parts of API documentation there too. This gives much more readable results than what we have done so far with Nikola. More things will move there. - User Manual: Add description how to access code attributes in ``nuitka-project`` style options. - User Manual: Added commands used to generate performance numbers for Python. - User Manual: List other Python's for which static linking is supposed to work. - Improved help for ``--include-package`` with a hint how to exclude some of the subpackages. - Started using Jinja2 in code templates with a few types, adding basic infrastructure to do that. This will be expanded in the future. - Updated plugin documentation with more recent information. - Added Python flavor as detected to the ``--version`` output for improved bug reports. - Linux: Added distribution name to ``--version`` output for improved bug reports. - Always enable the ``gevent`` plugin, we want to achieve this for all plugins, and this is only a step in that direction. - Added project URLs for PyPI, so people looking at it from there have some immediate places to checkout. - Debian: Use common code for included PDF files, which have page styles and automatic corrections for ``rst2pdf`` applied. - Updated to latest ``black``, ``isort``, ``pylint`` versions. - The binary names for Python2 changed from ``nuitka`` and ``nuitka-run`` to ``nuitka2`` and ``nuitka2-run``. This harmonizes it with Python2 and avoids issues, where the ``bin`` folder in ``sys.path`` can cause issues with re-execution of Nuitka finding those to import. .. note:: You ought to be using ``python -m nuitka`` style of calling Nuitka anyway, as it gives you best control over what Python is used to run Nuitka, you can pick ``python2`` there if you want it to run with that, even with full path. Check the relevant section in the User Manual too. - Added support for Fedora 34 and Fedora 35. Cleanups ======== - In a change of mind ``--enable-plugin`` has become the only form to enable a plugin used in documentation and tests. - Massive cleanup of ``numpy`` and Qt binding plugins, e.g. ``pyside2``. Data files and DLLs are now provided through proper declarative objects rather than copied manually. The handling of PyQt5 from the plugin should have improved as a side effect. - Massive cleanups of all documentation in ReST format. Plenty of formatting errors were resolved. Many typos were identified and globally fixed. Spellings e.g. of "Developer Manual" are now enforced with automatic replacements. Also missing or wrong quotes were turned to proper methods. Also enforce code language for shell scripts to be the same everywhere. - Removed last usages of ``getPythonFlags()`` and made the function private, replacing their use with dedicated function to check for individual flags. - Avoid string comparison with ``nuitka.utils.getOS()`` and instead add accessors that are more readable, e.g. ``nuitka.utils.isMacOS()`` and put them to use where it makes sense. - Replaced usages of string tests in list of python flags specified, with functions that check for a specific name with a speaking function name. - Added mixin for expressions that have no side effect outside of their value, providing common method implementation more consistently. - Remove code geared to using old PyLint and on Python2, we no longer use that. Also removed annotations only used for overriding Python2 builtins from Nuitka code. - The PDF specific annotations were moved into being applied only in the PDF building step, avoiding errors for raw PDF directives. - Apply Visual Code autoformat to our Yaml files. This is unfortunately not and automatic formatting yet. - Introduce dedicated ``nuitka.utils.Json`` module, as we intend to expand its usage, e.g. for caching. - Replacing remaining usages of ``print`` functions with uses of ``nuitka.Tracing`` instead. - Massive cleanup of the ``gevent`` plugin, user proper method to execute code after module load, rather than source patching without need. The plugin no longer messes with inclusions that other code already provides for standalone. - Using own helper to update ``sys`` module attributes, to avoid errors from old C compilers, and also cleaning up using code to not have to cast on string constants. - More consistent naming of plugin classes, and enforce a relationship of detector class names to the names of detected plugins. The new naming consistency is now enforced. Tests ===== - Added CPython 3.10 test suite, it needs more work though. - Added generated test that exercises dictionary methods in multiple variations. - Test suite names were specified wrongly in a few of them. Summary ======= This release is again a huge step forward. It refines on PGO and LTO for C level to work with all relevant compilers. Internally Python level PGO is prepared, but only a future release will feature it. With that, scalability improvements as well as even more performance improvements will be unlocked. The amount of optimization added this time is even bigger, some of which unlocks static optimization of module imports, that previously would have to be considered implicit. This work will need one extra step, namely to also trace hard imports on the function level, then this will be an extremely powerful tool to solve these kinds of issues in the future. The next release will have this and go even further in this area. With the dictionary methods, and some string methods, also a whole new kind of optimization has been started. These will make working with ``dict`` containers faster, but obviously a lot of ground is to cover there still, e.g. ``list`` values are a natural target not yet started. Future releases will progress here. Type specialization for Python3 has not progressed though, and will have to be featured in a future releases though. For scalability, the ``anti-bloat`` work has continued, and this should be the last release, where this is not on by default. Compiling without it is something that is immediately noticeable in exploding module amounts. It is very urgently recommended to enable it for your compilations. The support for macOS has been refined, with version information being possible to add, and adding information to the binary about which OSes are supported, as well as rejecting Apple Python, which is only a trap if you want to deploy to other OS versions. More work will be needed to support ``pyenv`` or even Homebrew there too, for now CPython is still the recommended platform to use. This release achieves major compatibility improvements. And of course, the experimental support for 3.10 is not the least. The next release will strive to complete the support for it fully, but this should be usable at least, for now please stay on 3.9 if you can. *********************** Nuitka Release 0.6.17 *********************** This release has a focus on performance improvements, while also polishing plugins and adding many new features. Bug Fixes ========= - Fix, plugins were not catching being used on packages not installed. Fixed in 0.6.16.2 already. - macOS: Fix weaknesses in the ``otool`` parsing to determine DLL dependency parsing. Fixed in 0.6.16.2 already. - Linux: Allow onefile program args with spaces contained to be properly passed. Fixed in 0.6.16.3 already. - Windows: Avoid using less portable C function for ``%PID%`` formatting, which restores compilation on Windows 7 with old toolchains. Fixed in 0.6.16.3 already. - Standalone: Added support for ``fstrings`` package. Fixed in 0.6.16.3 already. - Compatibility: Fix, need to import ``.pth`` files after ``site`` module, not before. This was causing crashes on CentOS7 with Python2. Fixed in 0.6.16.3 already. - Compatibility: Fix, when extension modules failed to load, in some cases the ``ImportError`` was lost to a ``KeyError``. Fixed in 0.6.16.3 already. - Fix, linker resource modes ``code`` and ``linker`` were not working anymore, but are needed with LTO mode at least. Fixed in 0.6.16.3 already. - Standalone: Bytecode modules with null bytes in standard library, typically from disk corruption, were not handled properly. Fixed in 0.6.16.3 already. - Fix, failed ``.throw()`` into generators could cause corruption. Fixed in 0.6.16.4 already. - Python2: Fix, the bytecode compilation didn't respect the ``--python-flag=no_asserts`` mode. Fixed in 0.6.16.4 already. - Fix, calls were not annotating their arguments as escaped, causing corruption of mutable in static optimization. Fixed in 0.6.16.5 already. - Fix, some sequence objects, e.g. ``numpy.array`` actually implement in-place add operations that need to be called. Fixed in 0.6.16.5 already. - Windows: Fix, onefile binaries were not working after being signed. This now works. - Standalone: Added missing implicit dependency for ``sklearn``. - Compatibility: Modules giving ``SyntaxError`` from source were not properly handled, giving runtime ``ImportError``. Now they are giving ``SyntaxError``. - Fix, the LTO mode has issues with ``incbin`` usage on older gcc, so use ``linker`` mode when it is enabled. - Python3: Fix, locals dict codes were not properly checking errors that the mapping might raise when setting values. - Fix, modules named ``entry`` were causing compile time errors in the C stage. - macOS: Never include files from OS private frameworks in standalone mode. - Fix, the python flag ``--python-flag=no_warning`` wasn't working on all platforms. - Compatibility: Fix, the main code of the ``site`` module wasn't executing, so that its added builtins were not there. Of course, you ought to use ``--python-flag=no_site`` to not have it in the normal case. - Python2: Added code path to handle edited standard library source code which then has no valid bytecode file. - Anaconda: In module mode, the CondaCC wasn't recognized as form of gcc. - Fix, bytecode modules could shadow compiled modules of the same name. - Onefile: Fix, expansion of ``%PID%`` wasn't working properly on non-Windows, making temp paths less unique. The time stamp is not necessarily enough. - Fix, ``multiprocessing`` error exits from slave processes were not reporting tracebacks. - Standalone: Added ``xcbglintegrations`` to the list of sensible Qt plugins to include by default, otherwise rendering will be inferior. - Standalone: Added ``platformthemes`` to the list of sensible Qt plugins to include by default, otherwise file dialogs on non-Windows would be inferior. - Fix, created ``.pyi`` files were not ordered deterministically. - Standalone: Added support for ``win32file``. - Fix, namespace packages were not using runtime values for their ``__path__`` value. - Python3.7+: Fix, was leaking ``AttributeError`` exceptions during name imports. - Fix, standard library detection could fail for relative paths. New Features ============ - Added experimental support for C level PGO (Profile Guided Optimization), which runs your program and then uses feedback from the execution. At this time only gcc is supported, and only C compiler is collecting feedback. Check the User Manual for a table with current results. - macOS: Added experimental support for creating application bundles. For these, icons can be specified and console can be disabled. But at this time, onefile and accelerated mode are not yet usable with it, only standalone mode works. - Plugins: Add support for ``pkg_resources.require`` calls to be resolved at compile time. These are not working at runtime, but this avoids the issue very nicely. - Plugins: Massive improvements to the ``anti-bloat`` plugin, it can now make ``numpy``, ``scipy``, ``skimage``, ``pywt``, and ``matplotlib`` use much less packages and has better error handling. - Plugins: Added ``anti-bloat`` ability ability to append code to a module, which might get used in the future by other plugins that need some sort of post load changes to be applied. - Plugins: Added ability to replace code of functions at parse time, and use this in ``anti-bloat`` plugin to replace functions that do unnecessary stuff with variants that often just do nothing. This is illustrated here. .. code:: yaml gevent._util: description: "remove gevent release framework" change_function: "prereleaser_middle": "'(lambda data: None)'" "postreleaser_before": "'(lambda data: None)'" This example is removing ``gevent`` code that loads dependencies used for their CI release process, that need not be part of normal programs. - Added ability to persist source code changes done by plugins in the Python installation. This is considered experimental and needs write access to the Python installation, so this is best done in a virtualenv and it may confuse plugins. - Added support for ``multiprocessing.tracker`` and spawn mode for all platforms. For non-default modes outside of Windows, you need to ``--enable-plugin=multiprocessing`` to use these. - Plugins: Allow multiple entry points to be provided by one or several plugins for the same modules. These are now merged into one automatically. - Standalone: Fix for numpy not working when compiling with ``--python-flag=no_docstrings``. - Fix, method calls were not respecting descriptors provided by types with non-generic attribute lookups. - Windows: Add support for using self-compiled Python3 from the build folder too. - Added support for Nuitka-Python 2.7, which will be our faster Python fork. - Colorized output for error outputs encountered in Scons, these are now yellow for better recognition. Optimization ============ - Faster threading code was used for Python3.8 or higher, and this has been extended to 3.7 on Windows, but we won't be able to have it other platforms and not on earlier Python3 versions. - Faster calls esp. with keyword arguments. Call with keywords no longer create dictionaries if the call target supports that, and with 3.8 or higher, non-compiled code that allows vectorcall is taken advantage of. - Faster class creation that avoids creation of argument tuples and dictionaries. - Faster attribute check code in case of non-present attributes. - Faster unbound method calls, unlike bound methods calls these were not optimized as well yet. - Type shapes for star arguments are now known and used in optimization. .. code:: python def f(*args, **kwargs): type(args) # Statically known to be tuple type(kwargs) # Statically known to be dict - Python2: Faster old-style class creation. These are classes that do not explicitly inherit from ``object``. - Python2: Faster string comparisons for Python by specializing for the ``str`` type as well. - Python3: Added specialization for ``bytes`` comparisons too. These are naturally very much the same as ``str`` comparisons in Python2. - Added specialization for ``list`` comparisons too. We had them for ``tuples`` only so far. - Faster method calls when called from Python core, our ``tp_call`` slot wasn't as good as it can be. - Optimization: Faster deep copies of constants. This can speed up constant calls with mutable types. Before it was checking the type too often to be fast. - Allow using static linking with Debian Python giving much better performance with the system Python. This is actually a huge improvement as it makes things much faster. So far it's only automatically enabled for Python2, but it seems to work for Python3 on Debian too. Needs more tweaking in the future. - Optimization: Added ``functools`` module to the list of hard imports in preparation of optimizing ``functools.partial`` to work better with compiled functions. - Python2: Demote to ``xrange`` when iterating over ``range`` calls, even for small ranges, they are always faster. Previously this was only done for values with at least 256 values. - Enable LTO automatically for Debian Python, this also allows more optimization. - Enable LTO automatically for Anaconda with CondaCC on non-Windows, also allowing more optimization. Organisational ============== - Added section in the User Manual on how to deal with memory issues and C compiler bugs. This is a frequent topic and should serve as a pointer for this kind of issue. - The ``--lto`` option was changed to require an argument, so that it can also be disabled. The default is ``auto`` which is the old behaviour where it's enabled if possible. - Changed ``--no-progress`` to ``--no-progressbar`` in order to make it more clear what it's about. Previously it was possible to relate it to ``--show-progress``. - No longer require specific versions of dependencies in our ``requirements.txt`` and relegate those to only being in ``requirements-devel.txt`` such that by default Nuitka doesn't collide with user requirements on those same packages which absolutely all the time don't really make a difference. - Added ability to check all unpushed changes with pylint with a new ``./bin/check-nuitka-with-pylint --unpushed`` option. Before it was only possible to make the check (quickly) with ``--diff``, but that stopped working after commits are made. - Revived support for ``vmprof`` based analysis of compiled programs, but it requires a fork of it now. - Make Windows specific compiler options visible on all platforms. There is no point in them being errors, instead warnings are given when they are specified on non-Windows. - Added project variable ``Commercial`` for use in Nuitka project syntax. - Consistent use of metavars for nicer help output should make it more readable. - Avoid ``ast`` tree dumps in case of ``KeyboardInterrupt`` exceptions, they are just very noisy. Also not annotate where Nuitka was in optimization when a plugin is asking to ``sysexit``. Cleanups ======== - Encoding names for UTF8 in calls to ``.encode()`` were used inconsistent with and without dashes in the source code, added cleanup to autoformat that picks the one blessed. - Cleanup taking of runtime traces of DLLs used in preparation for using it in main code eventually, moving it to a dedicated module. - Avoid special names for Nuitka options in test runner, this only adds a level of confusion. Needs more work in future release. - Unify implementation to create modules into single function. We had 3 forms, one in recursion, one for main module, and one for plugin generated code. This makes it much easier to understand and use in plugins. - Further reduced code duplication between the two Scons files, but more work will be needed there. - Escaped variables are still known to be assigned/unassigned rather than unknown, allowing for many optimizations to still work on them., esp. for immutable value - Enhanced autoformat for rest documents, bullet list spacing is now consistent and spelling of organisational is unified automatically. - Moved icon conversion functionality to separate module, so it can be reused for other platforms more easily. Tests ===== - Removed ``reflected`` test, because of Nuitka special needs to restart with variable Python flags. This could be reverted though, since Nuitka no longer needs anything outside inline copies, and therefore no longer loads from site packages. - Use ``anti-bloat`` plugin in standalone tests of Numpy, Pandas and tests to reduce their compile times, these have become much more manageable now. - Enhanced checks for used files to use proper below path checks for their ignoring. - Remove reflected test, compiling Nuitka with Nuitka has gotten too difficult. - Verify constants integrity at program end in debug mode again, so we catch corruption of them in tests. Summary ======= This release is one of the most important ones in a long time. The PGO and LTO, and static libpython work make a big different for performance of created binaries. The amount of optimization added is also huge, calls are much faster now, and object creations too. These avoiding to go through actual dictionaries and tuples in most cases when compiled code interacts gives very significant gains. This can be seen in the increase of pystone performance. The new type specializations allow many operations to be much faster. More work will follow in this area and important types, ``str`` and ``int`` do not have specialized comparisons for Python3, holding it back somewhat to where our Python2 performance is for these things. For scalability, the ``anti-bloat`` work is extremely valuable, and this plugin should become active by default in the future, for now it must be strongly recommended. It needs more control over what parts you want to deactivate from it, in case of it causing problems, then we can and should do it. The support for macOS has been enhanced a lot, and will become perfect in the next release (currently develop). The bundle mode is needed for all kinds of GUI programs to not need a console. This platform is becoming as well supported as the others now. Generally this release marks a huge step forward. We hope to add Python level PGO in the coming releases, for type knowledge retrofitted without any annotations used. Benchmarks will become more fun clearly. *********************** Nuitka Release 0.6.16 *********************** This release is mostly polishing and new features. Optimization looked only at threading performance, and LTO improvements on Windows. Bug Fixes ========= - Fix, the ``pkg-resources`` failed to resolve versions for ``importlib.metadata`` from its standard library at compile time. Fixed in 0.6.15.1 already. - Standalone: Fix, ``--include-module`` was not including the module if it was an extension modules, but only for Python modules. Fixed in 0.6.15.1 already. - Standalone: Added missing implicit dependencies for ``gi.overrides``. Fixed in 0.6.15.1 already. - Python3.9: Fix, could crash when using generic aliases in certain configurations. Fixed in 0.6.15.2 already. - Fix, the tensorflow plugin needed an update due to changed API. Fixed in 0.6.15.3 already. - When error exiting Nuitka, it now closes any open progress bar for cleaner display. - Standalone: Added missing dependency for ``skimage``. - Standalone: The ``numpy`` plugin now automatically includes Qt backend if any of the Qt binding plugins is active. New Features ============ - Pyton3.5+: Added support for onefile compression. This is using ``zstd`` which is known to give very good compression with very high decompression, much better than e.g. ``zlib``. - macOS: Added onefile support. - FreeBSD: Added onefile support. - Linux: Added method to use tempdir onefile support as used on other platforms as an alternative to ``AppImage`` based. - Added support for recursive addition of files from directories with patterns. - Attaching the payload to onefile now has a progress bar too. - Windows: Prelimary support for the yet unfinished Nuitka-Python that allows static linking and higher performance on Windows, esp. with Nuitka. - Windows: In acceleration mode, for uninstalled Python, now a CMD file is created rather than copying the DLL to the binary directory. That avoids conflicts with architectures and of course useless file copies. - New abilities for plugin ``anti-bloat`` allow to make it an error when certain modules are imported. Added more specific options for usual trouble makes, esp. ``setuptools``, ``pytest`` are causing an explosion for some programs, while being unused code. This makes it now easier to oversee this. - It's now possible to override ``appdirs`` decision for where cache files live with an environment variable ``NUITKA_CACHE_DIR``. - The ``-o`` option now also works with onefile mode, it previously rejected anything but acceleration mode. Fixed in 0.6.15.3 already. - Plugins: It's now possible for multiple plugins to provide pre or post load code for the same module. - Added indications for compilation modes ``standalone`` and ``onefile`` to the ``__compiled__`` attribute. - Plugins: Give nicer error message in case of colliding command line options. Optimization ============ - Faster threading code is now using for Python3.8 or higher and not only 3.9, giving a performance boost, esp. on Windows. - Using ``--lto`` is now the default with MSVC 2019 or higher. This will given smaller and faster binaries. It has been available for some time, but not been the default yet. Cleanups ======== - Using different progress bar titles for C compilation of Python code and C compilation of onefile bootstrap. - Moved platform specific detections, for FreeBSD/OpenBSD/macOS out of the Scons file and to common Nuitka code, sometimes eliminating duplications with one version being more correct than the other. - Massive cleanup of datafile plugin, using pattern descriptions, so more code duplication can be removed. - More cleanup of the scons files, sharing more common code. Organisational ============== - Under the name Nuitka-Python we are now also developing a fork of CPython with enhancements, you can follow and joint it at https://github.com/Nuitka/Nuitka-Python but at this time it is not yet ready for prime time. - Onefile under Windows now only is temporary file mode. Until we figure out how to solve the problems with locking and caching, the mode where it installs to the AppData of the user is no longer available. - Renamed the plugin responsible for PyQt5 support to match the names of others. Note however, that at this time, PySide2 or PySide6 are to be recommended. - Make it clear that PySide 6.1.2 is actually going to be the supported version of PySide6. - Use MSVC in Github actions. Summary ======= This release had a massive focus on expanding existing features, esp. for onefile, and plugins API, such that we can now configure ``anti-bloat`` with yaml, have really nice datafile handling options, and have onefile on all OSes practically. *********************** Nuitka Release 0.6.15 *********************** This release polished previous work with bug fixes, but there are also important new things that help make Nuitka more usable, with one important performance improvement. Bug Fixes ========= - Fix, hard imports were not automatically used in code generation leading to errors when used. Fixed in 0.6.14.2 already. - Windows: Fix, ``clcache`` was disabled by mistake. Fixed in 0.6.14.2 already. - Standalone: Added data files for ``jsonschema`` to be copied automatically. - Standalone: Support for ``pendulum`` wasn't working anymore with the last release due to plugin interface issues. - Retry downloads without SSL if that fails, as some Python do not have working SSL. Fixed in 0.6.14.5 already. - Fix, the ``ccache`` path wasn't working if it contained spaces. Fixed in 0.6.14.5 already. - Onefile: For Linux and ARM using proper download off appimage. Fixed in 0.6.14.5 already. - Standalone: Added support for ``pyreadstat``. Fixed in 0.6.14.5 already. - Standalone: Added missing dependencies for ``pandas``. Fixed in 0.6.14.6 already. - Standalone: Some preloaded packages from ``.pth`` do not have a ``__path__``, these can and must be ignored. - Onefile: On Linux, the ``sys.argv[0]`` was not the original file as advertised. - Standalone: Do not consider ``.mesh`` and ``.frag`` files as DLls in the Qt bindings when including the qml support. This was causing errors on Linux, but was generally wasteful. - Fix, project options could be injected twice, which could lead to errors with options that were only allowed once, e.g. ``--linux-onefile-icon``. - Windows: When updating the resources in created binaries, treat all kinds of ``OSError`` with information output. - Onefile: Remove onefile target binary path at startup as well, so it cannot cause confusion after error exit. - Onefile: In case of error exit from ``AppImage``, preserve its outputs and attempt to detect if there was a locking issue. - Standalone: Scan package folders on Linux for DLLs too. This is necessary to properly handle ``PyQt5`` in case of Qt installed in the system as well. - Standalone: On Linux, standard QML files were not found. - Standalone: Enforce C locale when detecting DLLs on Linux, otherwise whitelisting messages didn't work properly on newer Linux. - Standalone: Added support for ``tzdata`` package data files. - Standalone: Added support for ``exchangelib``. - Python3.9: Fix, type subscripts could cause optimization errors. - UI: Project options didn't properly handle quoting of arguments, these are normally removed by the shell. - Linux: The default icon for Python in the system is now found with more version specific names and should work on more systems. - Standalone: Do not include ``libstdc++`` as it should come from the system rather. New Features ============ - Added plugin ``anti-bloat`` plugin, intended to fight bloat. For now it can make including certain modules an error, a warning, or force ``ImportError``, e.g. ``--noinclude-setuptools-mode=nofollow`` is very much recommended to limit compilation size. - The ``pkg-resources`` builtin now covers ``metadata`` and importlib_metadata packages for compile time version resolution as well. - Added support for ``PySide2`` on Python version before 3.6, because the patched code needs no workarounds. Fixed in 0.6.14.3 already. - Windows: Convert images to icon files on the fly. So now you can specify multiple PNG files, and Nuitka will create an icon out of that automatically. - macOS: Automatically download ``ccache`` binary if not present. - Plugins: New interface to query the main script path. This allows plugins to look at its directory. - UI: Output the versions of Nuitka and Python during compilation. - UI: Added option to control static linking. So far this had been enabled only automatically for cases where we are certain, but this allows to force enable or disable it. Now an info is given, if Nuitka thinks it might be possible to enable it, but doesn't do it automatically. - UI: Added ``--no-onefile`` to disable ``--onefile`` from project options. Optimization ============ - Much enhanced GIL interaction with Python3.9 giving a big speed boost and better threading behaviour. - Faster conversion of iterables to ``list``, if size can be know, allocation ahead saves a lot of effort. - Added support for ``GenericAlias`` objects as compile time constants. Organisational ============== - Enhanced Github issue raising instructions. - Apply ``rstfmt`` to all documentation and make it part of the commit hook. - Make sure to check Scons files as well. This would have caught the code used to disable ``clcache`` temporarily. - Do not mention Travis in PR template anymore, we have stopped using it. - Updated requirements to latest versions. - Bump requirements for development to 3.7 at least, toosl like black do not work with 3.6 anymore. - Started work on Nuitka Python, a CPython fork intended for enhanced performance and standalone support with Nuitka. Cleanups ======== - Determine system prefix without virtualenv outside of Scons, such that plugins can share the code. There was duplication with the ``numpy`` plugin, and this will only be more complete using all approaches. This also removes a lot of noise from the scons file moving it to shared code. - The Qt plugins now collect QML files with cleaner code. Tests ===== - Nicer error message if a wrong search mode is given. - Windows: Added timeout for determining run time traces with dependency walker, sometimes this hangs. - Added test to cover the zip importer. - Making use of project options in onefile tests, making it easier to execute them manually. Summary ======= For Windows, it's now easier than ever to create an icon for your deployment, because you can use PNG files, and need not produce ICO files anymore, with Nuitka doing that for you. The onefile for Linux had some more or less severe problems that got addressed, esp. also when it came to QML applications with PySide. On the side, we are preparing to greatly improve the caching of Nuitka, starting with retaining modules that were demoted to bytecode. There are changes in this release, to support that, but it's not yet complete. We expect that scalability will then be possible to improve even further. Generally this is mostly a maintenance release, which outside of the threading performance improvement has very little to offer for faster execution, but that actually does a lot. Unfortunately right now it's limited to 3.9, but some of the newer Python's will also be supported in later releases. *********************** Nuitka Release 0.6.14 *********************** This release has few, but important bug fixes. The main focus was on expanding standalone support, esp. for PySide2, but also and in general with plugins added that workaround ``pkg_resources`` usage for version information. Also an important new features was added, e.g. the project configuration in the main file should prove to be very useful. Bug Fixes ========= - Compatibility: Fix, modules that failed to import, should be retried on next import. So far we only ever executed the module body once, but that is not how it's supposed to be. Instead, only if it's in ``sys.modules`` that should happen, which is the case after successful import. - Compatibility: Fix, constant ``False`` values in right hand side of ``and``/``or`` conditions were generating wrong code if the left side was of known ``bool`` shape too. - Standalone: Fix, add ``styles`` Qt plugins to list of sensible plugins. Otherwise no mouse hover events are generated on some platforms. - Compatibility: Fix, relative ``from`` imports beyond level 1 were not loadingg modules from packages if necessary. Fixed in 0.6.13.3 already. - Standalone: The ``crypto`` DLL check for Qt bindings was wrong. Fixed in 0.6.13.2 already. - Standalone: Added experimental support for PySide6, but for good results, 6.1 will be needed. - Standalone: Added support for newer matplotlib. Fixed in 0.6.12.1 already. - Standalone: Reverted changes related to ``pkg_resources`` that were causing regressions. Fixed in 0.6.13.1 already. - Standalone: Adding missing implicit dependency for ``cytoolz`` package. Fixed in 0.6.13.1 already. - Standalone: Matching for package names to not suggest recompile for was broken and didn't match. Fixed in 0.6.13.1 already. New Features ============ - Added support for project options. When found in the filename provided, Nuitka will inject options to the commandline, such that it becomes possible to do a complex project with only using .. code:: bash python -m nuitka filename.py .. code:: python # Compilation mode, support OS specific. # nuitka-project-if: {OS} in ("Windows", "Linux"): # nuitka-project: --onefile # nuitka-project-if: {OS} not in ("Windows", "Linux"): # nuitka-project: --standalone # The PySide2 plugin covers qt-plugins # nuitka-project: --enable-plugin=pyside2 # nuitka-project: --include-qt-plugins=sensible,qml # The pkg-resources plugin is not yet automatic # nuitka-project: --enable-plugin=pkg-resources # Nuitka Commercial only features follow: # Protect the constants from being readable. # nuitka-project: --enable-plugin=data-hiding # Include datafiles for Qt into the binary directory. # nuitka-project: --enable-plugin=datafile-inclusion # nuitka-project: --qt-datadir={MAIN_DIRECTORY} # nuitka-project: --qt-datafile-pattern=*.js # nuitka-project: --qt-datafile-pattern=*.qml # nuitka-project: --qt-datafile-pattern=*.svg # nuitka-project: --qt-datafile-pattern=*.png Refer to the User Manual for a table of directives and the variables allowed to be used. - Added option to include whole data directory structures in standalone. The new option ``--include-data-dir`` was added and is mostly required for onefile mode, but recommended for standalone too. - Added ``pkg-resources`` plugin. This one can resolve code like this at compile time without any need for pip metadata to be present or used. .. code:: python pkg_resources.get_distribution("module_name").version pkg_resources.get_distribution("module_name").parsed_version - Standalone: Also process early imports in optimization. Otherwise plugins cannot work on standard library modules. This makes it possible to handle them as well. Optimization ============ - Faster binary operations. Applying lessons learnt during the enhancements for in-place operations that initially gave worse results than some manual code, we apply the same tricks for all binary operations, which speeds them up by significant margins, e.g. 30% for float addition, 25% for Python int addition, and still 6% for Python int addition. - More direct optimization of unary operations on constant value. Without this, ``-1`` was not directly a constant value, but had to go through the unary ``-`` operation, which it still does, but now it's done at tree building time. - More direct optimization for ``not`` in branches. Invertible comparisons, i.e. ``is``/``is not`` and ``in``/``not in`` do not have do be done during optimization. This mainly avoids noise during optimization from such unimportant steps. - More direct optimization for constant slices. These are used in Python3 for all subscripts, e.g. ``a[1:2]`` will use ``slice(1,2)`` effectively. For Python2 they are used less often, but still. This also avoids a lot of noise during optimization, mostly on Python3 - Scons: Avoid writing database to disk entirely. This saves a bit of disk churn and makes it unnecessary to specify the location such that it doesn't collide between Python versions. - For optimization passes, use previous max total as minimum for next pass. That will usually be a more accurate result, rather than starting from 1 again. Part of 0.6.13.1 already. - Enhancements to the branch merging improve the scalability of Nuitka somewhat, although the merging itself is still not very scalable, there are some modules that are very slow to optimize still. - Use ``orderset`` if available over the inline copy for ``OrderedSet`` which is much faster and improves Nuitka compile times. - Make ``pkgutil`` a hard import too, this is in preparation of more optimization for its functions. Organisational ============== - Upstream patches for ``PySide6`` have been contributed and merged into the development branch ``dev``. Full support should be available once this is released as part of 6.1 which is waiting for Qt 6.1 naturally. - Patches for ``PySide2`` are available to commercial customers, see `PySide2 support `__ page. - Formatted all documents with ``rstfmt`` and made that part of the commit hook for Nuitka. It now works for all documents we have. - Updated inline copy of ``tqdm`` to 4.59.0 which ought to address spurious errors given. - User Manual: Remove ``--show-progress`` from the tutoral. The default progress bar is then disabled, and is actually much nicer to use. - Developer Manual: Added description of how context managers should be named. - Cleanup language for some warnings and outputs. It was still using obsolete "recursion" language rather than talking about "following imports", which is the new one. Cleanups ======== - Remove dead code related to constants marshal, the data composer has replaced this. - Avoid internal API usage for loading extension modules on Linux, there is a function in ``sys`` module to get the ld flags. Tests ===== - Fix, the ``only`` mode wasn't working properly. - Use new project options feature for specific options in basic tests allowing to remove them from the test runner. Summary ======= For PySide2 things became more perfect, but it takes upstream patches unfortunately such that only PySide6.1 will be working out of the box outside of the commercial offering. We will also attempt to provide workarounds, but there are some things that cannot be done that way. This release added some more scalability to the optimization process, however there will be more work needed to make efficient branch merges. For onefile, a feature to include whole directories had been missing, and could not easily be achieved with the existing options. This further rounds this up, now what's considered missing is compression and macOS support, both of which should be coming in a future release. For the performance side of things, the binary operator work can actually yield pretty good gains, with double digit improvements, but this covers only so much. Much more C types and better type tracing would be needed, but there was no progress on this front. Future releases will have to revisit the type tracing to make sure, we know more about loop variables, etc. so we can achieve the near C speed we are looking for, at least in the field of ``int`` performance. This release has largely been driven by the `Nuitka Commercial `__ offering and needs for compatibility with more code, which is of course always a good thing. *********************** Nuitka Release 0.6.13 *********************** This release follows up with yet again massive improvement in many ways with lots of bug fixes and new features. Bug Fixes ========= - Windows: Icon group entries were not still not working properly in some cases, leading to no icon or too small icons being displayed. Fixed in 0.6.12.2 already. - Windows: Icons and version information were copied from the standalone executable to the onefile executable, but that failed due to race situations, sometimes reproducible. Instead we now apply things to both independently. Fixed in 0.6.12.2 already. - Standalone: Fixup scanning for DLLs with ``ldconfig`` on Linux and newer versions making unexpected outputs. Fixed in 0.6.12.2 already. - UI: When there is no standard input provided, prompts were crashing with ``EOFError`` when ``--assume-yes-for-downloads`` is not given, change that to defaulting to ``"no"`` instead. Fixed in 0.6.12.2 already. - Windows: Detect empty strings for company name, product name, product and file versions rather than crashing on them later. Them being empty rather than not there can cause a lot of issues in other places. Fixed in 0.6.12.2 already. - Scons: Pass on exceptions during execution in worker threads and abort compilation immediately. Fixed in 0.6.12.2 already. - Python3.9: Still not fully compatible with typing subclasses, the enhanced check is now closely matching the CPython code. Fixed in 0.6.12.2 already. - Linux: Nicer error message for missing ``libfuse`` requirement. - Compatibility: Lookups on dictionaries with ``None`` value giving a ``KeyError`` exception, but with no value, which is not what CPython does. - Python3.9: Fix, future annotations were crashing in debug mode. Fixed in 0.6.12.3 already. - Standalone: Corrections to the ``glfw`` were made. Fixed in 0.6.12.3 already. - Standalone: Added missing ìmplicit dependency for ``py.test``. Fixed in 0.6.12.3 already. - Standalone: Adding missing implicit dependency for ``pyreadstat``. - Windows: Added workaround for common clcache locking problems. Since we use it only inside a single Scons process, we can avoiding using Windows mutexes, and use a process level lock instead. - Plugins: Fix plugin for support for ``eventlet``. Fixed in 0.6.12.3 already. - Standalone: Added support for latest ``zmq`` on Windows. - Scons: the ``--quiet`` flag was not fully honored yet, with Scons still making a few outputs. - Standalone: Added support for alternative DLL name for newer ``PyGTK3`` on Windows. Fixed in 0.6.12.4 already. - Plugins: Fix plugin for support for ``gevent``. Fixed in 0.6.12.4 already. - Standalone: Added yet another missing implicit dependency for ``pandas``. - Plugins: Fix, the ``qt-plugins`` plugin could stumble over ``.mesh`` files. - Windows: Fix, dependency walker wasn't properly working with unicode ``%PATH%`` which could e.g. happen with a virtualenv in a home directory that requires them. - Python3: Fixed a few Python debug mode warnings about unclosed files that have sneaked into the codebase. New Features ============ - Added new options ``--windows-force-stdout-spec`` and ``--windows-force-stderr-spec`` to force output to files. The paths provided at compile time can resolve symbolic paths, and are intended to e.g. place these files near the executable. Check the User Manual for a table of the currently supported values. At this time, the feature is limited to Windows, where the need arose first, but it will be ported to other supported OSes eventually. These are most useful for programs run as ``--windows-disable-console`` or with ``--enable-plugin=windows-service``. - Windows: Added option ``--windows-onefile-tempdir-spec`` to provide the temporary directory used with ``--windows-onefile-tempdir`` in onefile mode, you can now select your own pattern, and e.g. hardcode a base directory of your choice rather than ``%TEMP``. - Added experimental support for ``PySide2`` with workarounds for compiled methods not being accepted by its core. There are known issues with ``PySide2`` still, but it's working fine for some people now. Upstream patches will have to be created to remove the need for workarounds and full support. Optimization ============ - Use binary operation code for their in-place variants too, giving substantial performance improvements in all cases that were not dealt with manually already, but were covered in standard binary operations. Until now only some string, some float operations were caught sped up, most often due to findings of Nuitka being terribly slower, e.g. not reusing string memory for inplace concatenation, but now all operations have code that avoids a generic code path, that is also very slow on Windows due calling to using the embedded Python via API being slow. - For mixed type operations, there was only one direction provided, which caused fallbacks to slower forms, e.g. with ``long`` and ``float`` values leading to inconsistent results, such that ``a - 1`` and ``1 - a`` being accelerated or not. - Added C boolean optimization for a few operations that didn't have it, as these allow to avoid doing full computation of what the object result would have to do. This is not exhausted fully yet. - Python3: Faster ``+``/``-``/``+=``/``-=`` binary and in-place operations with ``int`` values providing specialized code helpers that are much faster, esp. in cases where no new storage is allocated for in-place results and where not a lot of digits are involved. - Python2: The Python3 ``int`` code is the Python2 ``long`` type and benefits from the optimization of ``+``/``-``/``+=``/``-=`` code as well, but of course its use is relatively rare. - Improved ``__future__`` imports to become hard imports, so more efficient code is generated for them. - Counting of instances had a runtime impact by providing a ``__del__`` that was still needed to be executed and limits garbage collection on types with older Python versions. - UI: Avoid loading ``tqdm`` module before it's actually used if at all (it may get disabled by the user), speeding up the start of Nuitka. - Make sure to optimize internal helpers only once and immediately, avoiding extra global passes that were slowing down Python level compilation by of large programs by a lot. - Make sure to recognize the case where a module optimization can provide no immediate change, but only after a next run, avoiding extra global passes originating from these, that were slowing down compilation of large programs by a lot. Together with the other change, this can improve scalability by a lot. - Plugins: Remove implicit dependencies for ``pkg_resources.extern`` and use aliases instead. Using one of the packages, was causing all that might be used, to be considered as used, with some being relatively large. This was kind of a mistake in how we supported this so far. - Plugins: Revamped the ``eventlet`` plugin, include needed DNS modules as bytecode rather than as source code, scanning them with ``pkgutil`` rather than filesystem, with much cleaner code in the plugin. Organisational ============== - Removed support for ``pefile`` dependency walker choice and inline copy of the code. It was never as good giving incomplete results, and after later improvements, slower, and therefore has lost the original benefit over using Dependency Walker that is faster and more correct. - Added example for onefile on Windows with the version information and with the temporary directory mode. - Describe difference in file access with onefile on Windows, where ``sys.argv[0]`` and ``os.path.dirname(__file__)`` will be different things. - Added inline copy of ``tqdm`` to make sure it's available for progress bar output for 2.7 or higher. Recommend having it in the Debian package. - Added inline copy of ``colorama`` for use on Windows, where on some terminals it will give better results with the progress bar. - Stop using old PyLint for Python2, while it would be nice to catch errors, the burden of false alarms seems to high now. - UI: Added even more checks on options that make no sense, made sure to do this only after a possible restart in proper environment, so warnings are not duplicated. - For Linux onefile, keep appimage outputs in case of an error, that should help debugging it in case of issues. - UI: Added traces for plugin provided implicit dependencies leading to inclusions. - Added inline copy of ``zstd`` C code for use in decompression for the Windows onefile bootstrap, not yet used though. - Added checks to options that accept package names for obvious mistakes, such that ``--include-package-data --mingw64`` will not swallow an option, as that is clearly not a package name, that would hide that option, while also not having any intended effect. - Added ignore list for decision to recompile extension modules with available source too. For now, Nuitka will not propose to recompile ``Cython`` modules that are very likely not used by the program anyway, and also not for ``lxml`` until it's clear if there's any benefit in that. More will be added in the future, this is mostly for cases, where Cython causes incompatibilities. - Added support for using abstract base classes in plugins. These are not considered for loading, and allow nicer implementation of shared code, e.g. between ``PyQt5`` and ``PySide2`` plugins, but allow e.g. to enforce the provision of certain overloads. - User Manual: Remove the instruction to install ``clcache``, since it's an inline copy, this makes no sense anymore and that was obsolete. - Updated PyLint to latest versions, and our requirements in general. Cleanups ======== - Started removal of PyLint annotations used for old Python2 only. This will be a continuous action to remove these. - Jinja2 based static code generation for operations was cleaned up, to avoid code for static mismatches in the result C, avoiding language constructs like ``if (1 && 0)`` with sometimes larger branches, replacing it with Jinja2 branches of the ``{% if ... %}`` form. - Jinja2 based Python2 ``int`` code was pioniering the use of macros, but this was expanded to allow kinds of types for binary operations, allow their reuse for in-place operation, with these macros making returns via goto exits rather than return statements in a function. Landing pads for these exits can then assign target values for in-place different from what those for binary operation result return do. - Changed the interfacing of plugins with DLL dependency detection, cleaning up the interactions considerably with more unified code, and faster executing due to cached plugin decisons. - Integrate manually provided slot function for ``unicode`` and ``str`` into the standard static code generation. Previously parts were generated and parts could be generated, but also provided with manual code. The later is now all gone. - Use a less verbose progress bar format with less useless infos, making it less likely to overflow. - Cleanup how payload data is accessed in Windows onefile bootstrap, preparing the addition of decompression, doing the reading from the file in only one dedicated function. - When Jinja2 generated exceptions in the static code, it is now done via proper Jinja2 macros rather than Python code, and these now avoid useless Python version branches where possible, e.g. because a type like ``bytes`` is already Python version specific, with the goal to get rid of ``PyErr_Format`` usage in our generated static code. That goal is future work though. - Move safe strings helpers (cannot overflow) to a dedicated file, and remove the partial duplication on the Windows onefile bootstrap code. - The Jinja2 static code generation was enhanced to track the usage of labels used as goto targets, so that error exits, and value typed exits from operations code no longer emitted when not used, and therefore labels that are not used are not present. - For implicit dependencies, the parsing of the ``.pyi`` file of a module no longer emits a dependency on the module itself. Also from plugins, these are now filtered away. Tests ===== - Detect if onefile mode has required downloads and if there is user consent, otherwise skip onefile tests in the test runner. - Need to also allow accesses to files via short paths on Windows if these are allowed long paths. - The standalone tests on Windows didn't actually take run time traces and therefore were ineffective. - Added standalone test for ``glfw`` coverage. - Construct based tests for in-place operations are now using a value for the first time, and then a couple more times, allowing for real in-place usage, so we are sure we measure correctly if that's happening. Summary ======= Where the big change of the last release were optimization changes to reduce the global passes, this release addresses remaining causes for extra passes, that could cause these to still happen. That makes sure, Nuitka scalability is very much enhanced in this field again. The new features for forced outputs are at this time Windows only and make a huge difference when it comes to providing a way to debug Windows Services or programs in general without a console, i.e. a GUI program. These will need even more specifiers, e.g. to cover program directory, rather than exe filename only, but it's a very good start. On the tooling side, not a lot has happened, with the clcache fix, it seems that locking issues on Windows are gone. The plugin changes from previous releases had left a few of them in a state where they were not working, but this should be restored. Interaction with the plugins is being refined constantly, and this releases improved again on their interfaces. It will be a while until this becomes stable. Adding support for PySide2 is a headline feature actually, but not as perfect as we are used to in other fields. More work will be needed, also in part with upstream changes, to get this to be fully supported. For the performance side of things, the in-place work and the binary operations work has taken proof of concept stuff done for Python2 and applied it more universally to Python3. Until we cover all long operations, esp. ``*`` seems extremely important and is lacking, this cannot be considered complete, but it gives amazing speedups in some cases now. Future releases will revisit the type tracing to make sure, we know more about loop variables, to apply specific code helpers more often, so we can achieve the near C speed we are looking for in the field of ``int`` performance. *********************** Nuitka Release 0.6.12 *********************** This release is yet again a massive improvement in many ways with lots of bug fixes and new features. Bug Fixes ========= - Windows: Icon group entries were not working properly in some cases, leading to no icon or too small icons being displayed. - Standalone: The PyQt implicit dependencies were broken. Fixed in 0.6.11.1 already. - Standalone: The datafile collector plugin was broken. Fixed in 0.6.11.3 already. - Standalone: Added support for newer forms of ``matplotlib`` which need a different file layout and config file format. Fixed in 0.6.11.1 already. - Plugins: If there was an error during loading of the module or plugin, it could still be attempted for use. Fixed in 0.6.11.1 already. - Disable notes given by gcc, these were treated as errors. Fixed in 0.6.11.1 already. - Windows: Fix, spaces in gcc installation paths were not working. Partially fixed in 0.6.11.4 already. - Linux: Fix, missing onefile icon error message was not complete. Fixed in 0.6.11.4 already. - Standalone: Workaround ``zmq`` problem on Windows by duplicating a DLL in both expected places. Fixed in 0.6.11.4 already. - Standalone: The ``dill-compat`` plugin wasn't working anymore. Fixed in 0.6.11.4 already. - Windows: Fix mistaken usage of ``sizeof`` for wide character buffers. This caused Windows onefile mode in temporary directory. Fixed in 0.6.11.4 already. - Windows: Fix, checking subfolder natured crashed with different drives on Windows. Fixed in 0.6.11.4 already. - Windows: Fix, usage from MSVC prompt was no longer working, detect used SDK properly. Fixed in 0.6.11.4 already. - Windows: Fix, old clcache installation uses pth files that prevented our inline copy from working, workaround was added. - Windows: Also specify stack size to be used when compiling with gcc or clang. - Fix, claim of Python 3.9 support also in PyPI metadata was missing. Fixed in 0.6.11.5 already. - Python3.9: Subscripting ``type`` for annotations wasn't yet implemented. - Python3.9: Better matching of types for metaclass selection, generic aliases were not yet working, breaking some forms of type annotations in base classes. - Windows: Allow selecting ``--msvc-version`` when a MSVC prompt is currently activated. - Windows: Do not fallback to using gcc when ``--msvc-version`` has been specified. Instead it's an error if that fails to work. - Python3.6+: Added support for ``del ()`` statements, these have no effect, but were crashing Nuitka. .. code:: python del a # standard form del a, b # same as del a; del b del (a, b) # braces are allowed del () # allowed for consistency, but wasn't working. - Standalone: Added support for ``glfw`` through a dedicated plugin. - macOS: Added support for Python3 from system and CPython official download for latest OS version. New Features ============ - UI: With ``tqdm`` installed alongside Nuitka, experimental progress bars are enabled. Do not use `` --show-progress`` or ``--verbose`` as these might have to disable it. - Plugins: Added APIs for final processing of the result and onefile post processing. - Onefile: On Windows, the Python process terminates with ``KeyboardInterrupt`` when the user sends CTRL-break, CTRL-C, shutdown or logoff signals. - Onefile: On Windows, in case of the launching process terminating unexpectedly, e.g. due to Taskmanager killing it, or a ``os.sigkill`` resulting in that, the Python process still terminates with ``KeyboardInterrupt``. - Windows: Now can select icons by index from files with multiple icons. Optimization ============ - Avoid global passes caused by module specific optimization. The variable completeness os now traced per module and function scope, allowing a sooner usage. Unused temporary variables and closure variables are remove immediately. Recognizing possible auto releases of parameter variables is also instantly. This should bring down current passes from 5-6 global passes to only 2 global passes in the normal case, reducing frontend compile times in some cases massively. - Better unary node handling. Dedicated nodes per operation allow for more compact memory usage and faster optimization. - Detect flow control and value escape for the repr of node based on type shape. - Enhanced optimization of caught exception references, these never raise or have escapes of control flow. - Exception matching operations are more accurately annotated, and may be recognized to not raise in more cases. - Added optimization for the ``issubclass`` built-in. - Removed scons caching as used on Windows entirely. We should either be using ``clcache`` or ``ccache`` automatically now. - Make sure to use ``__slots__`` for all node classes. In some cases, mixins were preventing the feature from being it. We now enforce their correct specification of slots, which makes sure we can't miss it anymore. This should again gain more speed and save memory at frontend compile time. - Scons: Enhanced gcc version detection with improved caching behavior, this avoids querying the same gcc binary twice. Organisational ============== - The description of Nuitka on PyPI was absent for a while. Added back by adding long description of the project derived from the README file. - Avoid terms ``blacklist``, ``whilelist`` and ``slave`` in the Nuitka code preferring ``blocklist``, ``ignorelist`` and ``child`` instead, which are actually more clear anyway. We follow a general trend to do this. - Configured the inline copy of Scons so pylance has an easier time to find it. - The git commit hook had stopped applying diffs with newest git, improved that. - Updated description for adding new CPython test suite. - Using https URLs for downloading dependency walker, for it to be more secure. - The commit hook can now be disabled, it's in the Developer Manual how to do it. Cleanups ======== - Moved unary operations to their own module, the operators module was getting too crowded. - The scons files for Python C backend and Windows onefile got cleaned up some more and moved more common code to shared modules. - When calling external tools, make sure to provide null input where possible. - Unified calling ``install_name_tool`` into a single method for adding rpath and name changes both at the same time. - Unified how tools like ``readelf``, ``ldconfig`` etc. are called and error exits and outputs checked to make sure we don't miss anything as easily. Tests ===== - Adapted for some openSUSE specific path usages in standalone tests. - Basic tests for onefile operation and with termination signal sent were added. Summary ======= The big changes in this release are the optimization changes to reduce the global passes and the memory savings from other optimization. These should again make Nuitka more scalable with large projects, but there definitely is work remaining. Adding nice stopping behaviour for the Onefile mode on Windows is seemingly a first, and it wasn't easy, but it will make it more reliable to users. Also tooling of gcc and MSVC on Windows got a lot more robust, covering more cases, and macOS support has been renewed and should be a lot better now. The progress bar is a nice touch and improves the overall feel of the compilation process, but obviously we need to aim at getting faster overall still. For projects using large dependencies, e.g. Pandas the compilation is still far too slow and that will need work on caching frontend results, and better optimization and C code generation for the backend. *********************** Nuitka Release 0.6.11 *********************** This release is a massive improvement in many ways with lots of bug fixes and new features. Bug Fixes ========= - Fix, the ``.pyi`` file parser didn't handle relative imports. Fixed in 0.6.10.1 already. - Windows: Fix, multiprocessing plugin was not working reliable following of imports from the additional entry point. Fixed in 0.6.10.1 already. - Pipenv: Workaround parsing issue with our ``setup.py`` to allow installation from Github. Fixed in 0.6.10.1 already. - Merging of branches in optimization could give indetermistic results leading to more iterations than necessary. Fixed in 0.6.10.1 already. - Windows: Avoid profile powershell when attempting to resolve symlinks. Fixed in 0.6.10.1 already. - Windows: Fix, always check for stdin, stdout, and stderr presence. This was so far restricted to gui mode applications, but it seems to be necessary in other situations too. Fixed in 0.6.10.1 already. - Python2: Fix, ``--trace-execution`` was not working for standalone mode but can be useful for debugging. Fixed in 0.6.10.1 already. - Windows: Onefile could run into path length limits. Fixed in 0.6.10.3 already. - Windows: The winlib gcc download link became broken and was updated. Fixed in 0.6.10.3 already. - Plugins: The "__main__" module was not triggering all plugin hooks, but it needs to for completeness. - Standalone: Fix, symlinked Python installations on Windows were not working, with dependency walker being unable to look into these. Fixed in 0.6.10.4 already. - Standalone: Fix support for numpy on Windows and macOS, the plugin failed to copy important DLLs. Fixed in 0.6.10.4 already. - Python3: For versions before 3.7, the symlink resolution also needs to be done, but wasn't handling the bytes output yet. Fixed in 0.6.10.4 already. - Fix, folder based inclusion would both pick up namespace folders and modules of the same name, crashing the compilation due to conflicts. Fixed in 0.6.10.4 already. - Fix, the ``--lto`` wasn't used for clang on non-Windows yet. - Fix, the order of locals dict releases wasn't enforced, which could lead to differences that break caching of C files potentially. Fixed in 0.6.10.5 already. - Fix, ``hash`` nodes didn't consider if their argument was raising, even if the type of the argument was ``str`` and therefore the operation should not. Fixed in 0.6.10.5 already. - Fix, need to copy type shape and escape description for the replacement inverted comparisons when used with ``not``, otherwise the compilation can crash as these are expected to be present at all times. Fixed in 0.6.10.5 already. - Fix, some complex constant values could be confused, e.g. ``-0j`` and ``0j``. These corner cases were not properly considered in the constant loading code, only for ``float`` so far. - Standalone: Fix, bytecode only standard library modules were not working. This is at least used with Fedora 33. - Linux: Fix, extension modules compiled with ``--lto`` were not working. - Windows: Retry if updating resources fails due to Virus checkers keeping files locked. - Plugins: Pre- and postload code of modules should not be allowed to cause ``ImportError``, as these will be invisible to the other parts of optimization, instead make them unraisable error traces. - Standalone: Adding missing import for SciPy 1.6 support. - Windows: Fix, only export required symbols when using MinGW64 in module mode. New Features ============ - Python3.9: Added official support for this version. - Onefile: Added command line options to include data files. These are ``--include-package-data`` which will copy all non-DLLs and non-Python files of package names matching the pattern given. And ``--include-data-file`` takes source and relative target file paths and copies them. For onefile this is the only way to include files, for standalone mode they are mostly a convenience function. - Onefile: Added mode where the file is unpacked to a temporary folder before running instead of doing it to appdata. - Onefile: Added linux specific options ``--linux-onefile-icon`` to allow provision of an icon to use in onefile mode on Linux, so far this was only available as the hard coded path to a Python icon, which also didn't exist on all platforms. - UI: Major logging cleanup. Everything is now using our tracing classes and even error exits go through there and are therefore colored if possible. - Plugins: Make it easier to integrate commercial plugins, now only an environment variable needs to point to them. - UI: Enhanced option parsing gives notes. This complains about options that conflict or that are implied in others. Trying to catch more usage errors sooner. - Plugins: Ignore exceptions in buggy plugin code, only warn about them unless in debug mode, where they still crash Nuitka. - Scons: More complete scons report files, includes list values as well and more modes used. - Windows: The ``clcache`` is now included and no longer used from the system. - Output for ``clcache`` and ``ccache`` results got improved. - Enhanced support for ``clang``, on Windows if present near a ``gcc.exe`` like it is the case for some winlibs downloads, it will be used. To use it provide ``--mingw64 --clang`` both. Without the first one, it will mean ``clangcl.exe`` which uses the MSVC compiler as a host. Optimization ============ - Some modules had very slow load times, e.g. if they used many list objects due to linear searches for memory deduplication of objects. We now have dictionaries of practically all constant objects loaded, making these more instant. - Use less memory at compile time due using ``__slots__`` for all node types, finally figured out, how to achieve this with multiple inheritance. - Use hedley for compiler macros like ``unlikely`` as they know best how to do these. - Special case the merging of 2 branches avoiding generic code and being much faster. - Hard imports have better code generated, and are being optimized into for the few standard library modules and builtin modules we handle, they also now annotate the type shape to be module. - No longer annotate hard module import attribute lookups as control flow escapes. Not present attributes are changed into static raises. Trust for values is configured for a few values, and experimental. - Avoid preloaded packages for modules that have no side effects and are in the standard library, typically ``.pth`` files will use e.g. ``os`` but that's not needed to be preserved. - Use ``incbin`` for including binary data through inline assembly of the C compiler. This covers many more platforms than our previous linker option hacks, and the fallback to generated C code. In fact everything but Windows uses this now. Organisational ============== - Windows: For Scons we now require a Python 3.5 or higher to be installed to use it. - Windows: Removed support for gcc older than version 8. This specifically affects CondaCC and older MinGW64 installations. Since Nuitka can now download the MinGW64 10, there is no point in having these and they cause issues. - We took over the maintenance of clcache as Nuitka/clcache which is not yet ready for public consumption, but should become the new source of clache in the future. - Include an inline copy of clcache in Nuitka and use it on Windows for MSVC and ClangCL. - Removed compatibility older aliases of follow option, ``--recurse-*`` and require ``--follow-*`` options to be used instead. - For pylint checking, the tool now supports a ``--diff`` mode where only the changed files get checked. This is much faster and allows to do it more often before commit. - Check the versions of isort and black when doing the autoformat to avoid using outdated versions. - Handling missing pylint more gracefully when checking source code quality. - Make sure to use the codespell tool with Python3 and make sure to error exit when spelling problems were found, so we can use this in Github actions too. - Removed Travis config, we now only use Github actions. - Removed landscape config, it doesn't really exist anymore. - Bumped all PyPI dependnecies to their latest versions. - Recommend ccache on Debian, as we now consider the absence of ccache something to warn about. - Plugins: The DLLs asked for by plugins that are not found are no longer warned about. - Allow our checker and format tools to run on outside of tree code. We are using that for Nuitka/clcache. - Added support for Fedora 33 and openSUSE 15.3, as well as Ubuntu Groovy. - Windows: Check if Windows SDK is installed for MSVC and ClangCL. - Windows: Enhanced wording in case no compiler was found. No longer tell people how to manually install MinGW64, that is no longer necessary and ``pywin32`` is not needed to detect MSVC, so it's not installed if not found. - Detect "embeddable Python" by missing include files, and reject it with proper error message. - Added onefile and standalone as a use case to the manual and put also the DLL and data files problems as typically issues. Cleanups ======== - Avoid decimal and string comparisons for Python versions checks, these were lazy and are going to break once 3.10 surfaces. In testing we now use tuples, in Nuitka core hexacimal values much like CPython itself does. - Stop using subnode child getters and setters, and instead only use subnode attributes. This was gradually changed so far, but in this release all remaining uses have migrated. This should also make the optimization stage go faster. - Change node constructors to not use a decorator to resolve conflicts with builtin names, rather handle these with manual call changes, the decorator only made it difficult to read and less performant. - Move safe string helpers to their own dedicated helper file, allowing for reuse in plugin code that doesn't want to use all of Nuitka C helpers. - Added utils code for inline copy imports, as we use that for quite a few things now. - Further restructured the Scons files to use more common code. - Plugins: The module name objects now reject many ``str`` specific APIs that ought to not be used, and the code got changed to use these instead, leading to cleaner and more correct usages. - Using named tuples to specify included data files and entry points. - Use ``pkgutil`` in plugins to scan for modules rather than listing directories. Tests ===== - New option to display executed commands during comparisons. - Added test suite for onefile testing. Summary ======= This release has seen Python3.9 and Onefile both being completed. The later needs compression added on Windows, but that can be added in a coming release, for now it's fully functional. The focus clearly has been on massive cleanups, some of which will affect compile time performance. There is relatively little new optimization otherwise. The adoption of clcache enables a very fast caching, as it's now loaded directly into the Scons process, avoiding a separate process fork. Generally a lot of polishing has been applied with many cleanups lowering the technical debt. It will be interesting to see where the hard module imports can lead us in terms of more optimization. Static optimization of the Python version comparisons and checks is needed to lower the amount of imports to be processed. Important fixes are also included, e.g. the constants loading performance was too slow in some cases. The ``multiprocessing`` on Windows and ``numpy`` plugins were regressed and finally everything ought to be back to working fine. Future work will have to aim at enhanced scalability. In some cases, Nuitka still takes too much time to compile if projects like Pandas include virtually everything installed as an option for it to use. *********************** Nuitka Release 0.6.10 *********************** This release comes with many new features, e.g. onefile support, as well as many new optimization and bug fixes. Bug Fixes ========= - Fix, was memory leaking arguments of all complex call helper functions. Fixed in 0.6.9.6 already. - Plugins: Fix, the dill-compat code needs to follow API change. Fixed in 0.6.9.7 already. - Windows: Fixup for multiprocessing module and complex call helpers that could crash the program. Fixed in 0.6.9.7 already. - Fix, the frame caching could leak memory when using caching for functions and generators used in multiple threads. - Python3: Fix, importing an extension module below a compiled module was not possible in accelerated mode. - Python3: Fix, keyword arguments for ``open`` built-in were not fully compatible. - Fix, the scons python check should also not accept directories, otherwise strange misleading error will occur later. - Windows: When Python is installed through a symbolic link, MinGW64 and Scons were having issues, added a workaround to resolve it even on Python2. - Compatibility: Added support for ``co_freevars`` in code objects, e.g. newer matplotlib needs this. - Standalone: Add needed data files for gooey. Fixed in 0.6.9.4 already. - Scons: Fix, was not respecting ``--quiet`` option when running Scons. Fixed in 0.6.9.3 already. - Scons: Fix, wasn't automatically detecting Scons from promised paths. Fixed in 0.6.9.2 already. - Scons: Fix, the clcache output parsing wasn't robust enough. Fixed in 0.6.9.1 already. - Python3.8: Ignore all non-strings provided in doc-string fashion, they are not to be considered. - Fix, ``getattr``, ``setattr`` and ``hasattr`` could not be used in finally clauses anymore. Fixed in 0.6.9.1 already. - Windows: For Python3 enhanced compatibility for Windows no console mode, they need a ``sys.stdin`` or else e.g. ``input`` will not be compatible and raise ``RuntimeError``. New Features ============ - Added experimental support for Python 3.9, in such a way that the CPython3.8 test suite passes now, the 3.9 suite needs investigation still, so we might be missing new features. - Added experimental support for Onefile mode with ``--onefile`` that uses ``AppImage`` on Linux and our own bootstrap binary on Windows. Other platforms are not supported at this time. With this, the standalone folder is packed into a single binary. The Windows variant currently doesn't yet do any compression yet, but the Linux one does. - Windows: Added downloading of ``ccache.exe``, esp. as the other sources so far recommended were not working properly after updates. This is taken from the official project and should be good. - Windows: Added downloading of matching MinGW64 C compiler, if no other was found, or that was has the wrong architecture, e.g. 32 bits where we need 64 bits. - Windows: Added ability to copy icon resources from an existing binary with new option ``--windows-icon-from-exe``. - Windows: Added ability to provide multiple icon files for use with different desktop resolutions with new option ``--windows-icon-from-ico`` that got renamed to disambiguate from other icon options. - Windows: Added support for requesting UAC admin right with new option ``--windows-uac-admin``. - Windows: Added support for requesting "uiaccess" rights with yet another new option ``--windows-uac-uiaccess``. - Windows: Added ability to specify version info to the binary. New options ``--windows-company-name``, ``--windows-product-name``, ``--windows-file-version``, ``--windows-product-version``, and ``--windows-file-description`` have been added. Some of these have defaults. - Enhanced support for using the Win32 compiler of MinGW64, but it's not perfect yet and not recommended. - Windows: Added support for LTO mode for MSVC as well, this seems to allow more optimization. - Plugins: The numpy plugin now handles matplotlib3 config files correctly. Optimization ============ - Use less C variables in dictionary created, not one per key/value pair. This improved scalability of C compilation. - Use common code for module variable access, leading to more compact code and enhanced scalability of C compilation. - Use error exit during dictionary creation to release the dictionary, list, tuple, and set in case of an error occurring while they are still under construction. That avoids releases of it in error exists, reducing the generated code size by a lot. This improves scalability of C compilation for generating these. - Annotate no exception raise for local variables of classes with know dict shape, to avoid useless error exits. - Annotate no exception exit for ``staticmethod`` and ``classmethod`` as they do not check their arguments at all. This makes code generated for classes with these methods much more compact, mainly improving their scalability in C compilation. - In code generation, prefer ``bool`` over ``nuitka_bool`` which allows to annotate exception result, leading to more compact code. Also cleanup so that code generation always go through the C type objects, rather than doing cases locally, adding a C type for ``bool``. - Use common code for C code handling const ``None`` return only, to cases where there is any immutable constant value returned, avoid code generation for this common case. Currently mutable constants are not handled, this may be added in the future. - Annotate no exception for exception type checks in handlers for Python2 and no exception if the value has exception type shape for Python3. The exception type shape was newly added. This avoids useless exception handlers in most cases, where the provided exception is just a built-in exception name. - Improve speed of often used compile time methods on nodes representing constant values, by making their implementation type specific to improve frontend compile time speed, we check e.g. mutable and hashable a lot. - Provide truth value for variable references, enhancing loop optimization and merge value tracing, to also decide this correctly for values only read, and then changed through attribute, e.g. ``append`` on lists. This allows many more static optimization. - Use ``staticmethod`` for methods in Nuitka nodes to achieve faster frontend compile times where possible. - Use dedicated helper code for calls with single argument, avoiding the need have a call site local C array of size one, just to pass a pointer to it. - Added handling of ``hash`` slot, to predict hashable keys for dictionary and sets. - Share more slot provision for built-in type shapes from mixin classes, to get them more universally provided, even for special types, where their consideration is unusual. - Trace "user provided" flag only for constants where it really matters, i.e. for containers and generally potentially large values, but not for every number or boolean value. - Added lowering of ``bytearray`` constant values to ``bytes`` value iteration, while handling constant values for this optimization with dedicated code for improved frontend compilation speed. - The dict built-in now annotates the dictionary type shape of its result. - The wrapping side-effects node now passes on the type shape of the wrapped value, allowing for optimization of these too. - Split ``slice`` nodes into variants with 1, 2 or 3 arguments, to avoid the overhead of determining which case we have, as well as to save a bit of memory, since these are more frequently used on Python3 for subscript operations. Also annotate their type shape, allowing more optimization. - Faster dictionary lookups, esp. in cases where errors occur, because we were manually recreating a ``KeyError`` that is already provided by the dict implementation. This should also be faster, as it avoids a CPython API call overhead on the DLL and they can provide a reference or not for the returned value, simplifying using code. - Faster dictionary containment checks, with our own dedicated helper, we can use code that won't create an exception when an item is not present at all. - Faster hash lookups with our own helper, separating cases where we want an exception for non-hashable values or not. These should also be faster to call. - Avoid acquiring thread state in exception handling that checks if a ``StopIteration`` occurred, to improved speed on Python3, where is involves locking, but this needs to be applied way more often. - Make sure checks to debug mode and full compatibility mode are done with the variables introduced, to avoid losing performance due to calls for Nuitka compile time enhancements. This was so far only done partially. - Split constant references into two base classes, only one of them tracking if the value was provided by the user. This saves compile time memory and avoids the overhead to check if sizes are exceeded in cases they cannot possibly be so. - The truth value of container creations is now statically known, because the empty container creation is no longer a possibility for these nodes, allowing more optimization for them. - Optimize the bool built-in with no arguments directory, allow to simplify the node for single argument form to avoid checks if an argument was given. - Added iteration handles for ``xrange`` values, and make them faster to create by being tied to the node type, avoiding shared types, instead using the mixin approach. This is in preparation to using them for standard iterator tracing as well. So far they are only used for ``any`` and ``all`` decision. - Added detection if a iterator next can raise, using existing iterator checking which allows to remove needless checks and exception traces. Adding a code variant for calls to next that cannot fail, while tuning the code used for ``next`` and unpacking next, to use faster exception checking in the C code. This will speed up unpacking performance for some forms of unpacking from known sizes. - Make sure to use the fastest tuple API possible in all of Nuitka, many place e.g. used ``PyTuple_Size``, and one was in a performance critical part, e.g. in code that used when compiled functions as called as a method. - Added optimized variant for ``_PyList_Extend`` for slightly faster unpacking code. - Added optimized variant for ``PyList_Append`` for faster list contractions code. - Avoid using ``RemoveFileSpec`` and instead provide our own code for that task, slightly reducing file size and avoiding to use the ``Shlapi`` link library. Tests ===== - Made reflected test use common cleanup of test folder, which is more robust against Windows locking issues. - Only output changed CPython output after the forced update of cached value was done, avoiding duplicate or outdated outputs. - Avoid complaining about exceptions for in-place operations in case they are lowered to non-inplace operations and then raise unsupported, not worth the effort to retain original operator. - Added generated test for subscript operations, also expanding coverage in generated tests by making sure, conditional paths are both taken by varying the ``cond`` value. - Use our own code helper to check if an object has an attribute, which is faster, because it avoids creating exceptions in the first place, instead of removing them afterwards. Cleanups ======== - Make sure that code generation always go through the C type objects rather than local ``elif`` casing of the type. This required cleaning up many of the methods and making code more abstract. - Added base class for C types without reference counting, so they can share the code that ignores their handling. - Remove ``getConstant`` for constant value nodes, use the more general ``getCompileTimeConstant`` instead, and provide quick methods that test for empty tuple or dict, to use for checking concrete values, e.g. with call operations. - Unified container creation into always using a factory function, to be sure that existing container creations are not empty. - Stop using ``@calledWithBuiltinArgumentNamesDecorator`` where possible, and instead make explicit wrapping or use correct names. This was used to allow e.g. an argument named ``list`` to be passed from built-in optimization, but that can be done in a cleaner fashion. Also aligned no attributes and the argument names, there was inconsistency there. - Name mangling was done differently for attribute names and normal names and with non-shared code, and later than necessary, removing this as a step from variable closure taking after initial tree build. - As part of the icon changes, now handled in Python code, we stop using the ``rc`` binary and handle all resources ourselves, allowing to remove that code from the Scons side of things. - Moved file comparison code of standalone mode into file utils function for use in plugins as well. - Unified how path concatenation is done in Nuitka helper code, there were more or less complete variants, this is making sure, the most capable form is used in all cases. - Massive cleanup to our scons file, by moving out util code that only scons uses, hacks we apply to speed up scons, and more to separate modules with dedicated interfaces. - When using ``enumerate`` we now provide start value of 1 where it is appropriate, e.g. when counting source code lines, rather than adding ``count+1`` on every usage, making code more readable. Organisational ============== - Do not recommend Anaconda on Windows anymore, it seems barely possible to get anything installed on it with a fresh download, due to the resolver literally working for days without finishing, and then reporting conflicts, it would only we usable when starting with Miniconda, but that seems less interesting to users, also gcc 5.2 is way too old these days. - The commit hook should be reinstalled, since it got improved and adapted for newer git versions. - Added link to donations to funding document, following a Github standard. - Bumped requirements for development to the latest versions, esp. newer isort. - Added a rough description of tests to do to add a new CPython test suite, to allow others to take this task in the future. - Updated the git hook so that Windows and newest git works. - Make it more clear in the documentation that Microsoft Appstore Python is not supported. Summary ======= This is the big release in terms of scalability. The optimization in this release mostly focused on getting things that cause increased compile times sorted out. A very important fix avoids loop optimization to leak into global passes of all modules unnecessarily, but just as important, generated code now is much better for the C compiler to consume in observed problematic cases. More optimization changes are geared towards reducing Nuitka frontend compile time, which could also be a lot in some cases, ending up specializing more constant nodes and how they expose themselves to optimization. Other optimization came from supporting Python 3.9 and things come across during the implementation of that feature, e.g. to be able to make differences with unpacking error messages, we provide more code to handle it ourselves, and to manually optimize how to interact with e.g. ``list`` objects. For Windows, the automatic download of ``ccache`` and a matching MinGW64 if none was found, is a new step, that should lower the barrier of entry for people who have no clue what a C compiler is. More changes are bound to come in this field with future releases, e.g. making a minimum version requirement for gcc on Windows that excludes unfit C compilers. All in all, this release should be taken as a major cleanup, resolving many technical debts of Nuitka and preparing more optimization to come. ********************** Nuitka Release 0.6.9 ********************** This releases contains important bug fixes for regressions of the 0.6.8 series which had relatively many problems. Not all of these could be addressed as hotfixes, and other issues were even very involved, causing many changes to be necessary. There are also many general improvements and performance work for tracing and loops, but the full potential of this will not be unlocked with this release yet. Bug Fixes ========= - Fix, loop optimization sometimes didn't determinate, effectively making Nuitka run forever, with no indication why. This has been fixed and a mechanism to give up after too many attempts has been added. - Fix, closure taking object allowed a brief period where the garbage collector was exposed to uninitialized objects. Fixed in 0.6.8.1 already. - Python3.6+: Fix corruption for exceptions thrown into asyncgen. Fixed in 0.6.8.1 already. - Fix, deleting variables detected as C type bool could raise an ``UnboundLocalError`` that was wrong. Fixed in 0.6.8.1 already. - Python3.8.3+: Fix, future annotations parsing was using hard coded values that were changed in CPython, leading to errors. - Windows: Avoid encoding issues for Python3 on more systems, by going from wide characters to unicode strings more directly, avoiding an encoding as UTF8 in the middle. Fixed in 0.6.8.2 already. - Windows: Do not crash when warning about uninstalled MSVC using Python3. This is a Scons bug that we fixed. Fixed in 0.6.8.3 already. - Standalone: The output of dependency walker should be considered as "latin1" rather than UTF8. Fixed in 0.6.8.3 already. - Standalone: Added missing hidden dependencies for ``flask``. Fixed in 0.6.8.1 already. - Standalone: Fixed ``win32com.client`` on Windows. Fixed in 0.6.8.1 already. - Standalone: Use ``pkgutil`` to scan encoding modules, properly ignoring the same files as Python does in case of garbage files being there. Fixed in 0.6.8.2 already. - Plugins: Enabling a plugin after the filename to compile was given, didn't allow for arguments to the passed, causing problems. Fixed in 0.6.8.3 already. - Standalone: The ``certifi`` data file is now supported for all modules using it and not only some. - Standalone: The bytecode for the standard library had filenames pointing to the original installation attached. While these were not used, but replaced at runtime, they increased the size of the binary, and leaked information. - Standalone: The path of ``sys.executable`` was not None, but pointing to the original executable, which could also point to some temporary virtualenv directory and therefore not exist, also it was leaking information about the original install. - Windows: With the MSVC compiler, elimination of duplicate strings was not active, causing even unused strings to be present in the binary, some of which contained file paths of the Nuitka installation. - Standalone: Added support for pyglet. - Plugins: The command line handling for Pmw plugin was using wrong defaults, making it include more code than necessary, and to crash if it was not there. New Features ============ - Windows: Added support for using Python 2.7 through a symlink too. This was already working for Python3, but a scons problem prevented this from working. - Caching of compiled C files is now checked with ccache and clcache, and added automatically where possible, plus a report of the success is made. This can accelerate the re-compile very much, even if you have to go through Nuitka compilation itself, which is not (yet) cached. - Added new ``--quiet`` option that will disable informational traces that are going to become more. - The Clang from MSVC installation is now picked up for both 32 and 64 bits and follows the new location in latest Visual Studio 2019. - Windows: The ``ccache`` from Anaconda is now supported as well as the one from msys64. Optimization ============ - The value tracing has become more correct with loops and in general less often inhibits optimization. Escaping of value traces is now a separate trace state allowing for more appropriate handling of actual unknowns. - Memory used for value tracing has been lowered by removing unnecessary states for traces, that we don't use anymore. - Windows: Prevent scons from scanning for MSVC when asked to use MinGW64. This avoids a performance loss doing something that will then end up being unused. - Windows: Use function level linking with MSVC, this will allow for smaller binaries to be created, that don't have to include unused helper functions. Cleanups ======== - The scons file now uses Nuitka utils functions and is itself split up into several modules for enhanced readability. - Plugin interfaces for providing extra entry points have been cleaned up and now named tuples are used. Backward compatibility is maintained though. Organisational ============== - The use of the logging module was replaced with more of our custom tracing and we now have the ability to write the optimization log to a separate file. - Old style plugin options are now detected and reported as a usage error rather than unknown plugin. - Changed submodules to use git over https, so as to not require ssh which requires a key registered and causes problems with firewalls too. - More correct Debian copyright file, made formatting of emails in source code consistent. - Added repository for Ubuntu focal. Summary ======= The main focus of this release has been bug fixes with only a little performance work due to the large amount of regressions and other findings from the last release. The new constants loading for removes a major scalability problem. The checked and now consistently possible use of ``ccache`` and ``clcache`` allows for much quicker recompilation. Nuitka itself can still be slow in some cases, but should have seen some improvements too. Scalability will have to remain a focus for the next releases too. The other focus, was to make the binaries contain no original path location, which is interesting for standalone mode. Nuitka should be very good in this area now. For optimization, the new loop code is again better. But it was also very time consuming, to redo it, yet again. This has prevented other optimization to be added. And then for correctness, the locals scope work, while very invasive, was necessary, to handle the usage of locals inside of contractions, but also will be instrumental for function inlining to become generally available. So, ultimately, this release is a necessary intermediate step. Upcoming releases will be able to focus more clearly on run time performance again as well as on scalability for generated C code. ********************** Nuitka Release 0.6.8 ********************** This releases contains important general improvements and performance improvements and enhanced optimization as well as many bug fixes that enhance the Python 3.8 compatibility. Bug Fixes ========= - Python3.5+: Fix, coroutines and asyncgen could continue iteration of awaited functions, even after their return, leading to wrong behaviour. - Python3.5+: Fix, absolute imports of names might also refer to modules and need to be handled for module loading as well. - Fix, the ``fromlist`` of imports could loose references, potentially leading to corruption of contained strings. - Python3.8: Fix, positional only arguments were not enforced to actually be that way. - Python3.8: Fix, complex calls with star arguments that yielded the same value twice, were not yet caught. - Python3.8: Fix, evaluation order for nested dictionary contractions was not followed yet. - Windows: Use short paths, these work much better to load extension modules and TCL parts of TkInter cannot handle unicode paths at all. This makes Nuitka work in locations, where normal Python cannot. - Windows: Fixup dependency walker in unicode input directories. - Standalone: Use frozen module loader only at ``libpython`` initialisation and switch to built-in bytecode loader that is more compatible afterwards, increasing compatibility. - Standalone: Fix for pydanctic support. - Standalone: Added missing hidden dependency of uvicorn. - Fix, the parser for ``.pyi`` files couldn't handle multiline imports. - Windows: Derive linker arch of Python from running binary, since it can happen that the Python binary is actually a script. - Fixup static linking with ``libpython.a`` that contains ``main.o`` by making our colliding symbols for ``Py_GetArgcArgv`` weak. - Python3.7: Fix misdetection as asyncgen for a normal generator, if the iterated value is async. - Distutils: Fix ``build_nuitka`` for modules under nested namespaces. - OpenBSD: Follow usage of clang and other corrections to make accelerated mode work. - macOS: Fixup for standalone mode library scan. - Fix, the logging of ``--show-modules`` was broken. - Windows: Enable ``/bigobj`` mode for MSVC for large compilations to work. - Windows: Fixup crash in warning with pefile dependency manager. - Windows: Fixup ``win32com`` standalone detection of other Python version ``win32com`` is in system ``PATH``. - Fix, the python flag for static hashes didn't have the intended effect. - Fix, generators may be resurrected in the cause of their destruction, and then must not be released. - Fix, method objects didn't implement the methods ``__reduce__`` and ``__reduce_ex__`` necessary for pickling them. - Windows: Fix, using a Python installation through a symlink was not working. - Windows: Fix, icon paths that were relative were not working anymore. - Python3.8: Detect duplicate keywords yielded from star arguments. - Fix, methods could not be pickled. - Fix, generators, coroutines and asyncgen might be resurrected during their release, allow for that. - Fix, frames need to traverse their attached locals to be released in some cases. New Features ============ - Plugin command line handling now allows for proper ``optparse`` options to be used, doing away with special parameter code for plugins. The arguments now also become automatically passed to the instantiations of plugins. Loading and creation of plugins are now two separate phases. They are loaded when they appear on the command line and can add options in their own group, even required ones, but also with default values. - Started using logging with name-spaces. Applying logging per plugin to make it easier to recognize which plugin said what. Warnings are now colored in red. - Python3.5+: Added support for two step module loading, making Nuitka loading even more compatible. - Enhanced import tracing to work on standalone binaries in a useful manner, allow to compare with normal binaries. - Fix, the ``setattr`` built-in was leaking a reference to the ``None`` value. Optimization ============ - Proper loop SSA capable of detecting shapes with an incremental initial phase and a final result of alternatives for variables written in the loop. This detects shapes of manual integer incrementing loops correctly now, it doesn't see through iterators yet, but this will come too. - Added type shapes for all operations and all important built-in types to allow more compile time optimization and better target type selection. - Target type code generation was expanded from manual usage with conditions to all operations allowing to get at bool target values more directly. - For in-place operations, there is the infrastructure to generate them for improved performance, but so far it's only used for Python2 int, and not for the many types normal operations are supported. - Force usage of C boolean type for all indicator variables from the re-formulation. In some cases, we are not yet there with detections, and this gives instant benefit. - Complex constants didn't annotate their type shape, preventing compile time optimization for them. - Python3.8: Also support vectorcall for compiled method objects. These are rarely used in new Python, but can make a difference. - Remove loops that have only a final break. This happens in static optimization in some cases, and allows more optimization to be done. - Avoid using a preparing a constant tuple value for calls with only constant arguments. - Avoid using ``PyErr_Format`` where it's not necessary by adding specialized helpers for common cases. - Detect ``del`` statements that will raise an exception and replace with that. - Exception matching is boolean shape, allowing for faster code generation. - Disable recursion checks outside of full compat mode. - Avoid large blocks for conditional statements that only need to enclose the condition evaluation. - Added shortcuts for interactions between compiled generator variants, to avoid calls to their C methods with argument passing, etc. Organisational ============== - Updated Developer Manual with changes that happened, removing the obsolete language choice section. - Added 3.8 support mentions in even more places. - The mailing list has been deleted. We now prefer Gitter chat and Github issues for discussions. - Visual Code recommended extensions are now defined as such in the project configuration and you will be prompted to install them. - Visual Code environents for ``Py38`` and ``Py27`` were added for easier switch. - Catch usage of Python from the Microsoft App Store, it is not supported and seems to limit access to the Python installation for security reasons that make support impossible. - Make it clear that ``--full-compat`` should not be used in help output. - Added instructions for MSVC runtimes and standalone compilation to support Windows 7. - More complete listing of copyright holders for Debian. - Updated to newer black and PyLint. - Enhanced gcc version check, properly works with gcc 10 and higher. Tests ===== - Pylint cleanups for some of the tests. - Added test for loading of user plugins. - Removed useless outputs for ``search`` mode skipping non-matches. Cleanups ======== - Limit command line handling for multiprocessing module to when the plugin is actually used, avoiding useless code of Windows binaries. - Pylint cleanup also foreign code like ``oset`` and ``odict``. - In preparation of deprecating the alternative, ``--enable-plugin`` has become the only form used in documentation and tests. - Avoid numeric pylint symbols more often. - Distutils: Cleanup module name for distutils commands, these are not actually enforced by distutils, but very ugly in our coding conventions. - The "cannot get here" code to mark unreachable code has been improved and no longer needs an identifier passed, but uses the standard C mechanism for that. - Removed accessors for lookup sources from nodes, allowing for faster usage and making sure, lookups are only done where needed. Summary ======= This release is huge in terms of bugs fixed, but also extremely important, because the new loop SSA and type tracing, allows for many more specialized code usages. We now can trace the type for some loops to be specifically an integer or long value only, and will become able to generate code that avoids using Python objects, in these cases. Once that happens, the performance will make a big jump. Future releases will have to consolidate the current state, but it is expected that at least an experimental addition of C type ``float`` or ``C long`` can be added, add to that ``iterator`` type shape and value analsis, and an actual jump in performance can be expected. ********************** Nuitka Release 0.6.7 ********************** This release contains bug fixes and improvements to the packaging, for the RPM side as well as for Debian, to cover Python3 only systems as they are now becoming more common. Bug Fixes ========= - Compatibility: The value of ``__module__`` for extension modules was not dependent into which package the module was loaded, it now is. - Anaconda: Enhanced detection of Anaconda for Python 3.6 and higher. - CentOS6: Detect gcc version to allow saving on macro memory usage, very old gcc didn't have that. - Include Python3 for all Fedora versions where it works as well as for openSUSE versions 15 and higher. - Windows: Using short path names to interact with Scons avoids problems with unicode paths in all cases. - macOS: The usage of ``install_name_tool`` could sometimes fail due to length limits, we now increase it at link time. - macOS: Do not link against ``libpython`` for module mode. This prevented extension modules from actually being usable. - Python3.6: Follow coroutine fixes in our asyncgen implementation as well. - Fix, our version number handling could overflow with minor versions past 10, so we limited it for now. New Features ============ - Added support for Python 3.8, the experimental was already there and pretty good, but now added the last obscure features too. - Plugins can now provide C code to be included in the compilation. - Distutils: Added targets ``build_nuitka`` and ``install_nuitka`` to complement ``bdist_nuitka``, so we support software other than wheels, e.g. RPM packaging that compiles with Nuitka. - Added support for ``lldb`` the Clang debugger with the ``--debugger`` mode. Optimization ============ - Make the file prefix map actually work for gcc and clang, and compile files inside the build folder, unless we are running in debugger mode, so we use ``ccache`` caching across different compilations for at least the static parts. - Avoid compilation of ``__frozen.c`` in accelerated mode, it's not used. - Prefer using the inline copy of scons over systems scons. The later will only be slower. Use the fallback to external scons only from the Debian packages, since there we consider it forbidden to include software as a duplicate. Organisational ============== - Added recommended plugins for Visual Code, replacing the list in the Developer Manual. - Added repository for Fedora 30 for download. - Added repository for CentOS 8 for download. - Updated inline copy of Scons used for Python3 to 3.1.2, which is said to be faster for large compilations. - Removed Eclipse setup from the manual, it's only infererior at this point and we do not use it ourselves. - Debian: Stop recommending PyQt5 in the package, we no longer use it for built-in GUI that was removed. - Debian: Bumped the standards version and modernized the packaging, solving a few warnings during the build. Cleanups ======== - Scons: Avoid to add Unix only include paths on Windows. - Scons: Have the static source code in a dedicated folder for clarity. Tests ===== - Added tests to Github Actions, for the supported Python versions for all of Linux, macOS and Windows, covering the later publicly for the first time. We use Anaconda on macOS for the tests now, rather than Homebrew. - Enable IO encoding to make sure we use UTF8 for more test suites that actually need it in case of problems. - Comparing module outputs now handles segfaults by running in the debugger too. Summary ======= This release adds full support for Python 3.8 finally, which took us a while, and it cleans up a lot on the packaging side. There aren't that many important bug fixes, but it's still nice to this cleaned up. We have important actual optimization in the pipeline that will apply specialization to target types and for comparison operations. We expect to see actual performance improvements in the next release again. ********************** Nuitka Release 0.6.6 ********************** This release contains huge amounts of crucial bug fixes all across the board. There is also new optimization and many organisational improvements. Bug Fixes ========= - Fix, the top level module must not be bytecode. Otherwise we end up violating the requirement for an entry point on the C level. - Fix, avoid optimizing calls with default values used. This is not yet working and needed to be disabled for now. - Python3: Fix, missing keyword only arguments were not enforced to be provided keyword only, and were not giving the compatible error message when missing. - Windows: Find ``win32com`` DLLs too, even if they live in sub folders of site-packages, and otherwise not found. They are used by other DLLs that are found. - Standalone: Fixup for problem with standard library module in most recent Anaconda versions. - Scons: Fix, was using ``CXXFLAGS`` and ``CPPFLAGS`` even for the C compiler, which is wrong, and could lead to compilation errors. - Windows: Make ``--clang`` limited to ``clang-cl.exe`` as using it inside a MinGW64 is not currently supported. - Standalone: Added support for using ``lib2to2.pgen``. - Standalone: Added paths used by openSUSE to the Tcl/Tk plugin. - Python3.6+: Fix, the ``__main__`` package was ``None``, but should be ``""`` which allows relative imports from itself. - Python2: Fix, compile time optimization of floor division was using normal division. - Python3: Fix, some run time operations with known type shapes, were falsely reporting error message with ``unicode`` or ``long``, which is of course not compatible. - Fix, was caching parent package, but these could be replaced e.g. due to bytecode demotion later, causing crashes during their optimization. - Fix, the value of ``__compiled__`` could be corrupted when being deleted, which some modules wrappers do. - Fix, the value of ``__package__`` could be corrupted when being deleted. - Scons: Make sure we can always output the compiler output, even if it has a broken encoding. This should resolve MSVC issues on non-English systems, e.g. German or Chinese. - Standalone: Support for newest ``sklearn`` was added. - macOS: Added resolver for run time variables in ``otool`` output, that gets PyQt5 to work on it again. - Fix, floor division of run time calculations with float values should not result in ``int``, but ``float`` values instead. - Standalone: Enhanced support for ``boto3`` data files. - Standalone: Added support for ``osgeo`` and ``gdal``. - Windows: Fix, there were issues with spurious errors attaching the constants blob to the binary due to incorrect C types provided. - Distutils: Fix, need to allow ``/`` as separator for package names too. - Python3.6+: Fix reference losses in asyncgen when throwing exceptions into them. - Standalone: Added support for ``dill``. - Standalone: Added support for ``scikit-image`` and ``skimage``. - Standalone: Added support for ``weasyprint``. - Standalone: Added support for ``dask``. - Standalone: Added support for ``pendulum``. - Standalone: Added support for ``pytz`` and ``pytzdata``. - Fix, ``--python-flags=no_docstrings`` no longer implies disabling the assertions. New Features ============ - Added experimental support for Python 3.8, there is only very few things missing for full support. - Distutils: Added support for packages that are in a namespace and not just top level. - Distutils: Added support for single modules, not only packages, by supporting ``py_modules`` as well. - Distutils: Added support for distinct namespaces. - Windows: Compare Python and C compiler architecture for MSVC too, and catch the most common user error of mixing 32 and 64 bits. - Scons: Output variables used from the outside, so the debugging is easier. - Windows: Detect if clang installed inside MSVC automatically and use it if requested via ``--clang`` option. This is only the 32 bits variant, but currently the easy way to use it on Windows with Nuitka. Optimization ============ - Loop variables were analysed, but results were only available on the inside of the loop, preventing many optimization in these cases. - Added optimization for the ``abs`` built-in, which is also a numerical operator. - Added optimization for the ``all`` built-in, adding a new concept of iteration handle, for efficient checking that avoids looking at very large sequences, of which properties can still be known. .. code:: python all(range(1, 100000)) # no need to look at all of them - Added support for optimizing ``ImportError`` construction with keyword-only arguments. Previously only used without these were optimized. .. code:: python raise ImportError(path="lala", name="lele") # now optimized - Added manual specialization for single argument calls, sovling a TODO, as these will be very frequent. - Memory: Use single child form of node class where possible, the general class now raises an error if used with used with only one child name, this will use less memory at compile time. - Memory: Avoid list for non-local declarations in every function, these are very rare, only have it if absolutely necessary. - Generate more compact code for potential ``NameError`` exceptions being raised. These are very frequent, so this improves scalability with large files. - Python2: Annotate comparison of ``None`` with ``int`` and ``str`` types as not raising an exception. - Shared empty body functions and generators. One shared implementation for all empty functions removes that burden from the C compiler, and from the CPU instruction cache. All the shared C code does is to release its arguments, or to return an empty generator function in case of generator. - Memory: Added support for automatic releases of parameter variables from the node tree. These are normally released in a try finally block, however, this is now handled during code generation for much more compact C code generated. - Added specialization for ``int`` and ``long`` operations ``%``, ``<<``, ``>>``, ``|``, ``&``, ``^``, ``**``, ``@``. - Added dedicated nodes for representing and optimizing based on shapes for all binary operations. - Disable gcc macro tracing unless in debug mode, to save memory during the C compilation. - Restored Python2 fast path for ``int`` with unknown object types, restoring performance for these. Cleanups ======== - Use dedicated ``ModuleName`` type that makes the tests that check if a given module name is inside a namespace as methods. This was hard to get right and as a result, adopting this fixed a few bugs and or inconsistent results. - Expand the use of ``nuitka.PostProcessing`` to cover all actions needed to get a runnable binary. This includes using ``install_name_tool`` on macOS standalone, as well copying the Python DLL for acceleration mode, cleaning the ``x`` bit for module mode. Previously only a part of these lived there. - Avoid including the definitions of dynamically created helper functions in the C code, instead just statically declare the ones expected to be there. This resolves Visual Code complaining about it, and should make life also easier for the compiler and caches like ``ccache``. - Create more helper code in closer form to what ``clang-format`` does, so they are easier to compare to the static forms. We often create hard coded variants for few arguments of call functions, and generate them for many argument variations. - Moved setter/getter methods for Nuitka nodes consistently to the start of the node class definitions. - Generate C code much closer to what ``clang-format`` would change it to be. - Unified calling ``install_name_tool`` on macOS into one function that takes care of all the things, including e.g. making the file writable. - Debug output from scons should be more consistent and complete now. - Sort files for compilation in scons for better reproducible results. - Create code objects version independent, avoiding python version checks by pre-processor, hiding new stuff behind macros, that ignore things on older Python versions. Tests ===== - Added many more built-in tests for increased coverage of the newly covered ones, some of them being generic tests that allow to test all built-ins with typical uses. - Many tests have become more PyLint clean as a result of work with Visual Code and it complaining about them. - Added test to check PyPI health of top 50 packages. This is a major GSoC 2019 result. - Output the standalone directory contents for Windows too in case of a failure. - Added generated tests to fully cover operations on different type shapes and their errors as well as results for typical values. - Added support for testing against installed version of Nuitka. - Cleanup up tests, merging those for only Python 3.2 with 3.3 as we no longer support that version anyway. - Execute the Python3 tests for macOS on Travis too. Organisational ============== - The donation sponsored machine called ``donatix`` had to be replaced due to hardware breakage. It was replaced with a Raspberry-Pi 4. - Enhanced plugin documentation. - Added description of the git workflow to the Developer Manual. - Added checker script ``check-nuitka-with-codespell`` that reports typos in the source code for easier use of ``codespell`` with Nuitka. - Use newest PyLint and clang-format. - Also check plugin documentation files for ReST errors. - Much enhanced support for Visual Code configuration. - Trigger module code is now written into the build directory in debug mode, to aid debugging. - Added deep check function that descends into tuples to check their elements too. Summary ======= This release comes after a long time of 4 months without a release, and has accumulated massive amounts of changes. The work on CPython 3.8 is not yet complete, and the performance work has yet to show actual fruit, but has also progressed on all fronts. Connecting the dots and pieces seems not far away. ********************** Nuitka Release 0.6.5 ********************** This release contains many bug fixes all across the board. There is also new optimization and many organisational improvements. Bug Fixes ========= - Python3.4+: Fixed issues with modules that exited with an exception, that could lead to a crash, dealing with their ``__spec__`` value. - Python3.4+: The ``__loader__`` method ``is_package`` had the wrong signature. - Python3.6+: Fix for ``async with`` being broken with uncompiled generators. - Python3.5+: Fix for ``coroutines`` that got their awaited object closed behind their back, they were complaining with ``RuntimeError`` should they be closed themselves. - Fix, constant values ``None`` in a bool target that could not be optimized away, lead to failure during code generation. .. code:: python if x() and None: ... - Standalone: Added support for sha224, sha384, sha512 in crypto package. - Windows: The icon wasn't properly attached with MinGW64 anymore, this was a regression. - Windows: For compiler outputs, also attempt preferred locale to interpret outputs, so we have a better chance to not crash over MSVC error messages that are not UTF-8 compatible. - macOS: Handle filename collisions for generated code too, Nuitka now treats all filesystems for all OS as case insensitive for this purpose. - Compatibility: Added support for tolerant ``del`` in class exception handlers. .. code:: python class C: try: ... except Exception as e: del e # At exception handler exit, "e" is deleted if still assigned We already were compatible for functions and modules here, but due to the special nature of class variables really living in dictionaries, this was delayed. But after some other changes, it was now possible to solve this TODO. - Standalone: Added support for Python3 variant of Pmw. - Fix, the NumPy plugin now handles more installation types. - Fix, the qt plugin now handles multiple library paths. - Fix, need ``libm`` for some Anaconda variants too. - Fix, left over bytecode from plugins could crash the plugin loader. - Fix, ``pkgutil.iter_packages`` is now working for loaded packages. New Features ============ - Python3.8: Followed some of the changes and works with beta2 as a Python 3.7, but none of the new features are implemented yet. - Added support for Torch, Tensorflow, Gevent, Sklearn, with a new Nuitka plugin. - Added support for "hinted" compilation, where the used modules are determined through a test run. - Added support for including TCL on Linux too. Optimization ============ - Added support for the ``any`` built-in. This handles a wide range of type shapes and constant values at compile time, while also having optimized C code. - Generate code for some ``CLONG`` operations in preparation of eventual per expression C type selection, it then will allow to avoid objects in many instances. - Windows: Avoid creating link libraries for MinGW64 as these have become unnecessary is the mean time. - Packages: Do not export entry points for all included packages, only for the main package name it is importable as. Organisational ============== - Added support for Visual Studio 2019 as a C compiler backend. - Improved plugin documentation describing how to create plugins for Nuitka even better. - The is now a mode for running the tests called ``all`` which will execute all the tests and report their errors, and only fail at the very end. This doesn't avoid wasting CPU cycles to report that e.g. all tests are broken, but it allows to know all errors before fixing some. - Added repository for Fedora 30 for download. - Added repository for openSUSE 15.1 for download. - Ask people to compile hello world program in the Github issue template, because many times, they have setup problems only. - Visual Studio Code is now the recommended IDE and has integrated configuration to make it immediately useful. - Updated internal copy of Scons to 3.1.0 as it incorporates many of our patches. - Changed wordings for optimization to use "lowering" as the only term to describe an optimization that simplifies. Cleanups ======== - Plugins: Major refactoring of Nuitka plugin API. - Plugins: To locate module kind, use core Nuitka code that handles more cases. - The test suite runners are also now autoformatted and checked with PyLint. - The Scons file is now PyLint clean too. - Avoid ``build_definitions.h`` to be included everywhere, in that it's only used in the main program part. This makes C linter hate us much less for using a non-existent file. Tests ===== - Run the tests using Travis on macOS for Python2 too. - More standalone tests have been properly whitelisting to cover openSSL usage from local system. - Disabled PySide2 test, it's not useful to fail and ignore it. - Tests: Fixups for coverage testing mode. - Tests: Temporarily disable some checks for constants code in reflected tests as it only exposes ``marshal`` not being deterministic. Summary ======= This release is huge again. Main points are compatibility fixes, esp. on the coroutine side. These have become apparently very compatible now and we might eventually focus on making them better. Again, GSoC 2019 is also showing effects, and will definitely continue to do soin the next release. Many use cases have been improved, and on an organisational level, the adoption of Visual Studio Code seems an huge improvement to have a well configured IDE out of the box too. In upcoming releases, more built-ins will be optimized, and hopefully the specialization of operations will hit more and more code with more of the infrastructure getting there. ********************** Nuitka Release 0.6.4 ********************** This release contains many bug fixes all across the board. There is also new optimization and many organisational improvements. Bug Fixes ========= - When linking very large programs or packages, with gcc compiler, Scons can produce commands that are too large for the OS. This happens sooner on the Windows OS, but also on Linux. We now have a workaround that avoids long command lines by using ``@sources.tmp`` syntax. - Standalone: Remove temporary module after its use, instead of keeping it in ``sys.modules`` where e.g. ``Quart`` code tripped over its ``__file__`` value that is illegal on Windows. - Fixed non-usage of our enhanced detection of ``gcc`` version for compilers if given as a full path. - Fixed non-detection of ``gnu-cc`` as a form of gcc compiler. - Python3.4: The ``__spec__`` value corrections for compiled modules was not taking into account that there was a ``__spec__`` value, which can happen if something is wrapping imported modules. - Standalone: Added implicit dependencies for ``passlib``. - Windows: Added workaround for OS command line length limit in compilation with MinGW64. - Python2: Revive the ``enum`` plugin, there are backports of the buggy code it tries to patch up. - Windows: Fixup handling of SxS with non zero language id, these occur e.g. in Anaconda. - Plugins: Handle multiple PyQt plugin paths, e.g. on openSUSE this is done, also enhanced finding that path with Anaconda on Windows. - Plugins: For ``multiprocessing`` on Windows, allow the ``.exe`` suffix to not be present, which can happen when ran from command line. - Windows: Better version checks for DLLs on Python3, the ``ctypes`` helper code needs more definitions to work properly. - Standalone: Added support for both ``pycryptodome`` and ``pycryptodomex``. - Fix, the ``chr`` built-in was not giving fully compatible error on non number input. - Fix, the ``id`` built-in doesn't raise an exception, but said otherwise. - Python3: Proper C identifiers for names that fit into ``latin-1``, but are not ``ascii`` encodings. New Features ============ - Windows: Catch most common user error of using compiler from one architecture against Python from another. We now check those and compare it, and if they do not match, inform the user directly. Previously the compilation could fail, or the linking, with cryptic errors. - Distutils: Using setuptools and its runners works now too, not merely only pure distutils. - Distutils: Added more ways to pass Nuitka specific options via distutils. - Python3.8: Initial compatibility changes to get basic tests to work. Organisational ============== - Nuitka is participating in the GSoC 2019 with 2 students, Batakrishna and Tommy. - Point people creating PRs to using the ``pre-commit`` hook in the template. Due to making the style issues automatic, we can hope to encounter less noise and resulting merge problems. - Many improvements to the ``pre-commit`` hook were done, hopefully completing its development. - Updated to latest ``pylint``, ``black``, and ``isort`` versions, also added ``codespell`` to check for typos in the source code, but that is not automated yet. - Added description of how to use experimental flags for your PRs. - Removed mirroring from Bitbucket and Gitlab, as we increasingly use the Github organisation features. - Added support for Ubuntu Disco, removed support for Ubuntu Artful packages. Optimization ============ - Windows: Attach data blobs as Windows resource files directly for programs and avoid using C data files for modules or MinGW64, which can be slow. - Specialization of helper codes for ``+`` is being done for more types and more thoroughly and fully automatic with Jinja2 templating code. This does replace previously manual code. - Added specialization of helper codes for ``*`` operation which is entirely new. - Added specialization of helper codes for ``-`` operation which is entirely new. - Dedicated nodes for specialized operations now allow to save memory and all use type shape based analysis to predict result types and exception control flow. - Better code generation for boolean type values, removing error checks when possible. - Better static analysis for even more type operations. Cleanups ======== - Fixed many kinds of typos in the code base with ``codespell``. - Apply automatic formatting to more test runner code, these were previously not done. - Avoid using ``shutil.copytree`` which fails to work when directory already exists, instead provide ``nuitka.util.FileOperations.copyTree`` and use that exclusively. Tests ===== - Added new mode of operation to test runners, ``only`` that executes just one test and stops, useful during development. - Added new mechanism for standalone tests to expression modules that need to be importable, or else to skip the test by a special comment in the file, instead of by coded checks in the test runner. - Added also for more complex cases, another form of special comment, that can be any expression, that decides if the test makes sense. - Cover also setuptools in our distutils tests and made the execution more robust against variable behavior of distutils and setuptools. - Added standalone test for Urllib3. - Added standalone test for rsa. - Added standalone test for Pmw. - Added standalone test for passlib. Summary ======= Again this release is a sign of increasing adoption of Nuitka. The GSoC 2019 is also showing effects, definitely will in the next release. This release has a lot of new optimization, called specialization, but for it to really used, in many instances, we need to get away from working on C types for variables only, and get to them beig used for expressions more often. Otherwise much of the new special code is not used for most code. The focus of this release has been again to open up development further and to incorporate findings from users. The number of fixes or new use cases working is astounding. In upcoming releases, new built-ins will be optimized, and specialization of operations will hit more and more code now that the infrastructure for it is in place. ********************** Nuitka Release 0.6.3 ********************** This has a focus on organisational improvements. With more and more people joining Nuitka, normal developers as well as many GSoC 2019 students, the main focus was to open up the development tools and processes, and to improve documentation. That said, an impressive amount of bug fixes was contributed, but optimization was on hold. Bug Fixes ========= - Windows: Added support for running compiled binaries in unicode path names. - Standalone: Added support for crytodomex and pycparser packages. - Standalone: Added support for OpenSSL support in PyQt on Windows. - Standalone: Added support for OpenGL support with QML in PyQt on Windows. - Standalone: Added support for SciPy and extended the NumPy plugin to also handle it. - UI: The option ``--plugin-list`` still needed a positional argument to work. - Make sure ``sys.base_prefix`` is set correctly too. - Python3: Also make sure ``sys.exec_prefix`` and ``sys.base_exec_prefix`` are set correctly. - Standalone: Added platform plugins for PyQt to the default list of sensible plugins to include. - Fix detection of standard library paths that include ``..`` path elements. Optimization ============ - Avoid static C++ runtime library when using MinGW64. New Features ============ - Plugins: A plugin may now also generate data files on the fly for a given module. - Added support for FreeBSD/PowerPC arch which still uses ``gcc`` and not ``clang``. Organisational ============== - Nuitka is participating in the GSoC 2019. - Added documentation on how to create or use Nuitka plugins. - Added more API doc to functions that were missing them as part of the ongoing effort to complete it. - Updated to latest PyLint 2.3.1 for checking the code. - Scons: Using newer Scons inline copy with Python 2.7 as, the old one remains only used with Python 2.6, making it easier to know the relevant code. - Autoformat was very much enhanced and handles C and ReST files too now. For Python code it does pylint comment formatting, import statement sorting, and blackening. - Added script ``misc/install-git-hooks.py`` that adds a commit hook that runs autoformat on commit. Currently it commits unstaged content and therefore is not yet ready for prime time. - Moved adapted CPython test suites to `Github repository under Nuitka Organisation `__. - Moved Nuitka-website repository to `Github repository under Nuitka Organisation `__. - Moved Nuitka-speedcenter repository to `Github repository under Nuitka Organisation `__. - There is now a `Gitter chat for Nuitka community `__. - Many typo and spelling corrections on all the documentation. - Added short installation guide for Nuitka on Windows. Cleanups ======== - Moved commandline parsing helper functions from common code helpers to the main program where of course their only usage is. - Moved post processing of the created standalone binary from main control to the freezer code. - Avoid using ``chmod`` binary to remove executable bit from created extension modules. - Windows: Avoid using ``rt.exe`` and ``mt.exe`` to deal with copying the manifest from the ``python.exe`` to created binaries. Instead use new code that extracts and adds Windows resources. - Fixed many ``ResourceWarnings`` on Python3 by improved ways of handling files. - Fixed deprecation warnings related to not using ``collections.abc``. - The runners in ``bin`` directory are now formatted with ``black`` too. Tests ===== - Detect Windows permission errors for two step execution of Nuitka as well, leading to retries should they occur. - The salt value for CPython cached results was improved to take more things into account. - Tests: Added more trick assignments and generally added more tests that were so far missing. Summary ======= With the many organisational changes in place, my normal work is expected to resume for after and yield quicker improvements now. It is also important that people are now enabled to contribute to the Nuitka web site and the Nuitka speedcenter. Hope is to see more improvements on this otherwise neglected areas. And generally, it's great to see that a community of people is now looking at this release in excitement and pride. Thanks to everybody who contributed! ********************** Nuitka Release 0.6.2 ********************** This release has a huge focus on organisational things. Nuitka is growing in terms of contributors and supported platforms. Bug Fixes ========= - Fix, the Python flag ``--python-flag=-O`` was removing doc strings, but that should only be done with ``--python-flag=-OO`` which was added too. - Fix, accelerated binaries failed to load packages from the ``virtualenv`` (not ``venv``) that they were created and ran with, due to not propagating ``sys.prefix``. - Standalone: Do not include ``plat-*`` directories as frozen code, and also on some platforms they can also contain code that fails to import without error. - Standalone: Added missing implicit dependency needed for newer NumPy versions. New Features ============ - Added support for Alpine Linux. - Added support for MSYS2 based Python on Windows. - Added support for Python flag ``--python flag=-OO``, which allows to remove doc strings. - Added experimental support for ``pefile`` based dependency scans on Windows, thanks to Orsiris for this contribution. - Added plugin for proper Tkinter standalone support on Windows, thanks to Jorj for this contribution. - There is now a ``__compiled__`` attribute for each module that Nuitka has compiled. Should be like this now, and contains Nuitka version information for you to use, similar to what ``sys.version_info`` gives as a ``namedtuple`` for your checks. .. code:: python __nuitka_version__(major=0, minor=6, micro=2, releaselevel="release") Optimization ============ - Experimental code for variant types for ``int`` and ``long`` values, that can be plain C value, as well as the ``PyObject *``. This is not yet completed though. - Minor refinements of specialized code variants reducing them more often the actual needed code. Organisational ============== - The Nuitka Github Organisation that was created a while ago and owns the Nuitka repo now, has gained members. Check out https://github.com/orgs/Nuitka/people for their list. This is an exciting transformation for Nuitka. - Nuitka is participating in the GSoC 2019 under the PSF umbrella. We hope to grow even further. Thanks to the mentors who volunteered for this important task. Check out the `GSoC 2019 page `__ and thanks to the students that are already helping out. - Added Nuitka internal `API documentation `__ that will receive more love in the future. It got some for this release, but a lot is missing. - The Nuitka code has been ``black``-ened and is formatted with an automatic tool now all the way, which makes contributors lives easier. - Added documentation for questions received as part of the GSoC applications and ideas work. - Some proof reading pull requests were merged for the documentation, thanks to everybody who addresses these kinds of errors. Sometimes typos, sometimes broken links, etc. - Updated inline copy of Scons used for Python3 to 3.0.4, which hopefully means more bugs are fixed. Summary ======= This release is a sign of increasing adoption of Nuitka. The GSoC 2019 is showing early effects, as is more developers joining the effort. These are great times for Nuitka. This release has not much on the optimization side that is user visible, but the work that has begun is capable of producing glorious benchmarks once it will be finished. The focus on this and coming releases is definitely to open up the Nuitka development now that people are coming in as permanent or temporary contributors in (relatively) high numbers. ********************** Nuitka Release 0.6.1 ********************** This release comes after a relatively long time, and contains important new optimization work, and even more bug fixes. Bug Fixes ========= - Fix, the options ``--[no]follow-import-to=package_name`` was supposed to not follow into the given package, but the check was executed too broadly, so that e.g. ``package_name2`` was also affected. Fixed in 0.6.0.1 already. - Fix, wasn't detecting multiple recursions into the same package in module mode, when attempting to compile a whole sub-package. Fixed in 0.6.0.1 already. - Fix, constant values are used as C boolean values still for some of the cases. Fixed in 0.6.0.1 already. - Fix, referencing a function cannot raise an exception, but that was not annotated. Fixed in 0.6.0.2 already. - macOS: Use standard include of C bool type instead of rolling our own, which was not compatible with newest Clang. Fixed in 0.6.0.3 already. - Python3: Fix, the ``bytes`` built-in type actually does have a ``__float__`` slot. Fixed in 0.6.0.4 already. - Python3.7: Types that are also sequences still need to call the method ``__class_getitem__`` for consideration. Fixed in 0.6.0.4 already. - Python3.7: Error exits from program exit could get lost on Windows due to ``__spec__`` handling not preserving errors. Fixed in 0.6.0.4 already. - Windows: Negative exit codes from Nuitka, e.g. due to a triggered assertion in debug mode were not working. Fixed in 0.6.0.4 already. - Fix, conditional ``and`` expressions were mis-optimized when not used to not execute the right hand side still. Fixed in 0.6.0.4 already. - Python3.6: Fix, generators, coroutines, and asyncgen were not properly supporting annotations for local variables. Fixed in 0.6.0.5 already. - Python3.7: Fix, class declarations had memory leaks that were untestable before 3.7.1 fixed reference count issues in CPython. Fixed in 0.6.0.6 already. - Python3.7: Fix, asyncgen expressions can be created in normal functions without an immediate awaiting of the iterator. This new feature was not correctly supported. - Fix, star imports on the module level should disable built-in name optimization except for the most critical ones, otherwise e.g. names like ``all`` or ``pow`` can become wrong. Previous workarounds for ``pow`` were not good enough. - Fix, the scons for Python3 failed to properly report build errors due to a regression of the Scons version used for it. This would mask build errors on Windows. - Python3.4: Fix, packages didn't indicate that they are packages in their ``__spec__`` value, causing issues with ``importlib_resources`` module. - Python3.4: The ``__spec__`` values of compiled modules didn't have compatible ``origin`` and ``has_location`` values preventing ``importlib_resources`` module from working to load data files. - Fix, packages created from ``.pth`` files were also considered when checking for sub-packages of a module. - Standalone: Handle cases of conflicting DLLs better. On Windows pick the newest file version if different, and otherwise just report and pick randomly because we cannot really decide which ought to be loaded. - Standalone: Warn about collisions of DLLs on non-Windows only as this can happen with wheels apparently. - Standalone: For Windows Python extension modules ``.pyd`` files, remove the SxS configuration for cases where it causes problems, not needed. - Fix: The ``exec`` statement on file handles was not using the proper filename when compiling, therefore breaking e.g. ``inspect.getsource`` on functions defined there. - Standalone: Added support for OpenGL platform plugins to be included automatically. - Standalone: Added missing implicit dependency for ``zmq`` module. - Python3.7: Fix, using the ``-X utf8`` flag on the calling interpreter, aka ``--python-flag=utf8_mode`` was not preserved in the compiled binary in all cases. Optimization ============ - Enabled C target type ``void`` which will catch creating unused stuff more immediately and give better code for expression only statements. - Enabled in-place optimization for module variables, avoiding write back to the module dict for unchanged values, accelerating these operations. - Compile time memory savings for the ``yield`` node of Python2, no need to track if it is in an exception handler, not relevant there. - Using the single child node for the ``yield`` nodes gives memory savings at compile time for these, while also making them operate faster. - More kinds of in-place operations are now optimized, e.g. ``int += int`` and the ``bytes`` ones were specialized to perform real in-place extension where possible. - Loop variables no longer loose type information, but instead collect the set of possible type shapes allowing optimization for them. Organisational ============== - Corrected download link for Arch AUR link of develop package. - Added repository for Ubuntu Cosmic (18.10) for download. - Added repository for Fedora 29 for download. - Describe the exact format used for ``clang-format`` in the Developer Manual. - Added description how to use CondaCC on Windows to the User Manual. Cleanups ======== - The operations used for ``async for``, ``async with``, and ``await`` were all doing a look-up of an awaitable, and then executing the ``yield from`` that awaitable as one thing. Now this is split into two parts, with a new ``ExpressionYieldFromAwaitable`` as a dedicated node. - The ``yield`` node types, now 3 share a base class and common computation for now, enhancing the one for awaitiable, which was not fully annotating everything that can happen. - In code generation avoid statement blocks that are not needed, because there are no local C variables declared, and properly indent them. Tests ===== - Fixups for the manual Valgrind runner and the UI changes. - Test runner detects lock issue of ``clcache`` on Windows and considers it a permission problem that causes a retry. Summary ======= This addresses even more corner cases not working correctly, the out of the box experience should be even better now. The push towards C level performance for integer operation was held up by the realization that loop SSA was not yet there really, and that it had to be implemented, which of course now makes a huge difference for the cases where e.g. ``bool`` are being used. There is no C type for ``int`` used yet, which limits the impact of optimization to only taking shortcuts for the supported types. These are useful and faster of course, but only building blocks for what is to come. Most of the effort went into specialized helpers that e.g. add a ``float`` and and ``int`` value in a dedicated fashion, as well as comparison operations, so we can fully operate some minimal examples with specialized code. This is too limited still, and must be applied to ever more operations. What's more is that the benchmarking situation has not improved. Work will be needed in this domain to make improvements more demonstrable. It may well end up being the focus for the next release to improve Nuitka speedcenter to give more fine grained insights across minor changes of Nuitka and graphs with more history. ********************** Nuitka Release 0.6.0 ********************** This release adds massive improvements for optimization and a couple of bug fixes. It also indicates reaching the mile stone of doing actual type inference, even if only very limited. And with the new version numbers, lots of UI changes go along. The options to control recursion into modules have all been renamed, some now have different defaults, and finally the filenames output have changed. Bug Fixes ========= - Python3.5: Fix, the awaiting flag was not removed for exceptions thrown into a coroutine, so next time it appeared to be awaiting instead of finished. - Python3: Classes in generators that were using built-in functions crashed the compilation with C errors. - Some regressions for XML outputs from previous changes were fixed. - Fix, ``hasattr`` was not raising an exception if used with non-string attributes. - For really large compilations, MSVC linker could choke on the input file, line length limits, which is now fixed for the inline copy of Scons. - Standalone: Follow changed hidden dependency of ``PyQt5`` to ``PyQt5.sip`` for newer versions - Standalone: Include certificate file using by ``requests`` module in some cases as a data file. Optimization ============ - Enabled C target type ``nuitka_bool`` for variables that are stored with boolean shape only, and generate C code for those - Using C target type ``nuitka_bool`` many more expressions are now handled better in conditions. - Enhanced ``is`` and ``is not`` to be C source type aware, so they can be much faster for them. - Use C target type for ``bool`` built-in giving more efficient code for some source values. - Annotate the ``not`` result to have boolean type shape, allowing for more compile time optimization with it. - Restored previously lost optimization of loop break handling ``StopIteration`` which makes loops much faster again. - Restore lost optimization of subscripts with constant integer values making them faster again. - Optimize in-place operations for cases where left, right, or both sides have known type shapes for some values. Initially only a few variants were added, but there is more to come. - When adjacent parts of an f-string become known string constants, join them at compile time. - When there is only one remaining part in an f-string, use that directly as the result. - Optimize empty f-strings directly into empty strings constant during the tree building phase. - Added specialized attribute check for use in re-formulations that doesn't expose exceptions. - Remove locals sync operation in scopes without local variables, e.g. classes or modules, making ``exec`` and the like slightly leaner there. - Remove ``try`` nodes that did only re-raise exceptions. - The ``del`` of variables is now driven fully by C types and generates more compatible code. - Removed useless double exception exits annotated for expressions of conditions and added code that allows conditions to adapt themselves to the target shape bool during optimization. New Features ============ - Added support for using ``.egg`` files in ``PYTHONPATH``, one of the more rare uses, where Nuitka wasn't yet compatible. - Output binaries in standalone mode with platform suffix, on non-Windows that means no suffix. In accelerated mode on non-Windows, use ``.bin`` as a suffix to avoid collision with files that have no suffix. - Windows: It's now possible to use ``clang-cl.exe`` for ``CC`` with Nuitka as a third compiler on Windows, but it requires an existing MSVC install to be used for resource compilation and linking. - Windows: Added support for using ``ccache.exe`` and ``clcache.exe``, so that object files can now be cached for re-compilation. - For debug mode, report missing in-place helpers. These kinds of reports are to become more universal and are aimed at recognizing missed optimization chances in Nuitka. This features is still in its infancy. Subsequent releases will add more like these. Organisational ============== - Disabled comments on the web site, we are going to use Twitter instead, once the site is migrated to an updated Nikola. - The static C code is now formatted with ``clang-format`` to make it easier for contributors to understand. - Moved the construct runner to top level binary and use it from there, with future changes coming that should make it generally useful outside of Nuitka. - Enhanced the issue template to tell people how to get the ``develop`` version of Nuitka to try it out. - Added documentation for how use the object caching on Windows to the User Manual. - Removed the included GUI, originally intended for debugging, but XML outputs are more powerful anyway, and it had been in disrepair for a long time. - Removed long deprecated options, e.g. ``--exe`` which has long been the default and is no more accepted. - Renamed options to include plugin files to ``--include-plugin-directory`` and ``--include-plugin-files`` for more clarity. - Renamed options for recursion control to e.g. ``--follow-imports`` to better express what they actually do. - Removed ``--python-version`` support for switching the version during compilation. This has only worked for very specific circumstances and has been deprecated for a while. - Removed ``--code-gen-no-statement-lines`` support for not having line numbers updated at run time. This has long been hidden and probably would never gain all that much, while causing a lot of incompatibilty. Cleanups ======== - Moved command line arguments to dedicated module, adding checks was becoming too difficult. - Moved rich comparison helpers to a dedicated C file. - Dedicated binary and unary node bases for clearer distinction and more efficient memory usage of unuary nodes. Unary operations also no longer have in-place operation as an issue. - Major cleanup of variable accesses, split up into multiple phases and all including module variables being performed through C types, with no special cases anymore. - Partial cleanups of C type classes with code duplications, there is much more to resolve though. - Windows: The way ``exec`` was performed is discouraged in the ``subprocess`` documentation, so use a variant that cannot block instead. - Code proving information about built-in names and values was using not very portable constructs, and is now written in a way that PyPy would also like. Tests ===== - Avoid using ``2to3`` for basic operators test, removing test of some Python2 only stuff, that is covered elsewhere. - Added ability to cache output of CPython when comparing to it. This is to allow CI tests to not execute the same code over and over, just to get the same value to compare with. This is not enabled yet. Summary ======= This release marks a point, from which on performance improvements are likely in every coming release. The C target types are a major milestone. More C target types are in the work, e.g. ``void`` is coming for expressions that are done, but not used, that is scheduled for the next release. Although there will be a need to also adapt optimization to take full advantage of it, progress should be quick from here. There is a lot of ground to cover, with more C types to come, and all of them needing specialized helpers. But as soon as e.g. ``int``, ``str`` are covered, many more programs are going to benefiting from this. *********************** Nuitka Release 0.5.33 *********************** This release contains a bunch of fixes, most of which were previously released as part of hotfixes, and important new optimization for generators. Bug Fixes ========= - Fix, nested functions with local classes using outside function closure variables were not registering their usage, which could lead to errors at C compile time. Fixed in 0.5.32.1 already. - Fix, usage of built-in calls in a class level could crash the compiler if a class variable was updated with its result. Fixed in 0.5.32.1 already. - Python 3.7: The handling of non-type bases classes was not fully compatible and wrong usages were giving ``AttributeError`` instead of ``TypeError``. Fixed in 0.5.32.2 already. - Python 3.5: Fix, ``await`` expressions didn't annotate their exception exit. Fixed in 0.5.32.2 already. - Python3: The ``enum`` module usages with ``__new__`` in derived classes were not working, due to our automatic ``staticmethod`` decoration. Turns out, that was only needed for Python2 and can be removed, making enum work all the way. Fixed in 0.5.32.3 already. - Fix, recursion into ``__main__`` was done and could lead to compiler crashes if the main module was named like that. This is not prevented. Fixed in 0.5.32.3 already. - Python3: The name for list contraction's frames was wrong all along and not just changed for 3.7, so drop that version check on it. Fixed in 0.5.32.3 already. - Fix, the hashing of code objects has creating a key that could produce more overlaps for the hash than necessary. Using a ``C1`` on line 29 and ``C`` on line 129, was considered the same. And that is what actually happened. Fixed in 0.5.32.3 already. - macOS: Various fixes for newer Xcode versions to work as well. Fixed in 0.5.32.4 already. - Python3: Fix, the default ``__annotations__`` was the empty dict and could be modified, leading to severe corruption potentially. Fixed in 0.5.32.4 already. - Python3: When an exception is thrown into a generator that currently does a ``yield from`` is not to be normalized. - Python3: Some exception handling cases of ``yield from`` were leaking references to objects. Fixed in 0.5.32.5 already. - Python3: Nested namespace packages were not working unless the directory continued to exist on disk. Fixed in 0.5.32.5 already. - Standalone: Do not include ``icuuc.dll`` which is a system DLL. Fixed in 0.5.32.5 already. - Standalone: Added hidden dependency of newer version of ``sip``. Fixed in 0.5.32.5 already. - Standalone: Do not copy file permissions of DLLs and extension modules as that makes deleting and modifying them only harder. Fixed in 0.5.32.6 already. - Windows: The multiprocessing plugin was not always properly patching the run time for all module loads, made it more robust. Fixed in 0.5.32.6 already. - Standalone: Do not preserve permissions of copied DLLs, which can cause issues with read-only files on Windows when later trying to overwrite or remove files. - Python3.4: Make sure to disconnect finished generators from their frames to avoid potential data corruption. Fixed in 0.5.32.6 already. - Python3.5: Make sure to disconnect finished coroutines from their frames to avoid potential data corruption. Fixed in 0.5.32.6 already. - Python3.6: Make sure to disconnect finished asyncgen from their frames to avoid potential data corruption. Fixed in 0.5.32.6 already. - Python3.5: Explicit frame closes of frames owned by coroutines could corrupt data. Fixed in 0.5.32.7 already. - Python3.6: Explicit frame closes of frames owned by asyncgen could corrupt data. Fixed in 0.5.32.7 already. - Python 3.4: Fix threaded imports by properly handling ``_initializing`` in compiled modules ``__spec__`` attributes. Before it happen that another thread attempts to use an unfinished module. Fixed in 0.5.32.8 already. - Fix, the options ``--include-module`` and ``--include-package`` were present but not visible in the help output. Fixed in 0.5.32.8 already. - Windows: The multiprocessing plugin failed to properly pass compiled functions. Fixed in 0.5.32.8 already. - Python3: Fix, optimization for in-place operations on mapping values are not allowed and had to be disabled. Fixed in 0.5.32.8 already. - Python 3.5: Fixed exception handling with coroutines and asyncgen ``throw`` to not corrupt exception objects. - Python 3.7: Added more checks to class creations that were missing for full compatibility. - Python3: Smarter hashing of unicode values avoids increased memory usage from cached converted forms in debug mode. Organisational ============== - The issue tracker on Github is now the one that should be used with Nuitka, winning due to easier issue templating and integration with pull requests. - Document the threading model and exception model to use for MinGW64. - Removed the ``enum`` plug-in which is no longer useful after the improvements to the ``staticmethod`` handling for Python3. - Added Python 3.7 testing for Travis. - Make it clear in the documentation that ``pyenv`` is not supported. - The version output includes more information now, OS and architecture, so issue reports should contain that now. - On PyPI we didn't yet indicated Python 3.7 as supported, which it of course is. New Features ============ - Added support for MiniConda Python. Optimization ============ - Using goto based generators that return from execution and resume based on heap storage. This makes tests using generators twice as fast and they no longer use a full C stack of 2MB, but only 1K instead. - Conditional ``a if cond else b``, ``a and b``, ``a or b`` expressions of which the result value is are now transformed into conditional statements allowing to apply further optimizations to the right and left side expressions as well. - Replace unused function creations with side effects from their default values with just those, removing more unused code. - Put all statement related code and declarations for it in a dedicated C block, making things slightly more easy for the C compiler to re-use the stack space. - Avoid linking against ``libpython`` in module mode on everything but Windows where it is really needed. No longer check for static Python, not needed anymore. - More compact function, generator, and asyncgen creation code for the normal cases, avoid qualname if identical to name for all of them. - Python2 class dictionaries are now indeed directly optimized, giving more compact code. - Module exception exits and thus its frames have become optional allowing to avoid some code for some special modules. - Uncompiled generator integration was backported to 3.4 as well, improving compatibility and speed there as well. Cleanups ======== - Frame object and their cache declarations are now handled by the way of allocated variable descriptions, avoid special handling for them. - The interface to "forget" a temporary variable has been replaced with a new method that skips a number for it. This is done to keep expression use the same indexes for all their child expressions, but this is more explicit. - Instead of passing around C variables names for temporary values, we now have full descriptions, with C type, code name, storage location, and the init value to use. This makes the information more immediately available where it is needed. - Variable declarations are now created when needed and stored in dedicated variable storage objects, which then in can generate the code as necessary. - Module code generation has been enhanced to be closer to the pattern used by functions, generators, etc. - There is now only one spot that creates variable declaration, instead of previous code duplications. - Code objects are now attached to functions, generators, coroutines, and asyncgen bodies, and not anymore to the creation of these objects. This allows for simpler code generation. - Removed fiber implementations, no more needed. Tests ===== - Finally the asyncgen tests can be enabled in the CPython 3.6 test suite as the corrupting crash has been identified. - Cover ever more cases of spurious permission problems on Windows. - Added the ability to specify specific modules a comparison test should recurse to, making some CPython tests follow into modules where actual test code lives. Summary ======= This release is huge in many ways. First, finishing "goto generators" clears an old scalability problem of Nuitka that needed to be addressed. No more do generators/coroutines/asyncgen consume too much memory, but instead they become as lightweight as they ought to be. Second, the use of variable declarations carying type information all through the code generation, is an important pre-condition for "C types" work to resume and become possible, what will be 0.6.0 and the next release. Third, the improved generator performance will be removing a lot of cases, where Nuitka wasn't as fast, as its current state not using "C types" yet, should allow. It is now consistently faster than CPython for everything related to generators. Fourth, the fibers were a burden for the debugging and linking of Nuitka on various platforms, as they provided deprecated interfaces or not. As they are now gone, Nuitka ought to definitely work on any platform where Python works. From here on, C types work can take it, and produce the results we are waiting for in the next major release cycle that is about to start. Also the amount of fixes for this release has been incredibly high. Lots of old bugs esp. for coroutines and asyncgen have been fixed, this is not only faster, but way more correct. Mainly due to the easier debugging and interface to the context code, bugs were far easier to avoid and/or find. *********************** Nuitka Release 0.5.32 *********************** This release contains substantial new optimization, bug fixes, and already the full support for Python 3.7. Among the fixes, the enhanced coroutine work for compatibility with uncompiled ones is most important. Bug Fixes ========= - Fix, was optimizing write backs of attribute in-place assignments falsely. - Fix, generator stop future was not properly supported. It is now the default for Python 3.7 which showed some of the flaws. - Python3.5: The ``__qualname__`` of coroutines and asyncgen was wrong. - Python3.5: Fix, for dictionary unpackings to calls, check the keys if they are string values, and raise an exception if not. - Python3.6: Fix, need to check assignment unpacking for too short sequences, we were giving ``IndexError`` instead of ``ValueError`` for these. Also the error messages need to consider if they should refer to "at least" in their wording. - Fix, outline nodes were cloned more than necessary, which would corrupt the code generation if they later got removed, leading to a crash. - Python3.5: Compiled coroutines awaiting uncompiled coroutines was not working properly for finishing the uncompiled ones. Also the other way around was raising a ``RuntimeError`` when trying to pass an exception to them when they were already finished. This should resolve issues with ``asyncio`` module. - Fix, side effects of a detected exception raise, when they had an exception detected inside of them, lead to an infinite loop in optimization. They are now optimized in-place, avoiding an extra step later on. New Features ============ - Support for Python 3.7 with only some corner cases not supported yet. Optimization ============ - Delay creation of ``StopIteration`` exception in generator code for as long as possible. This gives more compact code for generations, which now pass the return values via compiled generator attribute for Python 3.3 or higher. - Python3: More immediate re-formulation of classes with no bases. Avoids noise during optimization. - Python2: For class dictionaries that are only assigned from values without side effects, they are not converted to temporary variable usages, allowing the normal SSA based optimization to work on them. This leads to constant values for class dictionaries of simple classes. - Explicit cleanup of nodes, variables, and local scopes that become unused, has been added, allowing for breaking of cyclic dependencies that prevented memory release. Tests ===== - Adapted 3.5 tests to work with 3.7 coroutine changes. - Added CPython 3.7 test suite. Cleanups ======== - Removed remaining code that was there for 3.2 support. All uses of version comparisons with 3.2 have been adapted. For us, Python3 now means 3.3, and we will not work with 3.2 at all. This removed a fair bit of complexity for some things, but not all that much. - Have dedicated file for import released helpers, so they are easier to find if necessary. Also do not have code for importing a name in the header file anymore, not performance relevant. - Disable Python warnings when running scons. These are particularly given when using a Python debug binary, which is happening when Nuitka is run with ``--python-debug`` option and the inline copy of Scons is used. - Have a factory function for all conditional statement nodes created. This solved a TODO and handles the creation of statement sequences for the branches as necessary. - Split class reformulation into two files, one for Python2 and one for Python3 variant. They share no code really, and are too confusing in a single file, for the huge code bodies. - Locals scopes now have a registry, where functions and classes register their locals type, and then it is created from that. - Have a dedicated helper function for single argument calls in static code that does not require an array of objects as an argument. Organisational ============== - There are now ``requirements-devel.txt`` and ``requirements.txt`` files aimed at usage with scons and by users, but they are not used in installation. Summary ======= This releases has this important step to add conversion of locals dictionary usages to temporary variables. It is not yet done everywhere it is possible, and the resulting temporary variables are not yet propagated in the all the cases, where it clearly is possible. Upcoming releases ought to achieve that most Python2 classes will become to use a direct dictionary creation. Adding support for Python 3.7 is of course also a huge step. And also this happened fairly quickly and soon after its release. The generic classes it adds were the only real major new feature. It breaking the internals for exception handling was what was holding back initially, but past that, it was really easy. Expect more optimization to come in the next releases, aiming at both the ability to predict Python3 metaclasses ``__prepare__`` results, and at more optimization applied to variables after they became temporary variables. *********************** Nuitka Release 0.5.31 *********************** This release is massive in terms of fixes, but also adds a lot of refinement to code generation, and more importantly adds experimental support for Python 3.7, while enhancing support for Pyt5 in standalone mode by a lot. Bug Fixes ========= - Standalone: Added missing dependencies for ``PyQt5.Qt`` module. - Plugins: Added support for ``PyQt5.Qt`` module and its ``qml`` plugins. - Plugins: The sensible plugin list for PyQt now includes that platforms plugins on Windows too, as they are kind of mandatory. - Python3: Fix, for uninstalled Python versions wheels that linked against the ``Python3`` library as opposed to ``Python3X``, it was not found. - Standalone: Prefer DLLs used by main program binary over ones used by wheels. - Standalone: For DLLs added by Nuitka plugins, add the package directory to the search path for dependencies where they might live. - Fix, the ``vars`` built-in didn't annotate its exception exit. - Python3: Fix, the ``bytes`` and ``complex`` built-ins needs to be treated as a slot too. - Fix, consider if ``del`` variable must be assigned, in which case no exception exit should be created. This prevented ``Tkinter`` compilation. - Python3.6: Added support for the following language construct: .. code:: python d = {"metaclass": M} class C(**d): pass - Python3.5: Added support for cyclic imports. Now a ``from`` import with a name can really cause an import to happen, not just a module attribute lookup. - Fix, ``hasattr`` was never raising exceptions. - Fix, ``bytearray`` constant values were considered to be non-iterable. - Python3.6: Fix, now it is possible to ``del __annotations__`` in a class and behave compatible. Previously in this case we were falling back to the module variable for annotations used after that which is wrong. - Fix, some built-in type conversions are allowed to return derived types, but Nuitka assumed the exact type, this affected ``bytes``, ``int``, ``long``, ``unicode``. - Standalone: Fix, the ``_socket`` module was insisted on to be found, but can be compiled in. New Features ============ - Added experimental support for Python 3.7, more work will be needed though for full support. Basic tests are working, but there are are at least more coroutine changes to follow. - Added support for building extension modules against statically linked Python. This aims at supporting manylinux containers, which are supposed to be used for creating widely usable binary wheels for Linux. Programs won't work with statically linked Python though. - Added options to allow ignoring the Windows cache for DLL dependencies or force an update. - Allow passing options from distutils to Nuitka compilation via setup options. - Added option to disable the DLL dependency cache on Windows as it may become wrong after installing new software. - Added experimental ability to provide extra options for Nuitka to setuptools. - Python3: Remove frame preservation and restoration of exceptions. This is not needed, but leaked over from Python2 code. Optimization ============ - Apply value tracing to local dict variables too, enhancing the optimization for class bodies and function with ``exec`` statements by a lot. - Better optimization for "must not have value", wasn't considering merge traces of uninitialized values, for which this is also the case. - Use 10% less memory at compile time due to specialized base classes for statements with a single child only allowing ``__slots__`` usage by not having multiple inheritance for those. - More immediately optimize branches with known truth values, so that merges are avoided and do not prevent trace based optimization before the pass after the next one. In some cases, optimization based on traces could fail to be done if there was no next pass caused by other things. - Much faster handling for functions with a lot of ``eval`` and ``exec`` calls. - Static optimization of ``type`` with known type shapes, the value is predicted at compile time. - Optimize containers for all compile time constants into constant nodes. This also enables further compile time checks using them, e.g. with ``isinstance`` or ``in`` checks. - Standalone: Using threads when determining DLL dependencies. This will speed up the un-cached case on Windows by a fair bit. - Also remove unused assignments for mutable constant values. - Python3: Also optimize calls to ``bytes`` built-in, this was so far not done. - Statically optimize iteration over constant values that are not iterable into errors. - Removed Fortran, Java, LaTex, PDF, etc. stuff from the inline copies of Scons for faster startup and leaner code. Also updated to 3.0.1 which is no important difference over 3.0.0 for Nuitka however. - Make sure to always release temporary objects before checking for error exits. When done the other way around, more C code than necessary will be created, releasing them in both normal case and error case after the check. - Also remove unused assignments in case the value is a mutable constant. Cleanups ======== - Don't store "version" numbers of variable traces for code generation, instead directly use the references to the value traces instead, avoiding later lookups. - Added dedicated module for ``complex`` built-in nodes. - Moved C helpers for integer and complex types to dedicated files, solving the TODOs around them. - Removed some Python 3.2 only codes. Organisational ============== - For better bug reports, the ``--version`` output now contains also the Python version information and the binary path being used. - Started using specialized exceptions for some types of errors, which will output the involved data for better debugging without having to reproduce anything. This does e.g. output XML dumps of problematic nodes. - When encountering a problem (compiler crash) in optimization, output the source code line that is causing the issue. - Added support for Fedora 28 RPM builds. - Remove more instances of mentions of 3.2 as supported or usable. - Renovated the graphing code and made it more useful. Summary ======= This release marks important progress, as the locals dictionary tracing is a huge step ahead in terms of correctness and proper optimization. The actual resulting dictionary is not yet optimized, but that ought to follow soon now. The initial support of 3.7 is important. Right now it apparently works pretty well as a 3.6 replacement already, but definitely a lot more work will be needed to fully catch up. For standalone, this accumulated a lot of improvements related to the plugin side of Nuitka. Thanks to those involved in making this better. On Windows things ought to be much faster now, due to parallel usage of dependency walker. *********************** Nuitka Release 0.5.30 *********************** This release has improvements in all areas. Many bug fixes are accompanied with optimization changes towards value tracing. Bug Fixes ========= - Fix, the new setuptools runners were not used by ``pip`` breaking the use of Nuitka from PyPI. - Fix, imports of ``six.moves`` could crash the compiler for built-in names. Fixed in 0.5.29.2 already. - Windows: Make the ``nuitka-run`` not a symlink as these work really bad on that platform, instead make it a full copy just like we did for ``nuitka3-run`` already. Fixed in 0.5.29.2 already. - Python3.5: In module mode, ``types.coroutine`` was monkey patched into an endless recursion if including more than one module, e.g. for a package. Fixed in 0.5.29.3 already. - Python3.5: Dictionary unpackings with both star arguments and non star arguments could leak memory. Fixed in 0.5.29.3 already. .. code:: python c = {a: 1, **d} - Fix, distutils usage was not working for Python2 anymore, due to using ``super`` for what are old style classes on that version. - Fix, some method calls to C function members could leak references. .. code:: python class C: for_call = functools.partial def m(self): self.for_call() # This leaked a reference to the descriptor. - Python3.5: The bases classes should be treated as an unpacking too. .. code:: python class C(*D): # Allowed syntax that was not supported. pass - Windows: Added back batch files to run Nuitka from the command line. Fixed in 0.5.29.5 already. New Features ============ - Added option ``--include-package`` to force inclusion of a whole package with the submodules in a compilation result. - Added options ``--include-module`` to force inclusion of a single module in a compilation result. - The ``multiprocessing`` plug-in got adapted to Python 3.4 changes and will now also work in accelerated mode on Windows. - It is now possible to specify the Qt plugin directories with e.g. ``--enable-plugin-=qt_plugins=imageformats`` and have only those included. This should avoid dependency creep for shared libraries. - Plugins can now make the decision about recursing to a module or not. - Plugins now can get their own options passed. Optimization ============ - The re-raising of exceptions has gotten its own special node type. This aims at more readability (XML output) and avoiding the overhead of checking potential attributes during optimization. - Changed built-in ``int``, ``long``, and ``float`` to using a slot mechanism that also analyses the type shape and detects and warns about errors at compile time. - Changed the variable tracing to value tracing. This meant to cleanup all the places that were using it to find the variable. - Enable must have / must not value value optimization for all kinds of variables including module and closure variables. This often avoids error exits and leads to smaller and faster generated code. Tests ===== - Added burn test with local install of pip distribution to virtualenv before making any PyPI upload. It seems pip got its specific error sources too. - Avoid calling ``2to3`` and prefer `` -m lib2to3`` instead, as it seems at least Debian Testing stopped to provide the binary by default. For Python 2.6 and 3.2 we continue to rely on it, as the don't support that mode of operation. - The PyLint checks have been made more robust and even more Python3 portable. - Added PyLint to Travis builds, so PRs are automatically checked too. - Added test for distutils usage with Nuitka that should prevent regressions for this new feature and to document how it can be used. - Make coverage taking work on Windows and provide the full information needed, the rendering stage is not there working yet though. - Expanded the trick assignment test cases to cover more slots to find bugs introduced with more aggressive optimization of closure variables. - New test to cover multiprocessing usage. - Generating more code tests out of doctests for increased coverage of Nuitka. Cleanups ======== - Stop using ``--python-version`` in tests where they still remained. - Split the forms of ``int`` and ``long`` into two different nodes, they share nothing except the name. Create the constants for the zero arg variant more immediately. - Split the output comparison part into a dedicated testing module so it can be re-used, e.g. when doing distutils tests. - Removed dead code from variable closure taking. - Have a dedicated module for the metaclass of nodes in the tree, so it is easier to find, and doesn't clutter the node base classes module as much. - Have a dedicated node for reraise statements instead of checking for all the arguments to be non-present. Organisational ============== - There is now a pull request template for Github when used. - Deprecating the ``--python-version`` argument which should be replaced by using ``-m nuitka`` with the correct Python version. Outputs have been updated to recommend this one instead. - Make automatic import sorting and autoformat tools properly executable on Windows without them changing new lines. - The documentation was updated to prefer the call method with ``-m nuitka`` and manually providing the Python binary to use. Summary ======= This release continued the distutils integration adding first tests, but more features and documentation will be needed. Also, for the locals dictionary work, the variable tracing was made generic, but not yet put to use. If we use this to also trace dictionary keys, we can expect a lot of improvements for class code again. The locals dictionary tracing will be the focus before resuming the work on C types, where the ultimate performance boost lies. However, currently, not the full compatibility has been achieved even with currently using dictionaries for classes, and we would like to be able to statically optimize those better anyway. *********************** Nuitka Release 0.5.29 *********************** This release comes with a lot of improvements across the board. A lot of focus has been givevn to the packaging side of Nuitka, but also there is a lot of compatibility work. Bug Fixes ========= - Windows: When using Scons for Python3 and Scons for Python2 on the same build directory, a warning would be given about the need to migrate. Make the Scons cache directory use the Python ABI version as a key too, to avoid these issues. Fixed in 0.5.28.1 already. - Windows: Fixup for Python3 and Scons no more generating the MinGW64 import library for Python anymore properly. Was only working if cached from a previous install of Nuitka. Fixed in 0.5.28.1 already. - Plugins: Made the data files plugin mandatory and added support for the scrapy package needs. - Fix, added implicit dependencies for ``pkg_resources.external`` package. Fixed in 0.5.28.1 already. - Fix, an import of ``x.y`` where this was not a package didn't cause the package ``x`` to be included. - Standalone: Added support for ``six.moves`` and ``requests.packages`` meta imports, these cause hidden implicit imports, that are now properly handled. - Standalone: Patch the ``__file__`` value for technical bytecode modules loaded during Python library initialization in a more compatible way. - Standalone: Extension modules when loaded might actually raise legit errors, e.g. ``ImportError`` of another module, don't make those into ``SystemError`` anymore. - Python3.2: The ``__package__`` of sub-packages was wrong, which could cause issues when doing relative imports in that sub-package. - Python3: Contractions in a finally clause could crash the compiler. - Fix, unused closure variables could lead to a crash in they were passed to a nested function. - Linux: Standalone dependency analysis could enter an endless recursion in case of cyclic dependencies. - Python3.6: Async generation expressions need to return a ``None`` value too. - Python3.4: Fix, ``__spec__`` is a package attribute and not a built-in value. New Features ============ - It is now possible to run Nuitka with ``some_python_you_choose -m nuitka ...`` and therefore know exactly which Python installation is going to be used. It does of course need Nuitka installed for this to work. This mechanism is going to replace the ``--python-version`` mechanism in the future. - There are dedicated runners for Python3, simply use ``nuitka3`` or ``nuitka3-run`` to execute Nuitka if your code is Python3 code. - Added warning for implicit exception raises due to mismatch in unpacking length. These are statically detected, but so far were not warned about. - Added cache for ``depends.exe`` results. This speeds up standalone mode again as some of these calls were really slow. - The import tracer is more robust against recursion and works with Python3 now. - Added an option to assume yes for downloading questions. The currently only enables the download of ``depends.exe`` and is intended for CI servers. - There is now a report file for scons, which records the values used to run things, this could be useful for debugging. - Nuitka now registers with distutils and can be used with ``bdist_wheel`` directly, but this lacks documentation and tests. Many improvements in the distutils build. Optimization ============ - Forward propagate compile time constants even if they are only potential usages. This is actually the case where this makes the most sense, as it might remove its use entirely from the branches that do not use it. - Avoid extra copy of ``finally`` code. The cloning operation takes time and memory, and this shaved of 0.3% of Nuitka memory usage, as these can also become dangling. - Class dictionaries are now proper dictionarties in optimization, using some dedicated code for name lookups that are transformed to dedicated locals dictionary or mapping (Python3) accesses. This currently does not fully optimize, but will in coming releases, and saves about 25% of memory compared to the old code. - Treating module attributes ``__package__``, ``__loader__``, ``__file__``, and ``__spec__`` with dedicated nodes, that allow or forbid optimization dependent on usage. - Python3.6: Async generator expressions were not working fully, become more compatible. - Fix, using ``super`` inside a contraction could crash the compiler. - Fix, also accept ``__new__`` as properly decorated in case it's a ``classmethod`` too. - Fix, removed obsolete ``--nofreeze-stdlib`` which only complicated using the ``--recurse-stdlib`` which should be used instead. Organisational ============== - The ``nuitka`` Python package is now installed into the public namespace and used from there. There are distinct copies to be installed for both Python2 and Python3 on platforms where it is supported. - Using ``twine`` for upload to PyPI now as recommended on their site. - Running ``pylint`` on Windows became practical again. - Added RPM packages for Fedora 26 and 27, these used to fail due to packaging issues. - Added RPM packages for openSUSE Leap 42.2, 42.3 and 15.0 which were simply missing. - Added RPM packages for SLE 15. - Added support for PyLint 1.8 and its new warnings. - The RPM packages no longer contain ``nuitka-run3``, it will be replaced by the new ``nuitka3-run`` which is in all packages. - The runners used for installation are now easy install created, but patched to avoid overhead at run time. - Added repository for Ubuntu Artful (17.10) for download, removed support for Ubuntu Yakkety, Vivid and Zesty (no more supported by them). - Removed support for Debian Wheezy and Ubuntu Precise (they are too old for modern packaging used). - There is now a issue template for Github when used. Tests ===== - Windows: Standalone tests were referencing an old path to ``depends.exe`` that wasn't populated on new installs. - Refinements for CPython test suites to become more stable in results. Some tests occasionally fail to clean up, or might do indetermistic outputs, or are not relevant at all. - The tests don't use the runners, but more often do ``-m nuitka`` to become executable without having to find the proper runner. This improves usage during the RPM builds and generally. - Travis: Do not test development versions of CPython, even for stable release, they break too often. Summary ======= This release consolidates a lot of what we already had, adding hopeful stuff for distutils integration. This will need tests and documentation though, but should make Nuitka really easy to use. A few features are still missing to make it generally reliable in that mode, but they are going to come. Also the locals dictionary work is kind of incomplete without a proper generic tracing of not only local variables, but also dictionary keys. With that work in place, a lot of improvements will happen. *********************** Nuitka Release 0.5.28 *********************** This release has a focus on compatibility work and contains bug fixes and work to enhance the usability of Nuitka by integrating with distutils. The major improvement is that contractions no longer use pseudo functions to achieve their own local scope, but that there is now a dedicated structure for that representing an in-lined function. Bug Fixes ========= - Python3.6: Fix, ``async for`` was not yet implemented for async generators. - Fix, functions with keyword arguments where the value was determined to be a static raise could crash the compiler. - Detect using MinGW64 32 bits C compiler being used with 64 bits Python with better error message. - Fix, when extracting side effects of a static raise, extract them more recursively to catch expressions that themselves have no code generation being used. This fixes at least static raises in keyword arguments of a function call. - Compatibility: Added support for proper operation of ``pkgutil.get_data`` by implementing ``get_data`` in our meta path based loader. - Compatibility: Added ``__spec__`` module attribute was previously missing, present on Python3.4 and higher. - Compatibility: Made ``__loader__`` module attribute set when the module is loading already. - Standalone: Resolve the ``@rpath`` and ``@loader_path`` from ``otool`` on macOS manually to actual paths, which adds support for libraries compiled with that. - Fix, nested functions calling ``super`` could crash the compiler. - Fix, could not use ``--recurse-directory`` with arguments that had a trailing slash. - Fix, using ``--recurse-directory`` on packages that are not in the search crashed the compiler. - Compatibility: Python2 ``set`` and ``dict`` contractions were using extra frames like Python3 does, but those are not needed. - Standalone: Fix, the way ``PYTHONHOME`` was set on Windows had no effect, which allowed the compiled binary to access the original installation still. - Standalone: Added some newly discovered missing hidden dependencies of extension modules. - Compatibility: The name mangling of private names (e.g. ``__var``) in classes was applied to variable names, and function declarations, but not to classes yet. - Python3.6: Fix, added support for list contractions with ``await`` expressions in async generators. - Python3.6: Fix, ``async for`` was not working in async generators yet. - Fix, for module tracebacks, we output the module name `` instead of merely ````, but if the module was in a package, that was not indicated. Now it is ````. - Windows: The cache directory could be unicode which then failed to pass as an argument to scons. We now encode such names as UTF-8 and decode in Scons afterwards, solving the problem in a generic way. - Standalone: Need to recursively resolve shared libraries with ``ldd``, otherwise not all could be included. - Standalone: Make sure ``sys.path`` has no references to CPython compile time paths, or else things may work on the compiling machine, but not on another. - Standalone: Added various missing dependencies. - Standalone: Wasn't considering the DLLs directory for standard library extensions for freezing, which would leave out these. - Compatibility: For ``__future__`` imports the ``__import__`` function was called more than once. Optimization ============ - Contractions are now all properly inlined and allow for optimization as if they were fully local. This should give better code in some cases. - Classes are now all building their locals dictionary inline to the using scope, allowing for more compact code. - The dictionary API was not used in module template code, although it helps to generate more compact code. New Features ============ - Experimental support for building platform dependent wheel distribution. .. code:: bash python setup.py --command-packages=nuitka.distutils clean -a bdist_nuitka Use with caution, this is incomplete work. - Experimental support for running tests against compiled installation with ``nose`` and ``py.test``. - When specifying what to recurse to, now patterns can be used, e.g. like this ``--recurse-not-to=*.tests`` which will skip all tests in submodules from compilation. - By setting ``NUITKA_PACKAGE_packagename=/some/path`` the ``__path__`` of packages can be extended automatically in order to allow and load uncompiled sources from another location. This can be e.g. a ``tests`` sub-package or other plugins. - By default when creating a module, now also a ``module.pyi`` file is created that contains all imported modules. This should be deployed alongside the extension module, so that standalone mode creation can benefit from knowing the dependencies of compiled code. - Added option ``--plugin-list`` that was mentioned in the help output, but still missing so far. - The import tracing of the ``hints`` module has achieved experimental status and can be used to test compatibility with regards to import behavior. Cleanups ======== - Rename tree and codegen ``Helper`` modules to unique names, making them easier to work with. - Share the code that decides to not warn for standard library paths with more warnings. - Use the ``bool`` enum definition of Python2 which is more elegant than ours. - Move quality tools, autoformat, isort, etc. to the ``nuitka.tools.quality`` namespace. - Move output comparison tool to the ``nuitka.tools.testing`` namespace. - Made frame code generation capable of using nested frames, allowing the real inline of classes and contraction bodies, instead of "direct" calls to pseudo functions being used. - Proper base classes for functions that are entry points, and functions that are merely a local expression using return statements. Tests ===== - The search mode with pattern, was not working anymore. - Resume hash values now consider the Python version too. - Added test that covers using test runners like ``nose`` and ``py.test`` with Nuitka compiled extension modules. Organisational ============== - Added support for Scons 3.0 and running Scons with Python3.5 or higher. The option to specify the Python to use for scons has been renamed to reflect that it may also be a Python3 now. Only for Python3.2 to Python3.4 we now need another Python installation. - Made recursion the default for ``--recurse-directory`` with packages. Before you also had to tell it to recurse into that package or else it would only include the top level package, but nothing below. - Updated the man pages, correct mentions of its C++ to C and don't use now deprecated options. - Updated the help output which still said that standalone mode implies recursion into standard library, which is no longer true and even not recommended. - Added option to disable the output of ``.pyi`` file when creating an extension module. - Removed Ubuntu Wily package download, no longer supported by Ubuntu. Summary ======= This release was done to get the fixes and new features out for testing. There is work started that should make generators use an explicit extra stack via pointer, and restore instruction state via goto dispatchers at function entry, but that is not complete. This feature, dubbed "goto generators" will remove the need for fibers (which is itself a lot of code), reduce the memory footprint at run time for anything that uses a lot of generators, or coroutines. Integrating with ``distutils`` is also a new thing, and once completed will make use of Nuitka for existing projects automatic and trivial to do. There is a lot missing for that goal, but we will get there. Also, documenting how to run tests against compiled code, if that test code lives inside of that package, will make a huge difference, as that will make it easier for people to torture Nuitka with their own test cases. And then of course, nested frames now mean that every function could be inlined, which was previously not possible due to collisions of frames. This will pave the route for better optimization in those cases in future releases. The experimental features will require more work, but should make it easier to use Nuitka for existing projects. Future releases will make integrating Nuitka dead simple, or that is the hope. And last but not least, now that Scons works with Python3, chances are that Nuitka will more often work out the of the box. The older Python3 versions that still retain the issue are not very widespread. *********************** Nuitka Release 0.5.27 *********************** This release comes a lot of bug fixes and improvements. Bug Fixes ========= - Fix, need to add recursed modules immediately to the working set, or else they might first be processed in second pass, where global names that are locally assigned, are optimized to the built-in names although that should not happen. Fixed in 0.5.26.1 already. - Fix, the accelerated call of methods could crash for some special types. This had been a regress of 0.5.25, but only happens with custom extension types. Fixed in 0.5.26.1 already. - Python3.5: For ``async def`` functions parameter variables could fail to properly work with in-place assignments to them. Fixed in 0.5.26.4 already. - Compatibility: Decorators that overload type checks didn't pass the checks for compiled types. Now ``isinstance`` and as a result ``inspect`` module work fine for them. - Compatibility: Fix, imports from ``__init__`` were crashing the compiler. You are not supposed to do them, because they duplicate the package code, but they work. - Compatibility: Fix, the ``super`` built-in on module level was crashing the compiler. - Standalone: For Linux, BSD and macOS extension modules and shared libraries using their own ``$ORIGIN`` to find loaded DLLs resulted in those not being included in the distribution. - Standalone: Added more missing implicit dependencies. - Standalone: Fix, implicit imports now also can be optional, as e.g. ``_tkinter`` if not installed. Only include those if available. - The ``--recompile-c-only`` was only working with C compiler as a backend, but not in the C++ compatibility fallback, where files get renamed. This prevented that edit and test debug approach with at least MSVC. - Plugins: The PyLint plug-in didn't consider the symbolic name ``import-error`` but only the code ``F0401``. - Implicit exception raises in conditional expressions would crash the compiler. New Features ============ - Added support for Visual Studio 2017. - Added option ``--python2-for-scons`` to specify the Python2 execute to use for calling Scons. This should allow using Anaconda Python for that task. Optimization ============ - References to known unassigned variables are now statically optimized to exception raises and warned about if the according option is enabled. - Unhashable keys in dictionaries are now statically optimized to exception raises and warned about if the according option is enabled. - Enable forward propagation for classes too, resulting in some classes to create only static dictionaries. Currently this never happens for Python3, but it will, once we can statically optimize ``__prepare__`` too. - Enable inlining of class dictionary creations if they are mere return statements of the created dictionary. Currently this never happens for Python3, see above for why. - Python2: Selecting the metaclass is now visible in the tree and can be statically optimized. - For executables, we now also use a freelist for traceback objects, which also makes exception cases slightly faster. - Generator expressions no longer require the use of a function call with a ``.0`` argument value to carry the iterator value, instead their creation is directly inlined. - Remove "pass through" frames for Python2 list contractions, they are no longer needed. Minimal gain for generated code, but more lightweight at compile time. - When compiling Windows x64 with MinGW64 a link library needs to be created for linking against the Python DLL. This one is now cached and re-used if already done. - Use common code for ``NameError`` and ``UnboundLocalError`` exception code raises. In some cases it was creating the full string at compile time, in others at run time. Since the later is more efficient in terms of code size, we now use that everywhere, saving a bit of binary size. - Make sure to release unused functions from a module. This saves memory and can be decided after a full pass. - Avoid using ``OrderedDict`` in a couple of places, where they are not needed, but can be replaced with a later sorting, e.g. temporary variables by name, to achieve deterministic output. This saves memory at compile time. - Add specialized return nodes for the most frequent constant values, which are ``None``, ``True``, and ``False``. Also a general one, for constant value return, which avoids the constant references. This saves quite a bit of memory and makes traversal of the tree a lot faster, due to not having any child nodes for the new forms of return statements. - Previously the empty dictionary constant reference was specialized to save memory. Now we also specialize empty set, list, and tuple constants to the same end. Also the hack to make ``is`` not say that ``{} is {}`` was made more general, mutable constant references and now known to never alias. - The source references can be marked internal, which means that they should never be visible to the user, but that was tracked as a flag to each of the many source references attached to each node in the tree. Making a special class for internal references avoids storing this in the object, but instead it's now a class property. - The nodes for named variable reference, assignment, and deletion got split into separate nodes, one to be used before the actual variable can be determined during tree building, and one for use later on. This makes their API clearer and saves a tiny bit of memory at compile time. - Also eliminated target variable references, which were pseudo children of assignments and deletion nodes for variable names, that didn't really do much, but consume processing time and memory. - Added optimization for calls to ``staticmethod`` and ``classmethod`` built-in methods along with type shapes. - Added optimization for ``open`` built-in on Python3, also adding the type shape ``file`` for the result. - Added optimization for ``bytearray`` built-in and constant values. These mutable constants can now be compile time computed as well. - Added optimization for ``frozenset`` built-in and constant values. These mutable constants can now be compile time computed as well. - Added optimization for ``divmod`` built-in. - Treat all built-in constant types, e.g. ``type`` itself as a constant. So far we did this only for constant values types, but of course this applies to all types, giving slightly more compact code for their uses. - Detect static raises if iterating over non-iterables and warn about them if the option is enabled. - Split of ``locals`` node into different types, one which needs the updated value, and one which just makes a copy. Properly track if a functions needs an updated locals dict, and if it doesn't, don't use that. This gives more efficient code for Python2 classes, and ``exec`` using functions in Python2. - Build all constant values without use of the ``pickle`` module which has a lot more overhead than ``marshal``, instead use that for too large ``long`` values, non-UTF8 ``unicode`` values, ``nan`` float, etc. - Detect the linker arch for all Linux platforms using ``objdump`` instead of only a hand few hard coded ones. Cleanups ======== - The use of ``INCREASE_REFCOUNT`` got fully eliminated. - Use functions not vulenerable for buffer overflow. This is generally good and avoids warnings given on OpenBSD during linking. - Variable closure for classes is different from all functions, don't handle the difference in the base class, but for class nodes only. - Make sure ``mayBeNone`` doesn't return ``None`` which means normally "unclear", but ``False`` instead, since it's always clear for those cases. - Comparison nodes were using the general comparison node as a base class, but now a proper base class was added instead, allowing for cleaner code. - Valgrind test runners got changed to using proper tool namespace for their code and share it. - Made construct case generation code common testing code for re-use in the speedcenter web site. The code also has minor beauty bugs which will then become fixable. - Use ``appdirs`` package to determine place to store the downloaded copy of ``depends.exe``. - The code still mentioned C++ in a lot of places, in comments or identifiers, which might be confusing readers of the code. - Code objects now carry all information necessary for their creation, and no longer need to access their parent to determine flag values. That parent is subject to change in the future. - Our import sorting wrapper automatically detects imports that could be local and makes them so, removing a few existing ones and preventing further ones on the future. - Cleanups and annotations to become Python3 PyLint clean as well. This found e.g. that source code references only had ``__cmp__`` and need rich comparison to be fully portable. Tests ===== - The test runner for construct tests got cleaned up and the constructs now avoid using ``xrange`` so as to not need conversion for Python3 execution as much. - The main test runner got cleaned up and uses common code making it more versatile and robust. - Do not run test in debugger if CPython also segfaulted executing the test, then it's not a Nuitka issue, so we can ignore that. - Improve the way the Python to test with is found in the main test runner, prefer the running interpreter, then ``PATH`` and registry on Windows, this will find the interesting version more often. - Added support for "Landscape.io" to ignore the inline copies of code, they are not under our control. - The test runner for Valgrind got merged with the usage for constructs and uses common code now. - Construct generation is now common code, intended for sharing it with the Speedcenter web site generation. - Rebased Python 3.6 test suite to 3.6.1 as that is the Python generally used now. Organisational ============== - Added inline copy of ``appdirs`` package from PyPI. - Added credits for RedBaron and isort. - The ``--experimental`` flag is now creating a list of indications and more than one can be used that way. - The PyLint runner can also work with Python3 pylint. - The Nuitka Speedcenter got more fine tuning and produces more tags to more easily identify trends in results. This needs to become more visible though. - The MSI files are also built on AppVeyor, where their building will not depend on me booting Windows. Getting these artifacts as downloads will be the next step. Summary ======= This release improves many areas. The variable closure taking is now fully transparent due to different node types, the memory usage dropped again, a few obvious missing static optimizations were added, and many built-ins were completed. This release again improves the scalability of Nuitka, which again uses less memory than before, although not an as big jump as before. This does not extend or use special C code generation for ``bool`` or any type yet, which still needs design decisions to proceed and will come in a later release. *********************** Nuitka Release 0.5.26 *********************** This release comes after a long time and contains large amounts of changes in all areas. The driving goal was to prepare generating C specific code, which is still not the case, but this is very likely going to change soon. However this release improves all aspects. Bug Fixes ========= - Compatibility: Fix, for star imports didn't check the values from the ``__all__`` iterable, if they were string values which could cause problems at run time. .. code:: python # Module level __all__ = (1,) # ... # other module: from module import * - Fix, for star imports, also didn't check for values from ``__all__`` if they actually exist in the original values. - Corner cases of imports should work a lot more precise, as the level of compatibility for calls to ``__import__`` went from absurd to insane. - Windows: Fixed detection of uninstalled Python versions (not for all users and DLL is not in system directory). This of course only affected the accelerated mode, not standalone mode. - Windows: Scan directories for ``.pyd`` files for used DLLs as well. This should make the PyQt5 wheel work. - Python3.5: Fix, coroutines could have different code objects for the object and the frame using by it. - Fix, slices with built-in names crashed the compiler. .. code:: python something[id:len:range] - Fix, the C11 via C++ compatibility uses symlinks tp C++ filenames where possible instead of making a copy from the C source. However, even on Linux that may not be allowed, e.g. on a DOS file system. Added fallback to using full copy in that case. - Python3.5: Fix coroutines to close the "yield from" where an exception is thrown into them. - Python3: Fix, list contractions should have their own frame too. - Linux: Copy the "rpath" of compiling Python binary to the created binary. This will make compiled binaries using uninstalled Python versions transparently find the Python shared library. - Standalone: Add the "rpath" of the compiling Python binary to the search path when checking for DLL dependencies on Linux. This fixes standalone support for Travis and Anaconda on Linux. - Scons: When calling scons, also try to locate a Python2 binary to overcome a potential Python3 virtualenv in which Nuitka is running. - Standalone: Ignore more Windows only encodings on non-Windows. New Features ============ - Support for Python 3.6 with only few corner cases not supported yet. - Added options ``--python-arch`` to pick 32 or 64 bits Python target of the ``--python-version`` argument. - Added support for more kinds of virtualenv configurations. - Uninstalled Python versions such as Anaconda will work fine in accelerated mode, except on Windows. Optimization ============ - The node tree children are no longer stored in a separate dictionary, but in the instance dictionary as attributes, making the tree more lightweight and in principle faster to access. This also saved about 6% of the memory usage. - The memory usage of Nuitka for the Python part has fallen by roughly 40% due to the use of new style classes, and slots where that is possible (some classes use multiple inheritance, where they don't work), and generally by reducing useless members e.g. in source code references. This of course also will make things compiled faster (the C compilation of course is not affected by this.) - The code generation for frames was creating the dictionary for the raised exception by making a dictionary and then adding all variables, each tested to be set. This was a lot of code for each frame specific, and has been replaced by a generic "attach" mechanism which merely stores the values, and only takes a reference. When asked for frame locals, it only then builds the dictionary. So this is now only done, when that is absolutely necessary, which it normally never is. This of course makes the C code much less verbose, and actual handling of exceptions much more efficient. - For imports, we now detect for built-in modules, that their import cannot fail, and if name lookups can fail. This leads to less code generated for error handling of these. The following code now e.g. fully detects that no ``ImportError`` or ``AttributeError`` will occur. .. code:: python try: from __builtin__ import len except ImportError: from builtins import len - Added more type shapes for built-in type calls. These will improve type tracing. - Compiled frames now have a free list mechanism that should speed up frames that recurse and frames that exit with exceptions. In case of an exception, the frame ownership is immediately transferred to the exception making it easier to deal with. - The free list implementations have been merged into a new common one that can be used via macro expansion. It is now type agnostic and be slightly more efficient too. - Also optimize "true" division and "floor division", not only the default division of Python2. - Removed the need for statement context during code generation making it less memory intensive and faster. Cleanups ======== - Now always uses the ``__import__`` built-in node for all kinds of imports and directly optimizes and recursion into other modules based on that kind of node, instead of a static variant. This removes duplication and some incompatibility regarding defaults usage when doing the actual imports at run time. - Split the expression node bases and mixin classes to a dedicated module, moving methods that only belong to expressions outside of the node base, making for a cleaner class hierarchy. - Cleaned up the class structure of nodes, added base classes for typical compositions, e.g. expression with and without children, computation based on built-in, etc. while also checking proper ordering of base classes in the metaclass. - Moved directory and file operations to dedicated module, making also sure it is more generally used. This makes it easier to make more error resilient deletions of directories on e.g. Windows, where locks tend to live for short times beyond program ends, requiring second attempts. - Code generation for existing supported types, ``PyObject *``, ``PyObject **``, and ``struct Nuitka_CellObject *`` is now done via a C type class hierarchy instead of ``elif`` sequences. - Closure taking is now always done immediately correctly and references are take for closure variables still needed, making sure the tree is correct and needs no finalization. - When doing variable traces, initialize more traces immediately so it can be more reliable. - Code to setup a function for local variables and clean it up has been made common code instead of many similar copies. - The code was treating the ``f_executing`` frame member as if it were a counter with increases and decreases. Turn it into a mere boolean value and hide its usage behind helper functions. - The "maybe local variables" are no more. They were replaced by a new locals dict access node with a fallback to a module or closure variable should the dictionary not contain the name. This avoids many ugly checks to not do certain things for that kind of variable. - We now detect "exec" and "unqualified exec" as well as "star import" ahead of time as flags of the function to be created. We no longer need to mark functions as we go. - Handle "true", "floor" and normal division properly by applying future flags to decide which one to use. - We now use symbolic identifiers in all PyLint annotations. - The release scripts started to move into ``nuitka.tools.release`` so they get PyLint checks, autoformat and proper code re-use. - The use of ``INCREASE_REFCOUNT_X`` was removed, it got replaced with proper ``Py_XINCREF`` usages. - The use of ``INCREASE_REFCOUNT`` got reduced further, e.g. no generated code uses it anymore, and only a few compiled types do. The function was once required before "C-ish" lifted the need to do everything in one single function call. Tests ===== - More robust deletion of directories, temporary stages used by CPython test suites, and standalone directories during test execution. - Moved tests common code into ``nuitka.tools.testing`` namespace and use it from there. The code now is allowed to use ``nuitka.utils`` and therefore often better implementations. - Made standalone binaries robust against GTK theme access, checking the Python binary (some site.py files do that), Organisational ============== - Added repository for Ubuntu Zesty (17.04) for download. - Added support for testing with Travis to complement the internal Buildbot based infrastructure and have pull requests on Github automatically tested before merge. - The ``factory`` branch is now also on Github. - Removed MSI for Python3.4 32 bits. It seems impossible to co-install this one with the 64 bits variant. All other versions are provided for both bit sizes still. Summary ======= This release marks huge progress. The node tree is now absolutely clean, the variable closure taking is fully represented, and code generation is prepared to add another type, e.g. for ``bool`` for which work has already started. On a practical level, the scalability of the release will have increased very much, as this uses so much less memory, generates simpler C code, while at the same time getting faster for the exception cases. Coming releases will expand on the work of this release. Frame objects should be allowed to be nested inside a function for better re-formulations of classes and contractions of all kinds, as well as real inline of functions, even if they could raise. The memory savings could be even larger, if we stopped doing multiple inheritance for more node types. The ``__slots__`` were and the child API change could potentially make things not only more compact, but faster to use too. And also once special C code generation for ``bool`` is done, it will set the stage for more types to follow (``int``, ``float``, etc). Only this will finally start to give the C type speed we are looking for. Until then, this release marks a huge cleanup and progress to what we already had, as well as preparing the big jump in speed. *********************** Nuitka Release 0.5.25 *********************** This release contains a huge amount of bug fixes, lots of optimization gains, and many new features. It also presents many organisational improvements, and many cleanups. Bug Fixes ========= - Python3.5: Coroutine methods using ``super`` were crashing the compiler. Fixed in 0.5.24.2 already. - Python3.3: Generator return values were not properly transmitted in case of ``tuple`` or ``StopIteration`` values. - Python3.5: Better interoperability between compiled coroutines and uncompiled generator coroutines. - Python3.5: Added support to compile in Python debug mode under Windows too. - Generators with arguments were using two code objects, one with, and one without the ``CO_NOFREE`` flag, one for the generator object creating function, and one for the generator object. - Python3.5: The duplicate code objects for generators with arguments lead to interoperability issues with between such compiled generator coroutines and compiled coroutines. Fixed in 0.5.24.2 already. - Standalone: On some Linux variants, e.g. Debian Stretch and Gentoo, the linker needs more flags to really compile to a binary with ``RPATH``. - Compatibility: For set literal values, insertion order is wrong on some versions of Python, we now detect the bug and emulate it if necessary, previous Nuitka was always correct, but incompatible. .. code:: python {1, 1.0}.pop() # the only element of the set should be 1 - Windows: Make the batch files detect where they live at run time, instead of during ``setup.py``, making it possible to use them for all cases. - Standalone: Added package paths to DLL scan for ``depends.exe``, as with wheels there now sometimes live important DLLs too. - Fix, the clang mode was regressed and didn't work anymore, breaking the macOS support entirely. - Compatibility: For imports, we were passing for ``locals`` argument a real dictionary with actual values. That is not what CPython does, so stopped doing it. - Fix, for raised exceptions not passing the validity tests, they could be used after free, causing crashes. - Fix, the environment ``CC`` wasn't working unless also specifying ``CXX``. - Windows: The value of ``__file__`` in module mode was wrong, and didn't point to the compiled module. - Windows: Better support for ``--python-debug`` for installations that have both variants, it is now possible to switch to the right variant. New Features ============ - Added parsing for shebang to Nuitka. When compiling an executable, now Nuitka will check of the ``#!`` portion indicates a different Python version and ask the user to clarify with ``--python-version`` in case of a mismatch. - Added support for Python flag ``--python-flag=-O``, which allows to disable assertions and remove doc strings. Optimization ============ - Faster method calls, combining attribute lookup and method call into one, where order of evaluation with arguments doesn't matter. This gives really huge relative speedups for method calls with no arguments. - Faster attribute lookup in general for ``object`` descendants, which is all new style classes, and all built-in types. - Added dedicated ``xrange`` built-in implementation for Python2 and ``range`` for Python3. This makes those faster while also solving ordering problems when creating constants of these types. - Faster ``sum`` again, using quick iteration interface and specialized quick iteration code for typical standard type containers, ``tuple`` and ``list``. - Compiled generators were making sure ``StopIteration`` was set after their iteration, although most users were only going to clear it. Now only the ``send`` method, which really needs that does it. This speed up the closing of generators quite a bit. - Compiled generators were preparing a ``throw`` into non-started compilers, to be checked for immediately after their start. This is now handled in a generic way for all generators, saving code and execution time in the normal case. - Compiled generators were applying checks only useful for manual ``send`` calls even during iteration, slowing them down. - Compiled generators could duplicate code objects due to handling a flag for closure variables differently. - For compiled frames, the ``f_trace`` is not writable, but was taking and releasing references to what must be ``None``, which is not useful. - Not passing ``locals`` to import calls make it less code and faster too. Organisational ============== - This release also prepares Python 3.6 support, it includes full language support on the level of CPython 3.6.0 with the sole exception of the new generator coroutines. - The improved mode is now the default, and full compatibility is now the option, used by test suites. For syntax errors, improved mode is always used, and for test suites, now only the error message is compared, but not call stack or caret positioning anymore. - Removed long deprecated option "--no-optimization". Code generation too frequently depends on not seeing unoptimized code. This has been hidden and broken long enough to finally remove it. - Added support for Python3.5 numbers to Speedcenter. There are now also tags for speedcenter, indicating how well "develop" branch fares in comparison to master. - With a new tool, source code and Developer Manual contents can be kept in sync, so that descriptions can be quoted there. Eventually a full Sphinx documentation might become available, but for now this makes it workable. - Added repository for Ubuntu Yakkety (16.10) for download. - Added repository for Fedora 25 for download. Cleanups ======== - Moved the tools to compare CPython output, to sort import statements (isort) to autoformat the source code (Redbaron usage), and to check with PyLint to a common new ``nuitka.tools`` package, runnable with ``__main__`` modules and dedicated runners in ``bin`` directory. - The tools now share code to find source files, or have it for the first time, and other things, e.g. finding needed binaries on Windows installations. - No longer patch traceback objects dealloc function. Should not be needed anymore, and most probably was only bug hiding. - Moved handling of ast nodes related to import handling to the proper reformulation module. - Moved statement generation code to helpers module, making it accessible without cyclic dependencies that require local imports. - Removed deprecated method for getting constant code objects in favor of the new way of doing it. Both methods were still used, making it harder to analyse. - Removed useless temporary variable initializations from complex call helper internal functions. They worked around code generation issues that have long been solved. - The ABI flags are no longer passed to Scons together with the version. Tests ===== - Windows: Added support to detect and to switch debug Python where available to also be able to execute reference counting tests. - Added the CPython 3.3 test suite, after cleaning up the worst bits of it, and added the brandnew 3.6 test suite with a minimal set of changes. - Use the original 3.4 test suite instead of the one that comes from Debian as it has patched quite a few issues that never made it upstream, and might cause crashes. - More construct tests, making a difference between old style classes, which have instances and new style classes, with their objects. - It is now possible to run a test program with Python3 and Valgrind. Summary ======= The quick iteration is a precursor to generally faster iteration over unknown object iterables. Expanding this to general code generation, and not just the ``sum`` built-in, might yield significant gains for normal code in the future, once we do code generation based on type inference. The faster method calls complete work that was already prepared in this domain and also will be expanded to more types than compiled functions. More work will be needed to round this up. Adding support for 3.6.0 in the early stages of its release, made sure we pretty much have support for it ready right after release. This is always a huge amount of work, and it's good to catch up. This release is again a significant improvement in performance, and is very important to clean up open ends. Now the focus of coming releases will now be on both structural optimization, e.g. taking advantage of the iterator tracing, and specialized code generation, e.g. for those iterations really necessary to use quick iteration code. *********************** Nuitka Release 0.5.24 *********************** This release is again focusing on optimization, this time very heavily on the generator performance, which was found to be much slower than CPython for some cases. Also there is the usual compatibility work and improvements for Pure C support. Bug Fixes ========= - Windows: The 3.5.2 coroutine new protocol implementation was using the wrapper from CPython, but it's not part of the ABI on Windows. Have our own instead. Fixed in 0.5.23.1 already. - Windows: Fixed second compilation with MSVC failing. The files renamed to be C++ files already existed, crashing the compilation. Fixed in 0.5.23.1 already. - Mac OS: Fixed creating extension modules with ``.so`` suffix. This is now properly determined by looking at the importer details, leading to correct suffix on all platforms. Fixed in 0.5.23.1 already. - Debian: Don't depend on a C++ compiler primarily anymore, the C compiler from GNU or clang will do too. Fixed in 0.5.23.1 already. - Pure C: Adapted scons compiler detecting to properly consider C11 compilers from the environment, and more gracefully report things. Optimization ============ - Python2: Generators were saving and restoring exceptions, updating the variables ``sys.exc_type`` for every context switch, making it really slow, as these are 3 dictionary updates, normally not needed. Now it's only doing it if it means a change. - Sped up creating generators, coroutines and coroutines by attaching the closure variable storage directly to the object, using one variable size allocation, instead of two, once of which was a standard ``malloc``. This makes creating them easier and avoids maintaining the closure pointer entirely. - Using dedicated compiled cell implementation similar to ``PyCellObject`` but fully under our control. This allowed for smaller code generated, while still giving a slight performance improvement. - Added free list implementation to cache generator, coroutines, and function objects, avoiding the need to create and delete this kind of objects in a loop. - Added support for the built-in ``sum``, making slight optimizations to be much faster when iterating over lists and tuples, as well as fast ``long`` sum for Python2, and much faster ``bool`` sums too. This is using a prototype version of a "qiter" concept. - Provide type shape for ``xrange`` calls that are not constant too, allowing for better optimization related to those. Tests ===== - Added workarounds for locks being held by Virus Scanners on Windows to our test runner. - Enhanced constructs that test generator expressions to more clearly show the actual construct cost. - Added construct tests for the ``sum`` built-in on various types of ``int`` containers, making sure we can do all of those really fast. Summary ======= This release improves very heavily on generators in Nuitka. The memory allocator is used more cleverly, and free lists all around save a lot of interactions with it. More work lies ahead in this field, as these are not yet as fast as they should be. However, at least Nuitka should be faster than CPython for these kind of usages now. Also, proper pure C in the Scons is relatively important to cover more of the rarer use cases, where the C compiler is too old. The most important part is actually how ``sum`` optimization is staging a new kind of approach for code generation. This could become the standard code for iterators in loops eventually, making ``for`` loops even faster. This will be for future releases to expand. *********************** Nuitka Release 0.5.23 *********************** This release is focusing on optimization, the most significant part for the users being enhanced scalability due to memory usage, but also break through structural improvements for static analysis of iterators and the debut of type shapes and value shapes, giving way to "shape tracing". Bug Fixes ========= - Fix support Python 3.5.2 coroutine changes. The checks got added for improved mode for older 3.5.x, the new protocol is only supported when run with that version or higher. - Fix, was falsely optimizing away unused iterations for non-iterable compile time constants. .. code:: python iter(1) # needs to raise. - Python3: Fix, ``eval`` must not attempt to ``strip`` memoryviews. The was preventing it from working with that type. - Fix, calling ``type`` without any arguments was crashing the compiler. Also the exception raised for anything but 1 or 3 arguments was claiming that only 3 arguments were allowed, which is not the compatible thing. - Python3.5: Fix, follow enhanced error checking for complex call handling of star arguments. - Compatibility: The ``from x import x, y`` re-formulation was doing two ``__import__`` calls instead of re-using the module value. Optimization ============ - Uses only about 66% of the memory compared to last release, which is very important step for scalability independent of re-loading. This was achieved by making sure to break loop traces and their reference cycle when they become unused. - Properly detect the ``len`` of multiplications at compile time from newly introduces value shapes, so that this is e.g. statically optimized. .. code:: python print(len("*" * 10000000000)) - Due to newly introduced type shapes, ``len`` and ``iter`` now properly detect more often if values will raise or not, and warn about detected raises. .. code:: python iter(len(something)) # Will always raise - Due to newly introduced "iterator tracing", we can now properly detect if the length of an unpacking matches its source or not. This allows to remove the check of the generic re-formulations of unpackings at compile time. .. code:: python a, b = b, a # Will never raise due to unpacking a, b = b, a, c # Will always raise, 3 items cannot unpack to 2 - Added support for optimization of the ``xrange`` built-in for Python2. - Python2: Added support for ``xrange`` iterable constant values, pre-building those constants ahead of time. - Python3: Added support and ``range`` iterable constant values, pre-building those constants ahead of time. This brings optimization support for Python3 ranges to what was available for Python2 already. - Avoid having a special node variange for ``range`` with no arguments, but create the exception raising node directly. - Specialized constant value nodes are using less generic implementations to query e.g. their length or iteration capabilities, which should speed up many checks on them. - Added support for the ``format`` built-in. - Python3: Added support for the ``ascii`` built-in. Organisational ============== - The movement to pure C got the final big push. All C++ only idoms of C++ were removed, and everything works with C11 compilers. A C++03 compiler can be used as a fallback, in case of MSVC or too old gcc for instance. - Using pure C, MinGW64 6x is now working properly. The latest version had problems with ``hypot`` related changes in the C++ standard library. Using C11 solves that. - This release also prepares Python 3.6 support, it includes full language support on the level of CPython 3.6.0b1. - The CPython 3.6 test suite was run with Python 3.5 to ensure bug level compatibility, and had a few findings of incompatibilities. Cleanups ======== - The last holdouts of classes in Nuitka were removed, and many idioms of C++ were stopped using. - Moved range related helper functions to a dedicated include file. - Using ``str is not bytes`` to detect Python3 ``str`` handling or actual ``bytes`` type existence. - Trace collections were using a mix-in that was merged with the base class that every user of it was having. Tests ===== - Added more static optimization tests, a lot more has become feasible to decide at run time, and is now done. These are to detect regressions in that domain. - The CPython 3.6 test suite is now also run with CPython 3.5 which found some incompatibilities. Summary ======= This release marks a huge step forward. We are having the structure for type inference now. This will expand in coming releases to cover more cases, and there are many low hanging fruits for optimization. Specialized codes for variable versions of certain known shapes seems feasible now. Then there is also the move towards pure C. This will make the backend compilation lighter, but due to using C11, we will not suffer any loss of convenience compared to "C-ish". The plan is to use continue to use C++ for compilation for compilers not capable of supporting C11. The amount of static analysis done in Nuitka is now going to quickly expand, with more and more constructs predicted to raise errors or simplified. This will be an ongoing activity, as many types of expressions need to be enhanced, and only one missing will not let it optimize as well. Also, it seems about time to add dedicated code for specific types to be as fast as C code. This opens up vast possibilities for acceleration and will lead us to zero overhead C bindings eventually. But initially the drive is towards enhanced ``import`` analysis, to become able to know the precide module expected to be imported, and derive type information from this. The coming work will attack to start whole program optimization, as well as enhanced local value shape analysis, as well specialized type code generation, which will make Nuitka improve speed. *********************** Nuitka Release 0.5.22 *********************** This release is mostly an intermediate release on the way to the large goal of having per module compilation that is cacheable and requires far less memory for large programs. This is currently in progress, but required many changes that are in this release, more will be needed. It also contains a bunch of bug fixes and enhancements that are worth to be released, and the next changes are going to be more invasive. Bug Fixes ========= - Compatibility: Classes with decorated ``__new__`` functions could miss out on the ``staticmethod`` decorator that is implicit. It's now applied always, unless of course it's already done manually. This corrects an issue found with Pandas. Fixed in 0.5.22.1 already. - Standalone: For at least Python 3.4 or higher, it could happen that the locale needed was not importable. Fixed in 0.5.22.1 already. - Compatibility: Do not falsely assume that ``not`` expressions cannot raise on boolean expressions, since those arguments might raise during creation. This could lead to wrong optimization. Fixed in 0.5.22.2 already. - Standalone: Do not include system specific C libraries in the distribution created. This would lead to problems for some configurations on Linux in cases the glibc is no longer compatible with newer or older kernels. Fixed in 0.5.22.2 already. - The ``--recurse-directory`` option didn't check with decision mechanisms for module inclusion, making it impossible to avoid some things. Optimization ============ - Introduced specialized constant classes for empty dictionaries and other special constants, e.g. "True" and "False", so that they can have more hard coded properties and save memory by sharing constant values. - The "technical" sharing of a variable is only consider for variables that had some sharing going in the first place, speeing things up quite a bit for that still critical check. - Memory savings coming from enhanced trace storage are already visible at about 1%. That is not as much as the reloading will mean, but still helpful to use less overall. Cleanups ======== - The global variable registry was removed. It was in the way of unloading and reloading modules easily. Instead variables are now attached to their owner and referenced by other users. When they are released, these variables are released. - Global variable traces were removed. Instead each variable has a list of the traces attached to it. For non-shared variables, this allows to sooner tell attributes of those variables, allowing for sooner optimization of them. - No longer trace all initial users of a variable, just merely if there were such and if it constitutes sharing syntactically too. Not only does this save memory, it avoids useless references of the variable to functions that stop using it due to optimization. - Create constant nodes via a factory function to avoid non-special instances where variants exist that would be faster to use. - Moved the C string functions to a proper ``nuitka.utils.CStrings`` package as we use it for better code names of functions and modules. - Made ``functions`` and explicit child node of modules, which makes their use more generic, esp. for re-loading modules. - Have a dedicated function for building frame nodes, making it easier to see where they are created. Summary ======= This release is the result of a couple of months work, and somewhat means that proper re-loading of cached results is becoming in sight. The reloading of modules still fails for some things, and more changes will be needed, but with that out of the way, Nuitka's footprint is about to drop and making it then absolutely scalable. Something considered very important before starting to trace more information about values. This next thing big ought to be one thing that structurally holds Nuitka back from generating C level performance code with say integer operations. *********************** Nuitka Release 0.5.21 *********************** This release focused on scalability work. Making Nuitka more usable in the common case, and covering more standalone use cases. Bug Fixes ========= - Windows: Support for newer MinGW64 was broken by a workaround for older MinGW64 versions. - Compatibility: Added support for the (unofficial) C-Python API ``Py_GetArgcArgv`` that was causing ``prctl`` module to fail loading on ARM platforms. - Compatibility: The proper error message template for complex call arguments is now detected as compile time. There are changes coming, that are already in some pre-releases of CPython. - Standalone: Wasn't properly ignoring ``Tools`` and other directories in the standard library. New Features ============ - Windows: Detect the MinGW compiler arch and compare it to the Python arch. In case of a mismatch, the compiler is not used. Otherwise compilation or linking gives hard to understand errors. This also rules out MinGW32 as a compiler that can be used, as its arch doesn't match MinGW64 32 bits variant. - Compile modules in two passes with the option to specify which modules will be considered for a second pass at all (compiled without program optimization) or even become bytecode. - The developer mode installation of Nuitka in ``develop`` mode with the command ``pip install -e nuitka_git_checkout_dir`` is now supported too. Optimization ============ - Popular modules known to not be performance relevant are no longer C compiled, e.g. ``numpy.distutils`` and many others frequently imported (from some other module), but mostly not used and definitely not performance relevant. Cleanups ======== - The progress tracing and the memory tracing and now more clearly separate and therefore more readable. - Moved RPM related files to new ``rpm`` directory. - Moved documentation related files to ``doc`` directory. - Converted import sorting helper script to Python and made it run fast. Organisational ============== - The Buildbot infrastructure for Nuitka was updated to Buildbot 0.8.12 and is now maintained up to date with Ansible. - Upgraded the Nuitka bug tracker to Roundup 1.5.1 to which I had previously contributed security fixes already active. - Added SSL certificates from Let's Encrypt for the web server. Summary ======= This release advances the scalability of Nuitka somewhat. The two pass approach does not yet carry all possible fruits. Caching of single pass compiled modules should follow for it to become consistently fast. More work will be needed to achieve fast and scalable compilation, and that is going to remain the focus for some time. *********************** Nuitka Release 0.5.20 *********************** This release is mostly about catching up with issues. Most address standalone problems with special modules, but there are also some general compatibility corrections, as well as important fixes for Python3.5 and coroutines and to improve compatibility with special Python variants like Anaconda under the Windows system. Bug Fixes ========= - Standalone Python3.5: The ``_decimal`` module at least is using a ``__name__`` that doesn't match the name at load time, causing programs that use it to crash. - Compatibility: For Python3.3 the ``__loader__`` attribute is now set in all cases, and it needs to have a ``__module__`` attribute. This makes inspection as done by e.g. ``flask`` working. - Standalone: Added missing hidden dependencies for ``Tkinter`` module, adding support for this to work properly. - Windows: Detecting the Python DLL and EXE used at compile time and preserving this information use during backend compilation. This should make sure we use the proper ones, and avoids hacks for specific Python variants, enhancing the support for Anaconda, WinPython, and CPython installations. - Windows: The ``--python-debug`` flag now properly detects if the run time is supporting things and error exits if it's not available. For a CPython3.5 installation, it will switch between debug and non-debug Python binaries and DLLs. - Standalone: Added plug-in for the ``Pwm`` package to properly combine it into a single file, suitable for distribution. - Standalone: Packages from standard library, e.g. ``xml`` now have proper ``__path__`` as a list and not as a string value, which breaks code of e.g. PyXML. - Standalone: Added missing dependency of ``twisted.protocols.tls``. - Python3.5: When finalizing coroutines that were not finished, a corruption of its reference count could happen under some circumstances. - Standalone: Added missing DLL dependency of the ``uuid`` module at run time, which uses ctypes to load it. New Features ============ - Added support for Anaconda Python on this Linux. Both accelerated and standalone mode work now. - Added support for standalone mode on FreeBSD. - The plug-in framework was expanded with new features to allow addressing some specific issues. Cleanups ======== - Moved memory related stuff to dedicated utils package ``nuitka.utils.MemoryUsage`` as part of an effort to have more topical modules. - Plugins how have a dedicated module through which the core accesses the API, which was partially cleaned up. - No more "early" and "late" import detections for standalone mode. We now scan everything at the start. Summary ======= This release focused on expanding plugins. These were then used to enhance the success of standalone compatibility. Eventually this should lead to a finished and documented plug-in API, which will open up the Nuitka core to easier hacks and more user contribution for these topics. *********************** Nuitka Release 0.5.19 *********************** This release brings optimization improvements for dictionary using code. This is now lowering subscripts to dictionary accesses where possible and adds new code generation for known dictionary values. Besides this there is the usual range of bug fixes. Bug Fixes ========= - Fix, attribute assignments or deletions where the assigned value or the attribute source was statically raising crashed the compiler. - Fix, the order of evaluation during optimization was considered in the wrong order for attribute assignments source and value. - Windows: Fix, when ``g++`` is the path, it was not used automatically, but now it is. - Windows: Detect the 32 bits variant of MinGW64 too. - Python3.4: The finalize of compiled generators could corrupt reference counts for shared generator objects. Fixed in 0.5.18.1 already. - Python3.5: The finalize of compiled coroutines could corrupt reference counts for shared generator objects. Optimization ============ - When a variable is known to have dictionary shape (assigned from a constant value, result of ``dict`` built-in, or a general dictionary creation), or the branch merge thereof, we lower subscripts from expecting mapping nodes to dictionary specific nodes. These generate more efficient code, and some are then known to not raise an exception. .. code:: python def someFunction(a, b): value = {a: b} value["c"] = 1 return value The above function is not yet fully optimized (dictionary key/value tracing is not yet finished), however it at least knows that no exception can raise from assigning ``value["c"]`` anymore and creates more efficient code for the typical ``result = {}`` functions. - The use of "logical" sharing during optimization has been replaced with checks for actual sharing. So closure variables that were written to in dead code no longer inhibit optimization of the then no more shared local variable. - Global variable traces are now faster to decide definite writes without need to check traces for this each time. Cleanups ======== - No more using "logical sharing" allowed to remove that function entirely. - Using "technical sharing" less often for decisions during optimization and instead rely more often on proper variable registry. - Connected variables with their global variable trace statically avoid the need to check in variable registry for it. - Removed old and mostly unused "assume unclear locals" indications, we use global variable traces for this now. Summary ======= This release aimed at dictionary tracing. As a first step, the value assign is now traced to have a dictionary shape, and this this then used to lower the operations which used to be normal subscript operations to mapping, but now can be more specific. Making use of the dictionary values knowledge, tracing keys and values is not yet inside the scope, but expected to follow. We got the first signs of type inference here, but to really take advantage, more specific shape tracing will be needed. *********************** Nuitka Release 0.5.18 *********************** This release mainly has a scalability focus. While there are few compatibility improvements, the larger goal has been to make Nuitka compilation and the final C compilation faster. Bug Fixes ========= - Compatibility: The nested arguments functions can now be called using their keyword arguments. .. code:: python def someFunction(a, (b, c)): return a, b, c someFunction(a=1, **{".1": (2, 3)}) - Compatibility: Generators with Python3.4 or higher now also have a ``__del__`` attribute, and therefore properly participate in finalization. This should improve their interactions with garbage collection reference cycles, although no issues had been observed so far. - Windows: Was outputting command line arguments debug information at program start. Fixed in 0.5.17.1 already. Optimization ============ - Code generated for parameter parsing is now a *lot* less verbose. Python level loops and conditionals to generate code for each variable has been replaced with C level generic code. This will speed up the backend compilation by a lot. - Function calls with constant arguments were speed up specifically, as their call is now fully prepared, and yet using less code. Variable arguments are also faster, and all defaulted arguments are also much faster. Method calls are not affected by these improvements though. - Nested argument functions now have a quick call entry point as well, making them faster to call too. - The ``slice`` built-in, and internal creation of slices (e.g. in re-formulations of Python3 slices as subscripts) cannot raise. - Standalone: Avoid inclusion of bytecode of ``unittest.test``, ``sqlite3.test``, ``distutils.test``, and ``ensurepip``. These are not needed, but simply bloat the amount of bytecode used on e.g. macOS. - Speed up compilation with Nuitka itself by avoid to copying and constructing variable lists as much as possible using an always accurate variable registry. Cleanups ======== - Nested argument functions of Python2 are now re-formulated into a wrapping function that directly calls the actual function body with the unpacking of nested arguments done in nodes explicitly. This allows for better optimization and checks of these steps and potential in-lining of these functions too. - Unified slice object creation and built-in ``slice`` nodes, these were two distinct nodes before. - The code generation for all statement kinds is now done via dispatching from a dictionary instead of long ``elif`` chains. - Named nodes more often consistently, e.g. all loop related nodes start with ``Loop`` now, making them easier to group. - Parameter specifications got simplified to work without variables where it is possible. Organisational ============== - Nuitka is now available on the social code platforms gitlab as well. Summary ======= Long standing weaknesses have been addressed in this release, also quite a few structural cleanups have been performed, e.g. strengthening the role of the variable registry to always be accurate, is groundlaying to further improvement of optimization. However, this release cycle was mostly dedicated to performance of the actual compilation, and more accurate information was needed to e.g. not search for information that should be instant. Upcoming releases will focus on usability issues and further optimization, it was nice however to see speedups of created code even from these scalability improvements. *********************** Nuitka Release 0.5.17 *********************** This release is a major feature release, as it adds full support for Python3.5 and its coroutines. In addition, in order to properly support coroutines, the generator implementation got enhanced. On top of that, there is the usual range of corrections. Bug Fixes ========= - Windows: Command line arguments that are unicode strings were not properly working. - Compatibility: Fix, only the code object attached to exceptions contained all variable names, but not the one of the function object. - Python3: Support for virtualenv on Windows was using non-portable code and therefore failing. - The tree displayed with ``--display-tree`` duplicated all functions and did not resolve source lines for functions. It also displayed unused functions, which is not helpful. - Generators with parameters leaked C level memory for each instance of them leading to memory bloat for long running programs that use a lot of generators. Fixed in 0.5.16.1 already. - Don't drop positional arguments when called with ``--run``, also make it an error if they are present without that option. New Features ============ - Added full support for Python3.5, coroutines work now too. Optimization ============ - Optimized frame access of generators to not use both a local frame variable and the frame object stored in the generator object itself. This gave about 1% speed up to setting them up. - Avoid having multiple code objects for functions that can raise and have local variables. Previously one code object would be used to create the function (with parameter variable names only) and when raising an exception, another one would be used (with all local variable names). Creating them both at start-up was wasteful and also needed two tuples to be created, thus more constants setup code. - The entry point for generators is now shared code instead of being generated for each one over and over. This should make things more cache local and also results in less generated C code. - When creating frame codes, avoid working with strings, but use proper emission for less memory churn during code generation. Organisational ============== - Updated the key for the Debian/Ubuntu repositories to remain valid for 2 more years. - Added support for Fedora 23. - MinGW32 is no more supported, use MinGW64 in the 32 bits variant, which has less issues. Cleanups ======== - Detecting function type ahead of times, allows to handle generators different from normal functions immediately. - Massive removal of code duplication between normal functions and generator functions. The later are now normal functions creating generator objects, which makes them much more lightweight. - The ``return`` statement in generators is now immediately set to the proper node as opposed to doing this in variable closure phase only. We can now use the ahead knowledge of the function type. - The ``nonlocal`` statement is now immediately checked for syntax errors as opposed to doing that only in variable closure phase. - The name of contraction making functions is no longer skewed to empty, but the real thing instead. The code name is solved differently now. - The ``local_locals`` mode for function node was removed, it was always true ever since Python2 list contractions stop using pseudo functions. - The outline nodes allowed to provide a body when creating them, although creating that body required using the outline node already to create temporary variables. Removed that argument. - Removed PyLint false positive annotations no more needed for PyLint 1.5 and solved some TODOs. - Code objects are now mostly created from specs (not yet complete) which are attached and shared between statement frames and function creations nodes, in order to have less guess work to do. Tests ===== - Added the CPython3.5 test suite. - Updated generated doctests to fix typos and use common code in all CPython test suites. Summary ======= This release continues to address technical debt. Adding support for Python3.5 was the major driving force, while at the same time removing obstacles to the changes that were needed for coroutine support. With Python3.5 sorted out, it will be time to focus on general optimization again, but there is more technical debt related to classes, so the cleanup has to continue. *********************** Nuitka Release 0.5.16 *********************** This is a maintenance release, largely intended to put out improved support for new platforms and minor corrections. It should improve the speed for standalone mode, and compilation in general for some use cases, but this is mostly to clean up open ends. Bug Fixes ========= - Fix, the ``len`` built-in could give false values for dictionary and set creations with the same element. .. code:: python # This was falsely optimized to 2 even if "a is b and a == b" was true. len({a, b}) - Python: Fix, the ``gi_running`` attribute of generators is no longer an ``int``, but ``bool`` instead. - Python3: Fix, the ``int`` built-in with two arguments, value and base, raised ``UnicodeDecodeError`` instead of ``ValueError`` for illegal bytes given as value. - Python3: Using ``tokenize.open`` to read source code, instead of reading manually and decoding from ``tokenize.detect_encoding``, this handles corner cases more compatible. - Fix, the PyLint warnings plug-in could crash in some cases, make sure it's more robust. - Windows: Fix, the combination of Anaconda Python, MinGW 64 bits and mere acceleration was not working. - Standalone: Preserve not only namespace packages created by ``.pth`` files, but also make the imports done by them. This makes it more compatible with uses of it in Fedora 22. - Standalone: The extension modules could be duplicated, turned this into an error and cache finding them during compile time and during early import resolution to avoid duplication. - Standalone: Handle "not found" from ``ldd`` output, on some systems not all the libraries wanted are accessible for every library. - Python3.5: Fixed support for namespace packages, these were not yet working for that version yet. - Python3.5: Fixes lack of support for unpacking in normal ``tuple``, ``list``, and ``set`` creations. .. code:: python [*a] # this has become legal in 3.5 and now works too. Now also gives compatible ``SyntaxError`` for earlier versions. Python2 was good already. - Python3.5: Fix, need to reduce compiled functions to ``__qualname__`` value, rather than just ``__name__`` or else pickling methods doesn't work. - Python3.5: Fix, added ``gi_yieldfrom`` attribute to generator objects. - Windows: Fixed harmless warnings for Visual Studio 2015 in ``--debug`` mode. Optimization ============ - Re-formulate ``exec`` and ``eval`` to default to ``globals()`` as the default for the locals dictionary in modules. - The ``try`` node was making a description of nodes moved to the outside when shrinking its scope, which was using a lot of time, just to not be output, now these can be postponed. - Refactored how freezing of bytecode works. Uncompiled modules are now explicit nodes too, and in the registry. We only have one or the other of it, avoiding to compile both. Tests ===== - When ``strace`` or ``dtruss`` are not found, given proper error message, so people know what to do. - The doc tests extracted and then generated for CPython3 test suites were not printing the expressions of the doc test, leading to largely decreased test coverage here. - The CPython 3.4 test suite is now also using common runner code, and avoids ignoring all Nuitka warnings, instead more white listing was added. - Started to run CPython 3.5 test suite almost completely, but coroutines are blocking some parts of that, so these tests that use this feature are currently skipped. - Removed more CPython tests that access the network and are generally useless to testing Nuitka. - When comparing outputs, normalize typical temporary file names used on posix systems. - Coverage tests have made some progress, and some changes were made due to its results. - Added test to cover too complex code module of ``idna`` module. - Added Python3.5 only test for unpacking variants. Cleanups ======== - Prepare plug-in interface to allow suppression of import warnings to access the node doing it, making the import node is accessible. - Have dedicated class function body object, which is a specialization of the function body node base class. This allowed removing class specific code from that class. - The use of "win_target" as a scons parameter was useless. Make more consistent use of it as a flag indicator in the scons file. - Compiled types were mixing uses of ``compiled_`` prefixes, something with a space, sometimes with an underscore. Organisational ============== - Improved support for Python3.5 missing compatibility with new language features. - Updated the Developer Manual with changes that SSA is now a fact. - Added Python3.5 Windows MSI downloads. - Added repository for Ubuntu Wily (15.10) for download. Removed Ubuntu Utopic package download, no longer supported by Ubuntu. - Added repository with RPM packages for Fedora 22. Summary ======= So this release is mostly to lower the technical debt incurred that holds it back from supporting making more interesting changes. Upcoming releases may have continue that trend for some time. This release is mostly about catching up with Python3.5, to make sure we did not miss anything important. The new function body variants will make it easier to implement coroutines, and help with optimization and compatibility problems that remain for Python3 classes. Ultimately it will be nice to require a lot less checks for when function in-line is going to be acceptable. Also code generation will need a continued push to use the new structure in preparation for making type specific code generation a reality. *********************** Nuitka Release 0.5.15 *********************** This release enables SSA based optimization, the huge leap, not so much in terms of actual performance increase, but for now making the things possible that will allow it. This has been in the making literally for years. Over and over, there was just "one more thing" needed. But now it's there. The release includes much stuff, and there is a perspective on the open tasks in the summary, but first out to the many details. Bug Fixes ========= - Standalone: Added implicit import for ``reportlab`` package configuration dynamic import. Fixed in 0.5.14.1 already. - Standalone: Fix, compilation of the ``ctypes`` module could happen for some import patterns, and then prevented the distribution to contain all necessary libraries. Now it is made sure to not include compiled and frozen form both. Fixed in 0.5.14.1 already. - Fix, compilation for conditional statements where the boolean check on the condition cannot raise, could fail compilation. Fixed in 0.5.14.2 already. - Fix, the ``__import__`` built-in was making static optimization assuming compile time constants to be strings, which in the error case they are not, which was crashing the compiler. .. code:: python __import__(("some.module",)) # tuples don't work This error became only apparent, because now in some cases, Nuitka forward propagates values. - Windows: Fix, when installing Python2 only for the user, the detection of it via registry failed as it was only searching system key. This was `a github pull request `__. Fixed in 0.5.14.3 already. - Some modules have extremely complex expressions requiring too deep recursion to work on all platforms. These modules are now included entirely as bytecode fallback. - The standard library may contain broken code due to installation mistakes. We have to ignore their ``SyntaxError``. - Fix, pickling compiled methods was failing with the wrong kind of error, because they should not implement ``__reduce__``, but only ``__deepcopy__``. - Fix, when running under ``wine``, the check for scons binary was fooled by existence of ``/usr/bin/scons``. New Features ============ - Added experimental support for Python3.5, coroutines don't work yet, but it works perfectly as a 3.4 replacement. - Added experimental Nuitka plug-in framework, and use it for the packaging of Qt plugins in standalone mode. The API is not yet stable nor polished. - New option ``--debugger`` that makes ``--run`` execute directly in ``gdb`` and gives a stack trace on crash. - New option ``--profile`` executes compiled binary and outputs measured performance with ``vmprof``. This is work in progress and not functional yet. - Started work on ``--graph`` to render the SSA state into diagrams. This is work in progress and not functional yet. - Plug-in framework added. Not yet ready for users. Working ``PyQt4`` and ``PyQt5`` plug-in support. Experimental Windows ``multiprocessing`` support. Experimental PyLint warnings disable support. More to come. - Added support for Anaconda accelerated mode on macOS by modifying the rpath to the Python DLL. - Added experimental support for ``multiprocessing`` on Windows, which needs monkey patching of the module to support compiled methods. Optimization ============ - The SSA analysis is now enabled by default, eliminating variables that are not shared, and can be forward propagated. This is currently limited mostly to compile time constants, but things won't remain that way. - Code generation for many constructs now takes into account if a specific operation can raise or not. If e.g. an attribute look-up is known to not raise, then that is now decided by the node the looked is done to, and then more often can determine this, or even directly the value. - Calls to C-API that we know cannot raise, no longer check, but merely assert the result. - For attribute look-up and other operations that might be known to not raise, we now only assert that it succeeds. - Built-in loop-ups cannot fail, merely assert that. - Creation of built-in exceptions never raises, merely assert that too. - More Python operation slots now have their own computations and some of these gained overloads for more compile time constant optimization. - When taking an iterator cannot raise, this is now detected more often. - The ``try``/``finally`` construct is now represented by duplicating the final block into all kinds of handlers (``break``, ``continue``, ``return``, or ``except``) and optimized separately. This allows for SSA to trace values more correctly. - The ``hash`` built-in now has dedicated node and code generation too. This is mostly intended to represent the side effects of dictionary look-up, but gives more compact and faster code too. - Type ``type`` built-in cannot raise and has no side effect. - Speed improvement for in-place float operations for ``+=`` and ``*=``, as these will be common cases. Tests ===== - Made the construct based testing executable with Python3. - Removed warnings using the new PyLint warnings plug-in for the reflected test. Nuitka now uses the PyLint annotations to not warn. Also do not go into PyQt for reflected test, not needed. Many Python3 improvements for cases where there are differences to report. - The optimization tests no longer use 2to3 anymore, made the tests portable to all versions. - Checked more in-place operations for speed. Organisational ============== - Many improvements to the coverage taking. We can hope to see public data from this, some improvements were triggered from this already, but full runs of the test suite with coverage data collection are yet to be done. Summary ======= The release includes many important new directions. Coverage analysis will be important to remain certain of test coverage of Nuitka itself. This is mostly done, but needs more work to complete. Then the graphing surely will help us to debug and understand code examples. So instead of tracing, and reading stuff, we should visualize things, to more clearly see, how things evolve under optimization iteration, and where exactly one thing goes wrong. This will be improved as it proves necessary to do just that. So far, this has been rare. Expect this to become end user capable with time. If only to allow you to understand why Nuitka won't optimize code of yours, and what change of Nuitka it will need to improve. The comparative performance benchmarking is clearly the most important thing to have for users. It deserves to be the top priority. Thanks to the PyPy tool ``vmprof``, we may already be there on the data taking side, but the presenting and correlation part, is still open and a fair bit of work. It will be most important to empower users to make competent performance bug reports, now that Nuitka enters the phase, where these things matter. As this is a lot of ground to cover. More than ever. We can make this compiler, but only if you help, it will arrive in your life time. *********************** Nuitka Release 0.5.14 *********************** This release is an intermediate step towards value propagation, which is not considered ready for stable release yet. The major point is the elimination of the ``try``/``finally`` expressions, as they are problems to SSA. The ``try``/``finally`` statement change is delayed. There are also a lot of bug fixes, and enhancements to code generation, as well as major cleanups of code base. Bug Fixes ========= - Python3: Added support assignments trailing star assignment. .. code:: python *a, b = 1, 2 This raised ``ValueError`` before. - Python3: Properly detect illegal double star assignments. .. code:: python *a, *b = c - Python3: Properly detect the syntax error to star assign from non-tuple/list. .. code:: python *a = 1 - Python3.4: Fixed a crash of the binary when copying dictionaries with split tables received as star arguments. - Python3: Fixed reference loss, when using ``raise a from b`` where ``b`` was an exception instance. Fixed in 0.5.13.8 already. - Windows: Fix, the flag ``--disable-windows-console`` was not properly handled for MinGW32 run time resulting in a crash. - Python2.7.10: Was not recognizing this as a 2.7.x variant and therefore not applying minor version compatibility levels properly. - Fix, when choosing to have frozen source references, code objects were not use the same value as ``__file__`` did for its filename. - Fix, when re-executing itself to drop the ``site`` module, make sure we find the same file again, and not according to the ``PYTHONPATH`` changes coming from it. Fixed in 0.5.13.4 already. - Enhanced code generation for ``del variable`` statements, where it's clear that the value must be assigned. - When pressing CTRL-C, the stack traces from both Nuitka and Scons were given, we now avoid the one from Scons. - Fix, the dump from ``--xml`` no longer contains functions that have become unused during analysis. - Standalone: Creating or running programs from inside unicode paths was not working on Windows. Fixed in 0.5.13.7 already. - Namespace package support was not yet complete, importing the parent of a package was still failing. Fixed in 0.5.13.7 already. - Python2.6: Compatibility for exception check messages enhanced with newest minor releases. - Compatibility: The ``NameError`` in classes needs to say ``global name`` and not just ``name`` too. - Python3: Fixed creation of XML representation, now done without ``lxml`` as it doesn't support needed features on that version. Fixed in 0.5.13.5 already. - Python2: Fix, when creating code for the largest negative constant to still fit into ``int``, that was only working in the main module. Fixed in 0.5.13.5 already. - Compatibility: The ``print`` statement raised an assertion on unicode objects that could not be encoded with ``ascii`` codec. New Features ============ - Added support for Windows 10. - Followed changes for Python 3.5 beta 2. Still only usable as a Python 3.4 replacement, no new features. - Using a self compiled Python running from the source tree is now supported. - Added support for Anaconda Python distribution. As it doesn't install the Python DLL, we copy it along for acceleration mode. - Added support for Visual Studio 2015. Fixed in 0.5.13.3 already. - Added support for self compiled Python versions running from build tree, this is intended to help debug things on Windows. Optimization ============ - Function in-lining is now present in the code, but still disabled, because it needs more changes in other areas, before we can generally do it. - Trivial outlines, result of re-formulations or function in-lining, are now in-lined, in case they just return an expression. - The re-formulation for ``or`` and ``and`` has been giving up, eliminating the use of a ``try``/``finally`` expression, at the cost of dedicated boolean nodes and code generation for these. This saves around 8% of compile time memory for Nuitka, and allows for faster and more complete optimization, and gets rid of a complicated structure for analysis. - When a frame is used in an exception, its locals are detached. This was done more often than necessary and even for frames that are not necessary our own ones. This will speed up some exception cases. - When the default arguments, or the keyword default arguments (Python3) or the annotations (Python3) were raising an exception, the function definition is now replaced with the exception, saving a code generation. This happens frequently with Python2/Python3 compatible code guarded by version checks. - The SSA analysis for loops now properly traces "break" statement situations and merges the post-loop situation from all of them. This significantly allows for and improves optimization of code following the loop. - The SSA analysis of ``try``/``finally`` statements has been greatly enhanced. The handler for ``finally`` is now optimized for exception raise and no exception raise individually, as well as for ``break``, ``continue`` and ``return`` in the tried code. The SSA analysis for after the statement is now the result of merging these different cases, should they not abort. - The code generation for ``del`` statements is now taking advantage should there be definite knowledge of previous value. This speed them up slightly. - The SSA analysis of ``del`` statements now properly decided if the statement can raise or not, allowing for more optimization. - For list contractions, the re-formulation was enhanced using the new outline construct instead of a pseudo function, leading to better analysis and code generation. - Comparison chains are now re-formulated into outlines too, allowing for better analysis of them. - Exceptions raised in function creations, e.g. in default values, are now propagated, eliminating the function's code. This happens most often with Python2/Python3 in branches. On the other hand, function creations that cannot are also annotated now. - Closure variables that become unreferenced outside of the function become normal variables leading to better tracing and code generation for them. - Function creations cannot raise except their defaults, keyword defaults or annotations do. - Built-in references can now be converted to strings at compile time, e.g. when printed. Organisational ============== - Removed gitorious mirror of the git repository, they shut down. - Make it more clear in the documentation that Python2 is needed at compile time to create Python3 executables. Cleanups ======== - Moved more parts of code generation to their own modules, and used registry for code generation for more expression kinds. - Unified ``try``/``except`` and ``try``/``finally`` into a single construct that handles both through ``try``/``except``/``break``/``continue``/``return`` semantics. Finally is now solved via duplicating the handler into cases necessary. No longer are nodes annotated with information if they need to publish the exception or not, this is now all done with the dedicated nodes. - The ``try``/``finally`` expressions have been replaced with outline function bodies, that instead of side effect statements, are more like functions with return values, allowing for easier analysis and dedicated code generation of much lower complexity. - No more "tolerant" flag for release nodes, we now decide this fully based on SSA information. - Added helper for assertions that code flow does not reach certain positions, e.g. a function must return or raise, aborting statements do not continue and so on. - To keep cloning of code parts as simple as possible, the limited use of ``makeCloneAt`` has been changed to a new ``makeClone`` which produces identical copies, which is what we always do. And a generic cloning based on "details" has been added, requiring to make constructor arguments and details complete and consistent. - The re-formulation code helpers have been improved to be more convenient at creating nodes. - The old ``nuitka.codegen`` module ``Generator`` was still used for many things. These now all got moved to appropriate code generation modules, and their users got updated, also moving some code generator functions in the process. - The module ``nuitka.codegen.CodeTemplates`` got replaces with direct uses of the proper topic module from ``nuitka.codegen.templates``, with some more added, and their names harmonized to be more easily recognizable. - Added more assertions to the generated code, to aid bug finding. - The autoformat now sorts pylint markups for increased consistency. - Releases no longer have a ``tolerant`` flag, this was not needed anymore as we use SSA. - Handle CTRL-C in scons code preventing per job messages that are not helpful and avoid tracebacks from scons, also remove more unused tools like ``rpm`` from out in-line copy. Tests ===== - Added the CPython3.4 test suite. - The CPython3.2, CPython3.3, and CPython3.4 test suite now run with Python2 giving the same errors. Previously there were a few specific errors, some with line numbers, some with different ``SyntaxError`` be raised, due to different order of checks. This increases the coverage of the exception raising tests somewhat. - Also the CPython3.x test suites now all pass with debug Python, as does the CPython 2.6 test suite with 2.6 now. - Added tests to cover all forms of unpacking assignments supported in Python3, to be sure there are no other errors unknown to us. - Started to document the reference count tests, and to make it more robust against SSA optimization. This will take some time and is work in progress. - Made the compile library test robust against modules that raise a syntax error, checking that Nuitka does the same. - Refined more tests to be directly executable with Python3, this is an ongoing effort. Summary ======= This release is clearly major. It represents a huge step forward for Nuitka as it improves nearly every aspect of code generation and analysis. Removing the ``try``/``finally`` expression nodes proved to be necessary in order to even have the correct SSA in their cases. Very important optimization was blocked by it. Going forward, the ``try``/``finally`` statements will be removed and dead variable elimination will happen, which then will give function inlining. This is expected to happen in one of the next releases. This release is a consolidation of 8 hotfix releases, and many refactorings needed towards the next big step, which might also break things, and for that reason is going to get its own release cycle. *********************** Nuitka Release 0.5.13 *********************** This release contains the first use of SSA for value propagation and massive amounts of bug fixes and optimization. Some of the bugs that were delivered as hotfixes, were only revealed when doing the value propagation as they still could apply to real code. Bug Fixes ========= - Fix, relative imports in packages were not working with absolute imports enabled via future flags. Fixed in 0.5.12.1 already. - Loops were not properly degrading knowledge from inside the loop at loop exit, and therefore this could have lead missing checks and releases in code generation for cases, for ``del`` statements in the loop body. Fixed in 0.5.12.1 already. - The ``or`` and ``and`` re-formulation could trigger false assertions, due to early releases for compatibility. Fixed in 0.5.12.1 already. - Fix, optimizion of calls of constant objects (always an exception), crashed the compiler.Fixed in 0.5.12.2 already. - Standalone: Added support for ``site.py`` installations with a leading ``def`` or ``class`` statement, which is defeating our attempt to patch ``__file__`` for it. - Compatibility: In full compatibility mode, the tracebacks of ``or`` and ``and`` expressions are now as wrong as they are in CPython. Does not apply to ``--improved`` mode. - Standalone: Added missing dependency on ``QtGui`` by ``QtWidgets`` for PyQt5. - macOS: Improved parsing of ``otool`` output to avoid duplicate entries, which can also be entirely wrong in the case of Qt plugins at least. - Avoid relative paths for main program with file reference mode ``original``, as it otherwise changes as the file moves. - MinGW: The created modules depended on MinGW to be in ``PATH`` for their usage. This is no longer necessary, as we now link these libraries statically for modules too. - Windows: For modules, the option ``--run`` to immediately load the modules had been broken for a while. - Standalone: Ignore Windows DLLs that were attempted to be loaded, but then failed to load. This happens e.g. when both PySide and PyQt are installed, and could cause the dreaded conflicting DLLs message. The DLL loaded in error is now ignored, which avoids this. - MinGW: The resource file used might be empty, in which case it doesn't get created, avoiding an error due to that. - MinGW: Modules can now be created again. The run time relative code uses an API that is WinXP only, and MinGW failed to find it without guidance. Optimization ============ - Make direct calls out of called function creations. Initially this applies to lambda functions only, but it's expected to become common place in coming releases. This is now 20x faster than CPython. .. code:: python # Nuitka avoids creating a function object, parsing function arguments: (lambda x: x)(something) - Propagate assignments from non-mutable constants forward based on SSA information. This is the first step of using SSA for real compile time optimization. - Specialized the creation of call nodes at creation, avoiding to have all kinds be the most flexible form (keyword and plain arguments), but instead only what kind of call they really are. This saves lots of memory, and makes the tree faster to visit. - Added support for optimizing the ``slice`` built-in with compile time constant arguments to constants. The re-formulation for slices in Python3 uses these a lot. And the lack of this optimization prevented a bunch of optimization in this area. For Python2 the built-in is optimized too, but not as important probably. - Added support for optimizing ``isinstance`` calls with compile time constant arguments. This avoids static exception raises in the ``exec`` re-formulation which tests for ``file`` type, and then optimization couldn't tell that a ``str`` is not a ``file`` instance. Now it can. - Lower in-place operations on immutable types to normal operations. This will allow to compile time compute these more accurately. - The re-formulation of loops puts the loop condition as a conditional statement with break. The ``not`` that needs to apply was only added in later optimization, leading to unnecessary compile time efforts. - Removed per variable trace visit from optimization, removing useless code and compile time overhead. We are going to optimize things by making decision in assignment and reference nodes based on forward looking statements using the last trace collection. New Features ============ - Added experimental support for Python 3.5, which seems to be passing the test suites just fine. The new ``@`` matrix multiplicator operators are not yet supported though. - Added support for patching source on the fly. This is used to work around a (now fixed) issue with ``numexpr.cpuinfo`` making type checks with the ``is`` operation, about the only thing we cannot detect. Organisational ============== - Added repository for Ubuntu Vivid (15.04) for download. Removed Ubuntu Saucy and Ubuntu Raring package downloads, these are no longer supported by Ubuntu. - Added repository for Debian Stretch, after Jessie release. - Make it more clear in the documentation that in order to compile Python3, a Python2 is needed to execute Scons, but that the end result is a Python3 binary. - The PyLint checker tool now can operate on directories given on the command line, and whitelists an error that is Windows only. Cleanups ======== - Split up standalone code further, moving ``depends.exe`` handling to a separate module. - Reduced code complexity of scons interface. - Cleaned up where trace collection is being done. It was partially still done inside the collection itself instead in the owner. - In case of conflicting DLLs for standalone mode, these are now output with nicer formatting, that makes it easy to recognize what is going on. - Moved code to fetch ``depends.exe`` to dedicated module, so it's not as much in the way of standalone code. Tests ===== - Made ``BuiltinsTest`` directly executable with Python3. - Added construct test to demonstrate the speed up of direct lambda calls. - The deletion of ``@test`` for the CPython test suite is more robust now, esp. on Windows, the symbolic links are now handled. - Added test to cover ``or`` usage with in-place assignment. - Cover local relative ``import from .`` with ``absolute_import`` future flag enabled. - Again, more basic tests are now directly executable with Python3. Summary ======= This release is major due to amount of ground covered. The reduction in memory usage of Nuitka itself (the C++ compiler will still use much memory) is very massive and an important aspect of scalability too. Then the SSA changes are truly the first sign of major improvements to come. In their current form, without eliminating dead assignments, the full advantage is not taken yet, but the next releases will do this, and that's a major milestone to Nuitka. The other optimization mostly stem from looking at things closer, and trying to work towards function in-lining, for which we are making a lot of progress now. *********************** Nuitka Release 0.5.12 *********************** This release contains massive amounts of corrections for long standing issues in the import recursion mechanism, as well as for standalone issues now visible after the ``__file__`` and ``__path__`` values have changed to become runtime dependent values. Bug Fixes ========= - Fix, the ``__path__`` attribute for packages was still the original filename's directory, even in file reference mode was ``runtime``. - The use of ``runtime`` as default file reference mode for executables, even if not in standalone mode, was making acceleration harder than necessary. Changed to ``original`` for that case. Fixed in 0.5.11.1 already. - The constant value for the smallest ``int`` that is not yet a ``long`` is created using ``1`` due to C compiler limitations, but ``1`` was not yet initialized properly, if this was a global constant, i.e. used in multiple modules. Fixed in 0.5.11.2 already. - Standalone: Recent fixes around ``__path__`` revealed issues with PyWin32, where modules from ``win32com.shell`` were not properly recursed to. Fixed in 0.5.11.2 already. - The importing of modules with the same name as a built-in module inside a package falsely assumed these were the built-ins which need not exist, and then didn't recurse into them. This affected standalone mode the most, as the module was then missing entirely. .. code:: python # Inside "x.y" module: import x.y.exceptions - Similarly, the importing of modules with the same name as standard library modules could go wrong. .. code:: python # Inside "x.y" module: import x.y.types - Importing modules on Windows and macOS was not properly checking the checking the case, making it associate wrong modules from files with mismatching case. - Standalone: Importing with ``from __future__ import absolute_import`` would prefer relative imports still. - Python3: Code generation for ``try``/``return expr``/``finally`` could loose exceptions when ``expr`` raised an exception, leading to a ``RuntimeError`` for ``NULL`` return value. The real exception was lost. - Lambda expressions that were directly called with star arguments caused the compiler to crash. .. code:: python (lambda *args: args)(*args) # was crashing Nuitka Optimization ============ - Focusing on compile time memory usage, cyclic dependencies of trace merges that prevented them from being released, even when replaced were removed. - More memory efficient updating of global SSA traces, reducing memory usage during optimization by ca. 50%. - Code paths that cannot and therefore must not happen are now more clearly indicated to the backend compiler, allowing for slightly better code to be generated by it, as it can tell that certain code flows need not be merged. New Features ============ - Standalone: On systems, where ``.pth`` files inject Python packages at launch, these are now detected, and taking into account. Previously Nuitka did not recognize them, due to lack of ``__init__.py`` files. These are mostly pip installations of e.g. ``zope.interface``. - Added option ``--explain-imports`` to debug the import resolution code of Nuitka. - Added options ``--show-memory`` to display the amount of memory used in total and how it's spread across the different node types during compilation. - The option ``--trace-execution`` now also covers early program initialisation before any Python code runs, to ease finding bugs in this domain as well. Organisational ============== - Changed default for file reference mode to ``original`` unless standalone or module mode are used. For mere acceleration, breaking the reading of data files from ``__file__`` is useless. - Added check that the in-line copy of scons is not run with Python3, which is not supported. Nuitka works fine with Python3, but a Python2 is required to execute scons. - Discover more kinds of Python2 installations on Linux/macOS installations. - Added instructions for macOS to the download page. Cleanups ======== - Moved ``oset`` and ``odict`` modules which provide ordered sets and dictionaries into a new package ``nuitka.container`` to clean up the top level scope. - Moved ``SyntaxErrors`` to ``nuitka.tree`` package, where it is used to format error messages. - Moved ``nuitka.Utils`` package to ``nuitka.utils.Utils`` creating a whole package for utils, so as to better structure them for their purpose. Summary ======= This release is a major maintenance release. Support for namespace modules injected by ``*.pth`` is a major step for new compatibility. The import logic improvements expand the ability of standalone mode widely. Many more use cases will now work out of the box, and less errors will be found on case insensitive systems. There is aside of memory issues, no new optimization though as many of these improvements could not be delivered as hotfixes (too invasive code changes), and should be out to the users as a stable release. Real optimization changes have been postponed to be next release. *********************** Nuitka Release 0.5.11 *********************** The last release represented a significant change and introduced a few regressions, which got addressed with hot fix releases. But it also had a focus on cleaning up open optimization issues that were postponed in the last release. New Features ============ - The filenames of source files as found in the ``__file__`` attribute are now made relative for all modes, not just standalone mode. This makes it possible to put data files along side compiled modules in a deployment. Bug Fixes ========= - Local functions that reference themselves were not released. They now are. .. code:: python def someFunction(): def f(): f() # referencing 'f' in 'f' caused the garbage collection to fail. Recent changes to code generation attached closure variable values to the function object, so now they can be properly visited. Fixed in 0.5.10.1 already. - Python2.6: The complex constants with real or imaginary parts ``-0.0`` were collapsed with constants of value ``0.0``. This became more evident after we started to optimize the ``complex`` built-in. Fixed in 0.5.10.1 already. .. code:: python complex(0.0, 0.0) complex(-0.0, -0.0) # Could be confused with the above. - Complex call helpers could leak references to their arguments. This was a regression. Fixed in 0.5.10.1 already. - Parameter variables offered as closure variables were not properly released, only the cell object was, but not the value. This was a regression. Fixed in 0.5.10.1 already. - Compatibility: The exception type given when accessing local variable values not initialized in a closure taking function, needs to be ``NameError`` and ``UnboundLocalError`` for accesses in the providing function. Fixed in 0.5.10.1 already. - Fix support for "venv" on systems, where the system Python uses symbolic links too. This is the case on at least on Mageia Linux. Fixed in 0.5.10.2 already. - Python3.4: On systems where ``long`` and ``Py_ssize_t`` are different (e.g. Win64) iterators could be corrupted if used by uncompiled Python code. Fixed in 0.5.10.2 already. - Fix, generator objects didn't release weak references to them properly. Fixed in 0.5.10.2 already. - Compatibility: The ``__closure__`` attributes of functions was so far not supported, and rarely missing. Recent changes made it easy to expose, so now it was added. - macOS: A linker warning about deprecated linker option ``-s`` was solved by removing the option. - Compatibility: Nuitka was enforcing that the ``__doc__`` attribute to be a string object, and gave a misleading error message. This check must not be done though, ``__doc__`` can be any type in Python. Optimization ============ - Variables that need not be shared, because the uses in closure taking functions were eliminated, no longer use cell objects. - The ``try``/``except`` and ``try``/``finally`` statements now both have actual merging for SSA, allowing for better optimization of code behind it. .. code:: python def f(): try: a = something() except: return 2 # Since the above exception handling cannot continue the code flow, # we do not have to invalidate the trace of "a", and e.g. do not have # to generate code to check if it's assigned. return a Since ``try``/``finally`` is used in almost all re-formulations of complex Python constructs this is improving SSA application widely. The uses of ``try``/``except`` in user code will no longer degrade optimization and code generation efficiency as much as they did. - The ``try``/``except`` statement now reduces the scope of tried block if possible. When no statement raised, already the handling was removed, but leading and trailing statements that cannot raise, were not considered. .. code:: python def f(): try: b = 1 a = something() c = 1 except: return 2 This is now optimized to. .. code:: python def f(): b = 1 try: a = something() except: return 2 c = 1 The impact may on execution speed may be marginal, but it is definitely going to improve the branch merging to be added later. Note that ``c`` can only be optimized, because the exception handler is aborting, otherwise it would change behaviour. - The creation of code objects for standalone mode and now all code objects was creating a distinct filename object for every function in a module, despite them being same content. This was wasteful for module loading. Now it's done only once. Also, when having multiple modules, the code to build the run time filename used for code objects, was calling import logic, and doing lookups to find ``os.path.join`` again and again. These are now cached, speeding up the use of many modules as well. Cleanups ======== - Nuitka used to have "variable usage profiles" and still used them to decide if a global variable is written to, in which case, it stays away from doing optimization of it to built-in lookups, and later calls. The have been replaced by "global variable traces", which collect the traces to a variable across all modules and functions. While this is now only a replacement, and getting rid of old code, and basing on SSA, later it will also allow to become more correct and more optimized. - The standalone now queries its hidden dependencies from a plugin framework, which will become an interface to Nuitka internals in the future. Testing ======= - The use of deep hashing of constants allows us to check if constants become mutated during the run-time of a program. This allows to discover corruption should we encounter it. - The tests of CPython are now also run with Python in debug mode, but only on Linux, enhancing reference leak coverage. - The CPython test parts which had been disabled due to reference cycles involving compiled functions, or usage of ``__closure__`` attribute, were reactivated. Organisational ============== - Since Google Code has shutdown, it has been removed from the Nuitka git mirrors. Summary ======= This release brings exciting new optimization with the focus on the ``try`` constructs, now being done more optimal. It is also a maintenance release, bringing out compatibility improvements, and important bug fixes, and important usability features for the deployment of modules and packages, that further expand the use cases of Nuitka. The git flow had to be applied this time to get out fixes for regression bug fixes, that the big change of the last release brought, so this is also to consolidate these and the other corrections into a full release before making more invasive changes. The cleanups are leading the way to expanded SSA applied to global variable and shared variable values as well. Already the built-in detect is now based on global SSA information, which was an important step ahead. *********************** Nuitka Release 0.5.10 *********************** This release has a focus on code generation optimization. Doing major changes away from "C++-ish" code to "C-ish" code, many constructs are now faster or got looked at and optimized. Bug Fixes ========= - Compatibility: The variable name in locals for the iterator provided to the generator expression should be ``.0``, now it is. - Generators could leak frames until program exit, these are now properly freed immediately. Optimization ============ - Faster exception save and restore functions that might be in-lined by the backend C compiler. - Faster error checks for many operations, where these errors are expected, e.g. instance attribute lookups. - Do not create traceback and locals dictionary for frame when ``StopIteration`` or ``GeneratorExit`` are raised. These tracebacks were wasted, as they were immediately released afterwards. - Closure variables to functions and parameters of generator functions are now attached to the function and generator objects. - The creation of functions with closure taking was accelerated. - The creation and destruction of generator objects was accelerated. - The re-formulation for in-place assignments got simplified and got faster doing so. - In-place operations of ``str`` were always copying the string, even if was not necessary. .. code:: python a += b # Was not re-using the storage of "a" in case of strings - Python2: Additions of ``int`` for Python2 are now even faster. - Access to local variable values got slightly accelerated at the expense of closure variables. - Added support for optimizing the ``complex`` built-in. - Removing unused temporary and local variables as a result of optimization, these previously still allocated storage. Cleanup ======= - The use of C++ classes for variable objects was removed. Closure variables are now attached as ``PyCellObject`` to the function objects owning them. - The use of C++ context classes for closure taking and generator parameters has been replaced with attaching values directly to functions and generator objects. - The indentation of code template instantiations spanning multiple was not in all cases proper. We were using emission objects that handle it new lines in code and mere ``list`` objects, that don't handle them in mixed forms. Now only the emission objects are used. - Some templates with C++ helper functions that had no variables got changed to be properly formatted templates. - The internal API for handling of exceptions is now more consistent and used more efficiently. - The printing helpers got cleaned up and moved to static code, removing any need for forward declaration. - The use of ``INCREASE_REFCOUNT_X`` was removed, it got replaced with proper ``Py_XINCREF`` usages. The function was once required before "C-ish" lifted the need to do everything in one function call. - The use of ``INCREASE_REFCOUNT`` got reduced. See above for why that is any good. The idea is that ``Py_INCREF`` must be good enough, and that we want to avoid the C function it was, even if in-lined. - The ``assertObject`` function that checks if an object is not ``NULL`` and has positive reference count, i.e. is sane, got turned into a preprocessor macro. - Deep hashes of constant values created in ``--debug`` mode, which cover also mutable values, and attempt to depend on actual content. These are checked at program exit for corruption. This may help uncover bugs. Organisational ============== - Speedcenter has been enhanced with better graphing and has more benchmarks now. More work will be needed to make it useful. - Updates to the Developer Manual, reflecting the current near finished state of "C-ish" code generation. Tests ===== - New reference count tests to cover generator expressions and their usage got added. - Many new construct based tests got added, these will be used for performance graphing, and serve as micro benchmarks now. - Again, more basic tests are directly executable with Python3. Summary ======= This is the next evolution of "C-ish" coming to pass. The use of C++ has for all practical purposes vanished. It will remain an ongoing activity to clear that up and become real C. The C++ classes were a huge road block to many things, that now will become simpler. One example of these were in-place operations, which now can be dealt with easily. Also, lots of polishing and tweaking was done while adding construct benchmarks that were made to check the impact of these changes. Here, generators probably stand out the most, as some of the missed optimization got revealed and then addressed. Their speed increases will be visible to some programs that depend a lot on generators. This release is clearly major in that the most important issues got addressed, future releases will provide more tuning and completeness, but structurally the "C-ish" migration has succeeded, and now we can reap the benefits in the coming releases. More work will be needed for all in-place operations to be accelerated. More work will be needed to complete this, but it's good that this is coming to an end, so we can focus on SSA based optimization for the major gains to be had. ********************** Nuitka Release 0.5.9 ********************** This release is mostly a maintenance release, bringing out minor compatibility improvements, and some standalone improvements. Also new options to control the recursion into modules are added. Bug Fixes ========= - Compatibility: Checks for iterators were using ``PyIter_Check`` which is buggy when running outside of Python core, because it's comparing pointers we don't see. Replaced with ``HAS_ITERNEXT`` helper which compares against the pointer as extracting for a real non-iterator object. .. code:: python class Iterable: def __init__(self): self.consumed = 2 def __iter__(self): return Iterable() iter(Iterable()) # This is suppose to raise, but didn't with Nuitka - Python3: Errors when creating class dictionaries raised by the ``__prepare__`` dictionary (e.g. ``enum`` classes with wrong identifiers) were not immediately raised, but only by the ``type`` call. This was not observable, but might have caused issues potentially. - Standalone macOS: Shared libraries and extension modules didn't have their DLL load paths updated, but only the main binary. This is not sufficient for more complex programs. - Standalone Linux: Shared libraries copied into the ``.dist`` folder were read-only and executing ``chrpath`` could potentially then fail. This has not been observed, but is a conclusion of macOS fix. - Standalone: When freezing standard library, the path of Nuitka and the current directory remained in the search path, which could lead to looking at the wrong files. Organisational ============== - The ``getattr`` built-in is now optimized for compile time constants if possible, even in the presence of a ``default`` argument. This is more a cleanup than actually useful yet. - The calling of ``PyCFunction`` from normal Python extension modules got accelerated, especially for the no or single argument cases where Nuitka now avoids building the tuple. New Features ============ - Added the option ``--recurse-pattern`` to include modules per filename, which for Python3 is the only way to not have them in a package automatically. - Added the option ``--generate-c++-only`` to only generate the C++ source code without starting the compiler. Mostly used for debugging and testing coverage. In the later case we do not want the C++ compiler to create any binary, but only to measure what would have been used. Organisational ============== - Renamed the debug option ``--c++-only`` to ``--recompile-c++-only`` to make its purpose more clear and there now is ``--generate-c++-only`` too. Tests ===== - Added support for taking coverage of Nuitka in a test run on a given input file. - Added support for taking coverage for all Nuitka test runners, migrating them all to common code for searching. - Added uniform way of reporting skipped tests, not generally used yet. Summary ======= This release marks progress towards having coverage testing. Recent releases had made it clear that not all code of Nuitka is actually used at least once in our release tests. We aim at identifying these. Another direction was to catch cases, where Nuitka leaks exceptions or is subject to leaked exceptions, which revealed previously unnoticed errors. Important changes have been delayed, e.g. the closure variables will not yet use C++ objects to share storage, but proper ``PyCellObject`` for improved compatibility, and to approach a more "C-ish" status. These is unfinished code that does this. And the forward propagation of values is not enabled yet again either. So this is an interim step to get the bug fixes and improvements accumulated out. Expect more actual changes in the next releases. ********************** Nuitka Release 0.5.8 ********************** This release has mainly a focus on cleanups and compatibility improvements. It also advances standalone support, and a few optimization improvements, but it mostly is a maintenance release, attacking long standing issues. Bug Fixes ========= - Compatibility Windows macOS: Fix importing on case insensitive systems. It was not always working properly, if there was both a package ``Something`` and ``something``, by merit of having files ``Something/__init__.py`` and ``something.py``. - Standalone: The search path was preferring system directories and therefore could have conflicting DLLs. - Fix, the optimization of ``getattr`` with predictable result was crashing the compilation. This was a regression, fixed in 0.5.7.1 already. - Compatibility: The name mangling inside classes also needs to be applied to global variables. - Fix, proving ``clang++`` for ``CXX`` was mistakingly thinking of it as a ``g++`` and making version checks on it. - Python3: Declaring ``__class__`` global is now a ``SyntaxError`` before Python3.4. - Standalone Python3: Making use of module state in extension modules was not working properly. New Features ============ - The filenames of source files as found in the ``__file__`` attribute are now made relative in standalone mode. This should make it more apparent if things outside of the distribution folder are used, at the cost of tracebacks. Expect the default ability to copy the source code along in an upcoming release. - Added experimental standalone mode support for PyQt5. At least headless mode should be working, plugins (needed for anything graphical) are not yet copied and will need more work. Cleanup ======= - No longer using ``imp.find_module`` anymore. To solve the casing issues we needed to make our own module finding implementation finally. - The name mangling was handled during code generation only. Moved to tree building instead. - More code generation cleanups. The compatible line numbers are now attached during tree building and therefore better preserved, as well as that code no longer polluting code generation as much. Organisational ============== - No more packages for openSUSE 12.1/12.2/12.3 and Fedora 17/18/19 as requested by the openSUSE Build Service. - Added RPM packages for Fedora 21 and CentOS 7 on openSUSE Build Service. Tests ===== - Lots of test refinements for the CPython test suites to be run continuously in Buildbot for both Windows and Linux. Summary ======= This release brings about two major changes, each with the risk to break things. One is that we finally started to have our own import logic, which has the risk to cause breakage, but apparently currently rather improved compatibility. The case issues were not fixable with standard library code. The second one is that the ``__file__`` attributes for standalone mode is now no longer pointing to the original install and therefore will expose missing stuff sooner. This will have to be followed up with code to scan for missing "data" files later on. For SSA based optimization, there are cleanups in here, esp. the one removing the name mangling, allowing to remove special code for class variables. This makes the SSA tree more reliable. Hope is that the big step (forward propagation through variables) can be made in one of the next releases. ********************** Nuitka Release 0.5.7 ********************** This release is brings a newly supported platform, bug fixes, and again lots of cleanups. Bug Fixes ========= - Fix, creation of dictionary and set literals with non-hashable indexes did not raise an exception. .. code:: python {[]: None} # This is now a TypeError Optimization ============ - Calls to the ``dict`` built-in with only keyword arguments are now optimized to mere dictionary creations. This is new for the case of non-constant arguments only of course. .. code:: python dict(a=b, c=d) # equivalent to {"a": b, "c": d} - Slice ``del`` with indexable arguments are now using optimized code that avoids Python objects too. This was already done for slice look-ups. - Added support for ``bytearray`` built-in. Organisational ============== - Added support for OpenBSD with fiber implementation from library, as it has no context support. Cleanups ======== - Moved slicing solutions for Python3 to the re-formulation stage. So far the slice nodes were used, but only at code generation time, there was made a distinction between Python2 and Python3 for them. Now these nodes are purely Python2 and slice objects are used universally for Python3. Tests ===== - The test runners now have common code to scan for the first file to compile, an implementation of the ``search`` mode. This will allow to introduce the ability to search for pattern matches, etc. - More tests are directly executable with Python3. - Added ``recurse_none`` mode to test comparison, making using extra options for that purpose unnecessary. Summary ======= This solves long standing issues with slicing and subscript not being properly distinguished in the Nuitka code. It also contains major bug fixes that really problematic. Due to the involved nature of these fixes they are made in this new release. ********************** Nuitka Release 0.5.6 ********************** This release brings bug fixes, important new optimization, newly supported platforms, and important compatibility improvements. Progress on all fronts. Bug Fixes ========= - Closure taking of global variables in member functions of classes that had a class variable of the same name was binding to the class variable as opposed to the module variable. - Overwriting compiled function's ``__doc__`` attribute more than once could corrupt the old value, leading to crashes. Fixed in 0.5.5.2 already. - Compatibility Python2: The ``exec`` statement ``execfile`` were changing ``locals()`` was given as an argument. .. code:: python def function(): a = 1 exec code in locals() # Cannot change local "a". exec code in None # Can change local "a" exec code Previously Nuitka treated all 3 variants the same. - Compatibility: Empty branches with a condition were reduced to only the condition, but they need in fact to also check the truth value: .. code:: python if condition: pass # must be treated as bool(condition) # and not (bug) condition - Detection of Windows virtualenv was not working properly. Fixed in 0.5.5.2 already. - Large enough constants structures are now unstreamed via ``marshal`` module, avoiding large codes being generated with no point. Fixed in 0.5.5.2 already. - Windows: Pressing CTRL-C gave two stack traces, one from the re-execution of Nuitka which was rather pointless. Fixed in 0.5.5.1 already. - Windows: Searching for virtualenv environments didn't terminate in all cases. Fixed in 0.5.5.1 already. - During installation from PyPI with Python3 versions, there were errors given for the Python2 only scons files. Fixed in 0.5.5.3 already. - Fix, the arguments of ``yield from`` expressions could be leaked. - Fix, closure taking of a class variable could have in a sub class where the module variable was meant. .. code:: python var = 1 class C: var = 2 class D: def f(): # was C.var, now correctly addressed top level var return var - Fix, setting ``CXX`` environment variable because the installed gcc has too low version, wasn't affecting the version check at all. - Fix, on Debian/Ubuntu with ``hardening-wrapper`` installed the version check was always failing, because these report a shortened version number to Scons. Optimization ============ - Local variables that must be assigned also have no side effects, making use of SSA. This allows for a host of optimization to be applied to them as well, often yielding simpler access/assign code, and discovering in more cases that frames are not necessary. - Micro optimization to ``dict`` built-in for simpler code generation. Organisational ============== - Added support for ARM "hard float" architecture. - Added package for Ubuntu 14.10 for download. - Added package for openSUSE 13.2 for download. - Donations were used to buy a Cubox-i4 Pro. It got Debian Jessie installed on it, and will be used to run an even larger amount of tests. - Made it more clear in the user documentation that the ``.exe`` suffix is used for all platforms, and why. - Generally updated information in User Manual and Developer Manual about the optimization status. - Using Nikola 7.1 with external filters instead of our own, outdated branch for the web site. Cleanups ======== - PyLint clean for the first time ever. We now have a Buildbot driven test that this stays that way. - Massive indentation cleanup of keyword argument calls. We have a rule to align the keywords, but as this was done manually, it could easily get out of touch. Now with a "autoformat" tool based on RedBaron, it's correct. Also, spacing around arguments is now automatically corrected. More to come. - For ``exec`` statements, the coping back to local variables is now an explicit node in the tree, leader to cleaner code generation, as it now uses normal variable assignment code generation. - The ``MaybeLocalVariables`` became explicit about which variable they might be, and contribute to its SSA trace as well, which was incomplete before. - Removed some cases of code duplication that were marked as TODO items. This often resulted in cleanups. - Do not use ``replaceWith`` on child nodes, that potentially were re-used during their computation. Summary ======= The release is mainly the result of consolidation work. While the previous release contained many important enhancements, this is another important step towards full SSA, closing one loop whole (class variables and ``exec`` functions), as well as applying it to local variables, largely extending its use. The amount of cleanups is tremendous, in huge part due to infrastructure problems that prevented release repeatedly. This reduces the technological debt very much. More importantly, it would appear that now eliminating local and temporary variables that are not necessary is only a small step away. But as usual, while this may be easy to implement now, it will uncover more bugs in existing code, that we need to address before we continue. ********************** Nuitka Release 0.5.5 ********************** This release is finally making full use of SSA analysis knowledge for code generation, leading to many enhancements over previous releases. It also adds support for Python3.4, which has been longer in the making, due to many rather subtle issues. In fact, even more work will be needed to fully solve remaining minor issues, but these should affect no real code. And then there is much improved support for using standalone mode together with virtualenv. This combination was not previously supported, but should work now. New Features ============ - Added support for Python3.4 This means support for ``clear`` method of frames to close generators, dynamic ``__qualname__``, affected by ``global`` statements, tuples as ``yield from`` arguments, improved error messages, additional checks, and many more detail changes. Optimization ============ - Using SSA knowledge, local variable assignments now no longer need to check if they need to release previous values, they know definitely for the most cases. .. code:: python def f(): a = 1 # This used to check if old value of "a" needs a release ... - Using SSA knowledge, local variable references now no longer need to check for raising exceptions, let alone produce exceptions for cases, where that cannot be. .. code:: python def f(): a = 1 return a # This used to check if "a" is assigned - Using SSA knowledge, local variable references now are known if they can raise the ``UnboundLocalError`` exception or not. This allows to eliminate frame usages for many cases. Including the above example. - Using less memory for keeping variable information. - Also using less memory for constant nodes. Bug Fixes ========= - The standalone freezing code was reading Python source as UTF-8 and not using the code that handles the Python encoding properly. On some platforms there are files in standard library that are not encoded like that. - The fiber implementation for Linux amd64 was not working with glibc from RHEL 5. Fixed to use now multiple ``int`` to pass pointers as necessary. Also use ``uintptr_t`` instead of ``intprt_t`` to transport pointers, which may be more optimal. - Line numbers for exceptions were corrupted by ``with`` statements due to setting line numbers even for statements marked as internal. - Partial support for ``win32com`` by adding support for its hidden ``__path__`` change. - Python3: Finally figured out proper chaining of exceptions, given proper context messages for exception raised during the handling of exceptions. - Corrected C++ memory leak for each closure variable taken, each time a function object was created. - Python3: Raising exceptions with tracebacks already attached, wasn't using always them, but producing new ones instead. - Some constants could cause errors, as they cannot be handled with the ``marshal`` module as expected, e.g. ``(int,)``. - Standalone: Make sure to propagate ``sys.path`` to the Python instance used to check for standard library import dependencies. This is important for virtualenv environments, which need ``site.py`` to set the path, which is not executed in that mode. - Windows: Added support for different path layout there, so using virtualenv should work there too. - The code object flag "optimized" (fast locals as opposed to locals dictionary) for functions was set wrongly to value for the parent, but for frames inside it, one with the correct value. This lead to more code objects than necessary and false ``co_flags`` values attached to the function. - Options passed to ``nuitka-python`` could get lost. .. code:: bash nuitka-python program.py argument1 argument2 ... The above is supposed to compile program.py, execute it immediately and pass the arguments to it. But when Nuitka decides to restart itself, it would forget these options. It does so to e.g. disable hash randomization as it would affect code generation. - Raising tuples exception as exceptions was not compatible (Python2) or reference leaking (Python3). Tests ===== - Running ``2to3`` is now avoided for tests that are already running on both Python2 and Python3. - Made XML based optimization tests work with Python3 too. Previously these were only working on Python2. - Added support for ignoring messages that come from linking against self compiled Pythons. - Added test case for threaded generators that tortures the fiber layer a bit and exposed issues on RHEL 5. - Made reference count test of compiled functions generic. No more code duplication, and automatic detection of shared stuff. Also a more clear interface for disabling test cases. - Added Python2 specific reference counting tests, so the other cases can be executed with Python3 directly, making debugging them less tedious. Cleanups ======== - Really important removal of "variable references". They didn't solve any problem anymore, but their complexity was not helpful either. This allowed to make SSA usable finally, and removed a lot of code. - Removed special code generation for parameter variables, and their dedicated classes, no more needed, as every variable access code is now optimized like this. - Stop using C++ class methods at all. Now only the destructor of local variables is actually supposed to do anything, and their are no methods anymore. The unused ``var_name`` got removed, ``setVariableValue`` is now done manually. - Moved assertions for the fiber layer to a common place in the header, so they are executed on all platforms in debug mode. - As usual, also a bunch of cleanups for PyLint were applied. - The ``locals`` built-in code now uses code generation for accessing local variable values instead having its own stuff. Organisational ============== - The Python version 3.4 is now officially supported. There are a few problems open, that will be addressed in future releases, none of which will affect normal people though. - Major cleanup of Nuitka options. - Windows specific stuff is now in a dedicated option group. This includes options for icon, disabling console, etc. - There is now a dedicated group for controlling backend compiler choices and options. - Also pickup ``g++44`` automatically, which makes using Nuitka on CentOS5 more automatic. Summary ======= This release represents a very important step ahead. Using SSA for real stuff will allow us to build the trust necessary to take the next steps. Using the SSA information, we could start implementing more optimizations. ********************** Nuitka Release 0.5.4 ********************** This release is aiming at preparatory changes to enable optimization based on SSA analysis, introducing a variable registry, so that variables no longer trace their references to themselves. Otherwise, MinGW64 support has been added, and lots of bug fixes were made to improve the compatibility. Optimization ============ - Using new variable registry, now properly detecting actual need for sharing variables. Optimization may discover that it is unnecessary to share a variable, and then it no longer is. This also allows ``--debug`` without it reporting unused variable warnings on Python3. - Scons startup has been accelerated, removing scans for unused tools, and avoiding making more than one gcc version check. Bug Fixes ========= - Compatibility: In case of unknown encodings, Nuitka was not giving the name of the problematic encoding in the error message. Fixed in 0.5.3.3 already. - Submodules with the same name as built-in modules were wrongly shadowed. Fixed in 0.5.3.2 already. - Python3: Added implementations of ``is_package`` to the meta path based loader. - Python3.4: Added ``find_spec`` implementation to the meta path based loader for increased compatibility. - Python3: Corrections for ``--debug`` to work with Python3 and MSVC compiler more often. - Fixed crash with ``--show-scons`` when no compiler was found. Fixed in 0.5.3.5 already. - Standalone: Need to blacklist ``lib2to3`` from standard library as well. Fixed in 0.5.3.4 already. - Python3: Adapted to changes in ``SyntaxError`` on newer Python releases, there is now a ``msg`` that can override ``reason``. - Standalone Windows: Preserve ``sys.executable`` as it might be used to fork binaries. - Windows: The caching of Scons was not arch specific, and files could be used again, even if changing the arch from ``x86`` to ``x86_64`` or back. - Windows: On 32 bit Python it can happen that with large number of generators running concurrently (>1500), one cannot be started anymore. Raising an ``MemoryError`` now. Organisational ============== - Added support for MinGW64. Currently needs to be run with ``PATH`` environment properly set up. - Updated internal version of Scons to 2.3.2, which breaks support for VS 2008, but adds support for VS 2013 and VS 2012. The VS 2013 is now the recommended compiler. - Added RPM package and repository for RHEL 7. - The output of ``--show-scons`` now includes the used compiler, including the MSVC version. - Added option ``--msvc`` to select the MSVC compiler version to use, which overrides automatic selection of the latest. - Added option ``-python-flag=no_warnings`` to disable user and deprecation warnings at run time. - Repository for Ubuntu Raring was removed, no more supported by Ubuntu. Cleanups ======== - Made technical and logical sharing decisions separate functions and implement them in a dedicated variable registry. - The Scons file has seen a major cleanup. Summary ======= This release is mostly a maintenance release. The Scons integrations has been heavily visited, as has been Python3 and esp. Python3.4 compatibility, and results from the now possible debug test runs. Standalone should be even more practical now, and MinGW64 is an option for those cases, where MSVC is too slow. ********************** Nuitka Release 0.5.3 ********************** This release is mostly a follow up, resolving points that have become possible to resolve after completing the C-ish evolution of Nuitka. So this is more of a service release. New Features ============ - Improved mode ``--improved`` now sets error lines more properly than CPython does in many cases. - The ``-python-flag=-S`` mode now preserves ``PYTHONPATH`` and therefore became usable with virtualenv. Optimization ============ - Line numbers of frames no longer get set unless an exception occurs, speeding up the normal path of execution. - For standalone mode, using ``--python-flag-S`` is now always possible and yields less module usage, resulting in smaller binaries and faster compilation. Bug Fixes ========= - Corrected an issue for frames being optimized away where in fact they are still necessary. Fixed in 0.5.2.1 already. - Fixed handling of exception tests as side effects. These could be remainders of optimization, but didn't have code generation. Fixed in 0.5.2.1 already. - Previously Nuitka only ever used the statement line as the line number for all the expression, even if it spawned multiple lines. Usually nothing important, and often even more correct, but sometimes not. Now the line number is most often the same as CPython in full compatibility mode, or better, see above. - Python3.4: Standalone mode for Windows is working now. - Standalone: Undo changes to ``PYTHONPATH`` or ``PYTHONHOME`` allowing potentially forked CPython programs to run properly. - Standalone: Fixed import error when using PyQt and Python3. New Tests ========= - For our testing approach, the improved line number handling means we can undo lots of changes that are no more necessary. - The compile library test has been extended to cover a third potential location where modules may live, covering the ``matplotlib`` module as a result. Cleanups ======== - In Python2, the list contractions used to be re-formulated to be function calls that have no frame stack entry of their own right. This required some special handling, in e.g. closure taking, and determining variable sharing across functions. This now got cleaned up to be properly in-lined in a ``try``/``finally`` expression. - The line number handling got simplified by pushing it into error exits only, removing the need to micro manage a line number stack which got removed. - Use ``intptr_t`` over ``unsigned long`` to store fiber code pointers, increasing portability. Organisational ============== - Providing own Debian/Ubuntu repositories for all relevant distributions. - Windows MSI files for Python 3.4 were added. - Hosting of the web site was moved to metal server with more RAM and performance. Summary ======= This release brings about structural simplification that is both a follow-up to C-ish, as well as results from a failed attempt to remove static "variable references" and be fully SSA based. It incorporates changes aimed at making this next step in Nuitka evolution smaller. ********************** Nuitka Release 0.5.2 ********************** This is a major release, with huge changes to code generation that improve performance in a significant way. It is a the result of a long development period, and therefore contains a huge jump ahead. New Features ============ - Added experimental support for Python 3.4, which is still work in progress. - Added support for virtualenv on macOS. - Added support for virtualenv on Windows. - Added support for macOS X standalone mode. - The code generation uses no header files anymore, therefore adding a module doesn't invalidate all compiled object files from caches anymore. - Constants code creation is now distributed, and constants referenced in a module are declared locally. This means that changing a module doesn't affect the validity of other modules object files from caches anymore. Optimization ============ - C-ish code generation uses less C++ classes and generates more C-like code. Explicit temporary objects are now used for statement temporary variables. - The constants creation code is no more in a single file, but distributed across all modules, with only shared values created in a single file. This means improved scalability. There are remaining bad modules, but more often, standalone mode is now fast. - Exception handling no longer uses C++ exception, therefore has become much faster. - Loops that only break are eliminated. - Dead code after loops that do not break is now removed. - The ``try``/``finally`` and ``try``/``except`` constructs are now eliminated, where that is possible. - The ``try``/``finally`` part of the re-formulation for ``print`` statements is now only done when printing to a file, avoiding useless node tree bloat. - Tuples and lists are now generated with faster code. - Locals and global variables are now access with more direct code. - Added support for the anonymous ``code`` type built-in. - Added support for ``compile`` built-in. - Generators that statically return immediately, e.g. due to optimization results, are no longer using frame objects. - The complex call helpers use no pseudo frames anymore. Previous code generation required to have them, but with C-ish code generation that is no more necessary, speeding up those kind of calls. - Modules with only code that cannot raise, need not have a frame created for them. This avoids useless code size bloat because of them. Previously the frame stack entry was mandatory. Bug Fixes ========= - Windows: The resource files were cached by Scons and re-used, even if the input changed. The could lead to corrupted incremental builds. Fixed in 0.5.1.1 already. - Windows: For functions with too many local variables, the MSVC failed with an error "C1026: parser stack overflow, program too complex". The rewritten code generation doesn't burden the compiler as much. - Compatibility: The timing deletion of nested call arguments was different from C++. This shortcoming has been addressed in the rewritten code generation. - Compatibility: The ``__future__`` flags and ``CO_FREECELL`` were not present in frame flags. These were then not always properly inherited to ``eval`` and ``exec`` in all cases. - Compatibility: Compiled frames for Python3 had ``f_restricted`` attribute, which is Python2 only. Removed it. - Compatibility: The ``SyntaxError`` of having a ``continue`` in a finally clause is now properly raised. - Python2: The ``exec`` statement with no locals argument provided, was preventing list contractions to take closure variables. - Python2: Having the ASCII encoding declared in a module wasn't working. - Standalone: Included the ``idna`` encoding as well. - Standalone: For virtualenv, the file ``orig-prefix.txt`` needs to be present, now it's copied into the "dist" directory as well. Fixed in 0.5.1.1 already. - Windows: Handle cases, where Python and user program are installed on different volumes. - Compatibility: Can now finally use ``execfile`` as an expression. One of our oldest issues, no 5, is finally fixed after all this time thanks to C-ish code generation. - Compatibility: The order or call arguments deletion is now finally compatible. This too is thanks to C-ish code generation. - Compatibility: Code object flags are now more compatible for Python3. - Standalone: Removing "rpath" settings of shared libraries and extension modules included. This makes standalone binaries more robust on Fedora 20. - Python2: Wasn't falsely rejecting ``unicode`` strings as values for ``int`` and ``long`` variants with base argument provided. - Windows: For Python3.2 and 64 bits, global variable accesses could give false ``NameError`` exceptions. Fixed in 0.5.1.6 already. - Compatibility: Many ``exec`` and ``eval`` details have become more correctly, the argument handling is more compatible, and e.g. future flags are now passed along properly. - Compatibility: Using ``open`` with no arguments is now giving the same error. Organisational ============== - Replying to email from the issue tracker works now. - Added option name alias ``--xml`` for ``--dump-xml``. - Added option name alias ``--python-dbg`` for ``--python-debug``, which actually might make it a bit more clear that it is about using the CPython debug run time. - Remove option ``--dump-tree``, it had been broken for a long time and unused in favor of XML dumps. - New digital art folder with 3D version of Nuitka logo. Thanks to Juan Carlos for creating it. - Using "README.rst" instead of "README.txt" to make it look better on web pages. - More complete whitelisting of missing imports in standard library. These should give no warnings anymore. - Updated the Nuitka GUI to the latest version, with enhanced features. - The builds of releases and update of the `downloads page `__ is now driven by Buildbot. Page will be automatically updated as updated binaries arrive. Cleanups ======== - Temporary keeper variables and the nodes to handle them are now unified with normal temporary variables, greatly simplifying variable handling on that level. - Less code is coming from templates, more is actually derived from the node tree instead. - Releasing the references to temporary variables is now always explicit in the node tree. - The publishing and preservation of exceptions in frames was turned into explicit nodes. - Exception handling is now done with a single handle that checks with branches on the exception. This eliminates exception handler nodes. - The ``dir`` built-in with no arguments is now re-formulated to ``locals`` or ``globals`` with their ``.keys()`` attribute taken. - Dramatic amounts of cleanups to code generation specialities, that got done right for the new C-ish code generation. New Tests ========= - Warnings from MSVC are now error exits for ``--debug`` mode too, expanding the coverage of these tests. - The outputs with ``python-dbg`` can now also be compared, allowing to expand test coverage for reference counts. - Many of the basic tests are now executable with Python3 directly. This allows for easier debug. - The library compilation test is now also executed with Python3. Summary ======= This release would deserve more than a minor number increase. The C-ish code generation, is a huge body of work. In many ways, it lays ground to taking benefit of SSA results, that previously would not have been possible. In other ways, it's incomplete in not yet taking full advantage yet. The release contains so many improvements, that are not yet fully realized, but as a compiler, it also reflects a stable and improved state. The important changes are about making SSA even more viable. Many of the problematic cases, e.g. exception handlers, have been stream lined. A whole class of variables, temporary keepers, has been eliminated. This is big news in this domain. For the standalone users, there are lots of refinements. There is esp. a lot of work to create code that doesn't show scalability issues. While some remain, the most important problems have been dealt with. Others are still in the pipeline. More work will be needed to take full advantage. This has been explained in a `separate post `__ in greater detail. ********************** Nuitka Release 0.5.1 ********************** This release brings corrections and major improvements to how standalone mode performs. Much of it was contributed via patches and bug reports. Bug Fixes ========= - There was a crash when using ``next`` on a non-iterable. Fixed in 0.5.0.1 already. - Module names with special characters not allowed in C identifiers were not fully supported. Fixed in 0.5.0.1 already. - Name mangling for classes with leading underscores was not removing them from resulting attribute names. This broke at ``__slots__`` with private attributes for such classes. Fixed in 0.5.0.1 already. - Standalone on Windows might need "cp430" encoding. Fixed in 0.5.0.2 already. - Standalone mode didn't work with ``lxml.etree`` due to lack of hard coded dependencies. When a shared library imports things, Nuitka cannot detect it easily. - Wasn't working on macOS 64 bits due to using Linux 64 bits specific code. Fixed in 0.5.0.2 already. - On MinGW the constants blob was not properly linked on some installations, this is now done differently (see below). New Features ============ - Memory usages are now traced with ``--show-progress`` allowing us to trace where things go wrong. Optimization ============ - Standalone mode now includes standard library as bytecode by default. This is workaround scalability issues with many constants from many modules. Future releases are going to undo it. - On Windows the constants blob is now stored as a resource, avoiding compilation via C code for MSVC as well. MinGW was changed to use the same code. New Tests ========= - Expanded test coverage for "standalone mode" demonstrating usage of "hex" encoding, PySide, and PyGtk packages. Summary ======= This release is mostly an interim maintenance release for standalone. Major changes that provide optimization beyond that, termed "C-ish code generation" are delayed for future releases. This release makes standalone practical which is an important point. Instead of hour long compilation, even for small programs, we are down to less than a minute. The solution of the scalability issues with many constants from many modules will be top priority going forward. Since they are about how even single use constants are created all in one place, this will be easy, but as large changes are happening in "C-ish code generation", we are waiting for these to complete. ********************** Nuitka Release 0.5.0 ********************** This release breaks interface compatibility, therefore the major version number change. Also "standalone mode" has seen significant improvements on both Windows, and Linux. Should work much better now. But consider that this part of Nuitka is still in its infancy. As it is not the top priority of mine for Nuitka, which primarily is intended as an super compatible accelerator of Python, it will continue to evolve nearby. There is also many new optimization based on structural improvements in the direction of actual SSA. Bug Fixes ========= - The "standalone mode" was not working on all Redhat, Fedora, and openSUSE platforms and gave warnings with older compilers. Fixed in 0.4.7.1 already. - The "standalone mode" was not including all useful encodings. Fixed in 0.4.7.2 already. - The "standalone mode" was defaulting to ``--python-flag=-S`` which disables the parsing of "site" module. That unfortunately made it necessary to reach some modules without modifying ``PYTHONPATH`` which conflicts with the "out-of-the-box" experience. - The "standalone mode" is now handling packages properly and generally working on Windows as well. - The syntax error of having an all catching except clause and then a more specific one wasn't causing a ``SyntaxError`` with Nuitka. .. code:: python try: something() except: somehandling() except TypeError: notallowed() - A corruption bug was identified, when re-raising exceptions, the top entry of the traceback was modified after usage. Depending on ``malloc`` this was potentially causing an endless loop when using it for output. New Features ============ - Windows: The "standalone" mode now properly detects used DLLs using `Dependency Walker `__ which it offers to download and extra for you. It is used as a replacement to ``ldd`` on Linux when building the binary, and as a replacement of ``strace`` on Linux when running the tests to check that nothing is loaded from the outside. Optimization ============ - When iterating over ``list``, ``set``, this is now automatically lowered to ``tuples`` avoiding the mutable container types. So the following code is now equivalent: .. code:: python for x in [a, b, c]: ... # same as for x in (a, b, c): ... For constants, this is even more effective, because for mutable constants, no more is it necessary to make a copy. - Python2: The iteration of large ``range`` is now automatically lowered to ``xrange`` which is faster to loop over, and more memory efficient. - Added support for the ``xrange`` built-in. - The statement only expression optimization got generalized and now is capable of removing useless parts of operations, not only the whole thing when it has not side effects. .. code:: python [a, b] # same as a b This works for all container types. Another example is ``type`` built-in operation with single argument. When the result is not used, it need not be called. .. code:: python type(a) # same as a And another example ``is`` and ``is not`` have no effect of their own as well, therefore: .. code:: python a is b # same as a b - Added proper handling of conditional expression branches in SSA based optimization. So far these branches were ignored, which only acceptable for temporary variables as created by tree building, but not other variable types. This is preparatory for introducing SSA for local variables. Organisational ============== - The option ``--exe`` is now ignored and creating an executable is the default behavior of ``nuitka``, a new option ``--module`` allows to produce extension modules. - The binary ``nuitka-python`` was removed, and is replaced by ``nuitka-run`` with now only implies ``--execute`` on top of what ``nuitka`` is. - Using dedicated `Buildbot `__ for continuous integration testing and release creation as well. - The `Downloads `__ now offers MSI files for Win64 as well. - Discontinued the support for cross compilation to Win32. That was too limited and the design choice is to have a running CPython instance of matching architecture at Nuitka compile time. New Tests ========= - Expanded test coverage for "standalone mode" demonstrating usage of "hex" encoding, and PySide package. Summary ======= The "executable by default" interface change improves on the already high ease of use. The new optimization do not give all that much in terms of numbers, but are all signs of structural improvements, and it is steadily approaching the point, where the really interesting stuff will happen. The progress for standalone mode is of course significant. It is still not quite there yet, but it is making quick progress now. This will attract a lot of attention hopefully. As for optimization, the focus for it has shifted to making exception handlers work optimal by default (publish the exception to ``sys.exc_info()`` and create traceback only when necessary) and be based on standard branches. Removing special handling of exception handlers, will be the next big step. This release includes some correctness fixes stemming from that work already. ********************** Nuitka Release 0.4.7 ********************** This release includes important new features, lots of polishing cleanups, and some important performance improvements as well. Bug Fixes ========= - The RPM packages didn't build due to missing in-line copy of Scons. Fixed in 0.4.6.1 already. - The recursion into modules and unfreezing them was not working for packages and modules anymore. Fixed in 0.4.6.2 already. - The Windows installer was not including Scons. Fixed in 0.4.6.3 already. - Windows: The immediate execution as performed by ``nuitka --execute`` was not preserving the exit code. - Python3.3: Packages without ``__init.py__`` were not properly embedding the name-space package as well. - Python3: Fix, modules and packages didn't add themselves to ``sys.modules`` which they should, happened only for programs. - Python3.3: Packages should set ``__package`` to their own name, not the one of their parents. - Python3.3: The ``__qualname__`` of nested classes was corrected. - For modules that recursed to other modules, an infinite loop could be triggered when comparing types with rich comparisons. New Features ============ - The "standalone" mode allows to compile standalone binaries for programs and run them without Python installation. The DLLs loaded by extension modules on Windows need to be added manually, on Linux these are determined automatically already. To achieve running without Python installation, Nuitka learned to freeze bytecode as an alternative to compiling modules, as some modules need to be present when the CPython library is initialized. - New option ``--python-flag`` allows to specify flags to the compiler that the "python" binary normally would. So far ``-S`` and ``-v`` are supported, with sane aliases ``no_site`` and ``trace_imports``. The recommended use of ``--python-flag=-S`` is to avoid dependency creep in standalone mode compilations, because the ``site`` module often imports many useless things that often don't apply to target systems. Optimization ============ - Faster frame stack handling for functions without ``try``/``except`` (or ``try``/``finally`` in Python3). This gives a speed boost to "PyStone" of ca. 2.5% overall. - Python2: Faster attribute getting and setting, handling special cases at compile time. This gives a minor speed boost to "PyStone" of ca. 0.5% overall. - Python2: Much quicker calls of ``__getattr__`` and ``__setattr__`` as this is now using the quicker call method avoiding temporary tuples. - Don't treat variables usages used in functions called directly by their owner as shared. This leads to more efficient code generation for contractions and class bodies. - Create ``unicode`` constants directly from their UTF-8 string representation for Python2 as well instead of un-streaming. So far this was only done for Python3. Affects only program start-up. - Directly create ``int`` and ``long`` constants outside of ``2**31`` and ``2**32-1``, but only limited according to actual platform values. Affects only program start-up. - When creating ``set`` values, no longer use a temporary ``tuple`` value, but use a properly generated helper functions instead. This makes creating sets much faster. - Directly create ``set`` constants instead of un-streaming them. Affects only program start-up. - For correct line numbers in traceback, the current frame line number must be updated during execution. This was done more often than necessary, e.g. loops set the line number before loop entry, and at first statement. - Module variables are now accessed even faster, the gain for "PyStone" is only 0.1% and mostly the result of leaner code. Organisational ============== - The "standalone mode" code (formerly known as "portable mode" has been redone and activated. This is a feature that a lot of people expect from a compiler naturally. And although the overall goal for Nuitka is of course acceleration, this kind of packaging is one of the areas where CPython needs improvement. - Added package for Ubuntu 13.10 for download, removed packages for Ubuntu 11.04 and 11.10, no more supported. - Added package for openSUSE 13.1 for download. - Nuitka is now part of Arch and can be installed with ``pacman -S nuitka``. - Using dedicated `Buildbot `__ for continuous integration testing. Not yet public. - Windows: In order to speed up repeated compilation on a platform without ``ccache``, added Scons level caching in the build directory. - Disabled hash randomization for inside Nuitka (but not in ultimately created binaries) for a more stable output, because dictionary constants will not change around. This makes the build results possible to cache for ``ccache`` and Scons as well. Tests ===== - The ``programs`` tests cases now fail if module or directory recursion is not working, being executed in another directory. - Added test runner for packages, with initial test case for package with recursion and sub-packages. - Made some test cases more strict by reducing ``PYTHONPATH`` provision. - Detect use of extra flags in tests that don't get consumed avoiding ineffective flags. - Use ``--execute`` on Windows as well, the issue that prevented it has been solved after all. Cleanups ======== - The generated code uses ``const_``, ``var_``, ``par_`` prefixes in the generated code and centralized the decision about these into single place. - Module variables no longer use C++ classes for their access, but instead accessor functions, leading to much less code generated per module variable and removing the need to trace their usage during code generation. - The test runners now share common code in a dedicated module, previously they replicated it all, but that turned out to be too tedious. - Massive general cleanups, many of which came from new contributor Juan Carlos Paco. - Moved standalone and freezer related codes to dedicated package ``nuitka.freezer`` to not pollute the ``nuitka`` package name space. - The code generation use variable identifiers and their accesses was cleaned up. - Removed several not-so-special case identifier classes because they now behave more identical and all work the same way, so a parameters can be used to distinguish them. - Moved main program, function object, set related code generation to dedicated modules. Summary ======= This release marks major technological progress with the introduction of the much sought standalone mode and performance improvements from improved code generation. The major break through for SSA optimization was not yet achieved, but this is again making progress in the direction of it. Harmonizing variables of different kinds was an important step ahead. Also very nice is the packaging progress, Nuitka was accepted into Arch after being in Debian Testing for a while already. Hope is to see more of this kind of integration in the future. ********************** Nuitka Release 0.4.6 ********************** This release includes progress on all fronts. The primary focus was to advance SSA optimization over older optimization code that was already in place. In this domain, there are mostly cleanups. Another focus has been to enhance Scons with MSVC on Windows. Nuitka now finds an installed MSVC compiler automatically, properly handles architecture of Python and Windows. This improves usability a lot. Then this is also very much about bug fixes. There have been several hot fixes for the last release, but a complicated and major issue forced a new release, and many other small issues. And then there is performance. As can be seen in the `performance graph `__, this release is the fastest so far. This came mainly from examining the need for comparison slots for compiled types. And last, but not least, this also expands the base of supported platforms, adding Gentoo, and self compiled Python to the mix. Bug Fixes ========= - Support Nuitka being installed to a path that contains spaces and handle main programs with spaces in their paths. Fixed in 0.4.5.1 already. - Support Python being installed to a path that contains spaces. Fixed in 0.4.5.2 already. - Windows: User provided constants larger than 65k didn't work with MSVC. Fixed in 0.4.5.3 already. - Windows: The option ``--windows-disable-console`` was not effective with MSVC. Fixed in 0.4.5.3 already. - Windows: For some users, Scons was detecting their MSVC installation properly already from registry, but it didn't honor the target architecture. Fixed in 0.4.5.3 already. - When creating Python modules, these were marked as executable ("x" bit), which they are of course not. Fixed in 0.4.5.3 already. - Python3.3: On architectures where ``Py_ssize_t`` is not the same as ``long`` this could lead to errors. Fixed in 0.4.5.3 already. - Code that was using nested mutable constants and changed the nested ones was not executing correctly. - Python2: Due to list contractions being re-formulated as functions, ``del`` was rejected for the variables assigned in the contraction. .. code:: python [expr(x) for x in iterable()] del x # Should work, was gave an unjustified SyntaxError. New Features ============ - Compiled types when used in Python comparison now work. Code like this will work: .. code:: python def f(): pass assert type(f) == types.FunctionType This of course also works for ``in`` operator, and is another step ahead in compatibility, and surprising too. And best of all, this works even if the checking code is not compiled with Nuitka. - Windows: Detecting MSVC installation from registry, if no compiler is already present in PATH. - Windows: New options ``--mingw64`` to force compilation with MinGW. Optimization ============ - Rich comparisons (``==``, ``<``, and the like) are now faster than ever before due to a full implementation of its own in Nuitka that eliminates a bit of the overhead. In the future, we will aim at giving it type hints to make it even faster. This gives a minor speed boost to PyStone of ca. 0.7% overall. - Integer comparisons are now treated preferably, as they are in CPython, which gives 1.3% speed boost to CPython. - The SSA based analysis is now used to provide variable scopes for temporary variables as well as reference count needs. Cleanups ======== - Replaced "value friend" based optimization code with SSA based optimization, which allowed to remove complicated and old code that was still used mainly in optimization of ``or`` and ``and`` expressions. - Delayed declaration of temp variables and their reference type is now performed based on information from SSA, which may given more accurate results. Not using "variable usage" profiles for this anymore. - The Scons interface and related code got a massive overhaul, making it more consistent and better documented. Also updated the internal copy to 2.3.0 for the platforms that use it, mostly Windows. - Stop using ``os.system`` and ``subprocess.call(..., shell = True)`` as it is not really portable at all, use ``subprocess.call(..., shell = False)`` instead. - As usual lots of cleanups related to line length issues and PyLint. Organisational ============== - Added support for Gentoo Linux. - Added support for self compiled Python versions with and without debug enabled. - Added use of Nuitka fonts for headers in manuals. - Does not install in-line copy of Scons only on systems where it is not going to be used, that is mostly non-Windows, and Linux where it is not already present. This makes for cleaner RPM packages. Summary ======= While the SSA stuff is not yet bearing performance fruits, it starts to carry weight. Taking over the temporary variable handling now also means we can apply the same stuff to local variables later. To make up for the delay in SSA driven performance improvements, there is more traditional code acceleration for rich comparisons, making it significant, and the bug fixes make Nuitka more compatible than ever. So give this a roll, it's worth it. And feel free to join the mailing list (since closed) or `make a donation `__ to support Nuitka. ********************** Nuitka Release 0.4.5 ********************** This release incorporates very many bug fixes, most of which were already part of hot fixes, usability improvements, documentation improvements, new logo, simpler Python3 on Windows, warnings for recursion options, and so on. So it's mostly a consolidation release. Bug Fixes ========= - When targeting Python 3.x, Nuitka was using "python" to run Scons to run it under Python 2.x, which is not good enough on systems, where that is already Python3. Improved to only do the guessing where necessary (i.e. when using the in-line copy of Scons) and then to prefer "python2". Fixed in 0.4.4.1 already. - When using Nuitka created binaries inside a "virtualenv", created programs would instantly crash. The attempt to load and patch ``inspect`` module was not making sure that ``site`` module was already imported, but inside the "virtualenv", it cannot be found unless. Fixed in 0.4.4.1 already. - The option ``--recurse-directory`` to include plugin directories was broken. Fixed in 0.4.4.2 already. - Python3: Files with "BOM" marker causes the compiler to crash. Fixed in 0.4.4.2 already. - Windows: The generated code for ``try``/``return``/``finally`` was working with gcc (and therefore MinGW), but not with MSVC, causing crashes. Fixed in 0.4.4.2 already. - The option ``--recurse-all`` did not recurse to package ``__init__.py`` files in case ``from x.y import z`` syntax was used. Fixed in 0.4.4.2 already. - Python3 on macOS: Corrected link time error. Fixed in 0.4.4.2 already. - Python3.3 on Windows: Fixed crash with too many arguments to a kwonly argument using function. Fixed in 0.4.4.2 already. - Python3.3 on Windows: Using "yield from" resulted in a link time error. Fixed in 0.4.4.2 already. - Windows: Added back XML manifest, found a case where it is needed to prevent clashes with binary modules. - Windows: Generators only worked in the main Python threads. Some unusual threading modules therefore failed. - Using ``sys.prefix`` to find the Python installation instead of hard coded paths. New Features ============ - Windows: Python3 finds Python2 installation to run Scons automatically now. Nuitka itself runs under Python3 just fine, but in order to build the generated C++ code into binaries, it uses Scons which still needs Python2. Nuitka will now find the Python2 installation searching Windows registry instead of requiring hard coded paths. - Windows: Python2 and Python3 find their headers now even if Python is not installed to specific paths. The installation path now is passed on to Scons which then uses it. - Better error checking for ``--recurse-to`` and ``--recurse-not-to`` arguments, tell the user not to use directory paths. - Added a warning for ``--recurse-to`` arguments that end up having no effect to the final result. Cleanups ======== - Import mechanism got cleaned up, stopped using "PyImport_ExtendInittab". It does not handle packages, and the ``sys.meta_path`` based importer is now well proven. - Moved some of the constraint collection code mess into proper places. It still remains a mess. Organisational ============== - Added ``LICENSE.txt`` file with Apache License 2.0 text to make it more immediately obvious which license Nuitka is under. - Added section about Nuitka license to the `User Manual `__. - Added `Nuitka Logo `__ to the distribution. - Use Nuitka Logo as the bitmap in the Windows installer. - Use Nuitka Logo in the documentation (`User Manual `__ and `Developer Manual `__). - Enhanced documentation to number page numbers starting after table of contents, removed header/footer from cover pages. Summary ======= This release is mostly the result of improvements made based on the surge of users after Europython 2013. Some people went to extents and reported their experience very detailed, and so I could aim at making e.g. their misconceptions about how recursion options work, more obvious through warnings and errors. This release is not addressing performance improvements. The next release will be able to focus on that. I am taking my claim of full compatibility very serious, so any time it's broken, it's the highest priority to restore it. ********************** Nuitka Release 0.4.4 ********************** This release marks the point, where Nuitka for the first time supports all major current Python versions and all major features. It adds Python 3.3 support and it adds support for threading. And then there is a massive amount of fixes that improve compatibility even further. Aside of that, there is major performance work. One side is the optimization of call performance (to CPython non-compiled functions) and to compiled functions, both. This gave a serious improvement to performance. Then of course, we are making other, long term performance progress, as in "--experimental" mode, the SSA code starts to optimize unused code away. That code is not yet ready for prime time yet, but the trace structure will hold. New Features ============ - Python3.3 support. The test suite of CPython3.3 passes now too. The ``yield from`` is now supported, but the improved argument parsing error messages are not implemented yet. - Tracing user provided constants, now Nuitka warns about too large constants produced during optimization. - Line numbers of expressions are now updates as evaluation progresses. This almost corrects. Now only expression parts that cannot raise, do not update, which can still cause difference, but much less often, and then definitely useless. - Experimental support for threads. Threading appears to work just fine in the most cases. It's not as optimal as I wanted it to be, but that's going to change with time. Optimization ============ - Previous corrections for ``==``, ``!=``, and ``<=``, caused a performance regression for these operations in case of handling identical objects. For built-in objects of sane types (not ``float``), these operations are now accelerated again. The overreaching acceleration of ``>=`` was still there (bug, see below) and has been adapted too. - Calling non-compiled Python functions from compiled functions was slower than in CPython. It is now just as fast. - Calling compiled functions without keyword arguments has been accelerated with a dedicated entry point that may call the implementation directly and avoid parameter parsing almost entirely. - Making calls to compiled and non-compiled Python functions no longer requires to build a temporary tuple and therefore is much faster. - Parameter parsing code is now more compact, and re-uses error raises, or creates them on the fly, instead of hard coding it. Saves binary size and should be more cache friendly. Bug Fixes ========= - Corrected false optimization of ``a >= a`` on C++ level. When it's not done during Nuitka compile time optimization, the rich comparison helper still contained short cuts for ``>=``. This is now the same for all the comparison operators. - Calling a function with default values, not providing it, and not providing a value for a value without default, was not properly detecting the error, and instead causing a run time crash. .. code:: python def f(a, b=2): pass f(b=2) This now properly raises the ``TypeError`` exception. - Constants created with ``+`` could become larger than the normally enforced limits. Not as likely to become huge, but still potentially an issue. - The ``vars`` built-in, when used on something without ``__dict__`` attribute, was giving ``AttributeError`` instead of ``TypeError``. - When re-cursing to modules at compile time, script directory and current directory were used last, while at run time, it was the other way around, which caused overloaded standard library modules to not be embedded. Thanks for the patch to James Michael DuPont. - Super without arguments was not raising the correct ``RuntimeError`` exception in functions that cannot be methods, but ``UnboundLocalError`` instead. .. code:: python def f(): super() # Error, cannot refer to first argument of f - Generators no longer use ``raise StopIteration`` for return statements, because that one is not properly handled in ``try``/``except`` clauses, where it's not supposed to trigger, while ``try``/``finally`` should be honored. - Exception error message when throwing non-exceptions into generators was not compatible. - The use of ``return`` with value in generators is a ``SyntaxError`` before Python3.3, but that was not raised. - Variable names of the "__var" style need to be mangled. This was only done for classes, but not for functions contained in classes, there they are now mangled too. - Python3: Exceptions raised with causes were not properly chaining. - Python3: Specifying the file encoding corrupted line numbers, making them all of by one. Cleanups ======== - For containers (``tuple``, ``list``, ``set``, ``dict``) defined on the source code level, Nuitka immediately created constant references from them. For function calls, class creations, slice objects, this code is now re-used, and its dictionaries and tuples, may now become constants immediately, reducing noise in optimization steps. - The parameter parsing code got cleaned up. There were a lot of relics from previously explored paths. And error raises were part of the templates, but now are external code. - Global variable management moved to module objects and out of "Variables" module. - Make sure, nodes in the tree are not shared by accident. This helped to find a case of duplicate use in the complex call helpers functions. Code generation will now notice this kind of duplication in debug mode. - The complex call helper functions were manually taking variable closure, which made these functions inconsistent to other functions, e.g. no variable version was allocated to assignments. Removing the manual setting of variables allowed a huge reduction of code volume, as it became more generic code. - Converting user provided constants to create containers into constants immediately, to avoid noise from doing this in optimization. - The ``site`` module is now imported explicitly in the ``__main__`` module, so it can be handled by the recursion code as well. This will help portable mode. - Many line length 80 changes, improved comments. New Tests ========= - The CPython3.3 test suite was added, and run with both Python3.2 and Python3.3, finding new bugs. - The ``doctest`` to code generation didn't successfully handle all tests, most notably, "test_generators.py" was giving a ``SyntaxError`` and therefore not actually active. Correcting that improved the coverage of generator testing. Organisational ============== - The portable code is still delayed. Support for Python3.3 was a higher priority, but the intention is to get it into shape for Europython still. Added notes about it being disabled it in the `User Manual `__ documentation. Summary ======= This release is in preparation for Europython 2013. Wanted to get this much out, as it changes the status slides quite a bit, and all of that was mostly done in my Cyprus holiday a while ago. The portable code has not seen progress. The idea here is to get this into a development version later. ********************** Nuitka Release 0.4.3 ********************** This release expands the reach of Nuitka substantially, as new platforms and compilers are now supported. A lot of polish has been applied. Under the hood there is the continued and in-progress effort to implement SSA form in Nuitka. New Features ============ - Support for new compiler: Microsoft Visual C++. You can now use Visual Studio 2008 or Visual Studio 2010 for compiling under Windows. - Support for NetBSD. Nuitka works for at least NetBSD 6.0, older versions may or may not work. This required fixing bugs in the generic "fibers" implementation. - Support for Python3 under Windows too. Nuitka uses Scons to build the generated C++ files. Unfortunately it requires Python2 to execute, which is not readily available to call from Python3. It now guesses the default installation paths of CPython 2.7 or CPython 2.6 and it will use it for running Scons instead. You have to install it to ``C:\Python26`` or ``C:\Python27`` for Nuitka to be able to find it. - Enhanced Python 3.3 compatibility. The support the newest version of Python has been extended, improving compatibility for many minor corner cases. - Added warning when a user compiles a module and executes it immediately when that references ``__name__``. Because very likely the intention was to create an executable. And esp. if there is code like this: .. code:: python if __name__ == "__main__": main() In module mode, Nuitka will optimize it away, and nothing will happen on execution. This is because the command .. code:: bash nuitka --execute module is behavioral more like .. code:: bash python -c "import module" and that was a trap for new users. - All Linux architectures are now supported. Due to changes in how evaluation order is enforced, we don't have to implement for specific architectures anymore. Bug Fixes ========= - Dictionary creation was not fully compatible. As revealed by using Nuitka with CPython3.3, the order in which dictionaries are to be populated needs to be reversed, i.e. CPython adds the last item first. We didn't observe this before, and it's likely the new dictionary implementation that finds it. Given that hash randomization makes dictionaries item order undetermined anyway, this is more an issue of testing. - Evaluation order for arguments of calls was not effectively enforced. It is now done in a standards compliant and therefore fully portable way. The compilers and platforms so far supported were not affected, but the newly supported Visual Studio C++ compiler was. - Using a ``__future__`` import inside a function was giving an assertion, instead of the proper syntax error. - Python3: Do not set the attributes ``sys.exc_type``, ``sys.exc_value``, ``sys.exc_traceback``. - Python3: Annotations of function worked only as long as their definition was not referring to local variables. Optimization ============ - Calls with no positional arguments are now using the faster call methods. The generated C++ code was using the ``()`` constant at call site, when doing calls that use no positional arguments, which is of course useless. - For Windows now uses OS "Fibers" for Nuitka "Fibers". Using threads for fibers was causing only overhead and with this API, MSVC had less issues too. Organisational ============== - Accepting `Donations `__ via Paypal, please support funding travels, website, etc. - The `User Manual `__ has been updated with new content. We now do support Visual Studio, documented the required LLVM version for clang, Win64 and modules may include modules too, etc. Lots of information was no longer accurate and has been updated. - The Changelog has been improved for consistency, wordings, and styles. - Nuitka is now available on the social code platforms as well - Bitbucket (since removed) - `Github `__ - Gitorious (since discontinued) - Google Code (since discontinued) - Removed ``clean-up.sh``, which is practically useless, as tests now clean up after themselves reasonably, and with ``git clean -dfx`` working better. - Removed "create-environment.sh" script, which was only setting the ``PATH`` variable, which is not necessary. - Added ``check-with-pylint --emacs`` option to make output its work with Emacs compilation mode, to allow easier fixing of warnings from PyLint. - Documentation is formatted for 80 columns now, source code will gradually aim at it too. So far 90 columns were used, and up to 100 tolerated. Cleanups ======== - Removed useless manifest and resource file creation under Windows. Turns out this is no longer needed at all. Either CPython, MinGW, or Windows improved to no longer need it. - PyLint massive cleanups and annotations bringing down the number of warnings by a lot. - Avoid use of strings and built-ins as run time pre-computed constants that are not needed for specific Python versions, or Nuitka modes. - Do not track needed tuple, list, and dict creation code variants in context, but e.g. in ``nuitka.codegen.TupleCodes`` module instead. - Introduced an "internal" module to host the complex call helper functions, instead of just adding it to any module that first uses it. New Tests ========= - Added basic tests for order evaluation, where there currently were None. - Added support for "2to3" execution under Windows too, so we can run tests for Python3 installations too. Summary ======= The release is clearly major step ahead. The new platform support triggered a whole range of improvements, and means this is truly complete now. Also there is very much polish in this release, reducing the number of warnings, updated documentation, the only thing really missing is visible progress with optimization. ********************** Nuitka Release 0.4.2 ********************** This release comes with many bug fixes, some of which are severe. It also contains new features, like basic Python 3.3 support. And the `performance diagrams `__ got expanded. New Features ============ - Support for FreeBSD. Nuitka works for at least FreeBSD 9.1, older versions may or may not work. This required only fixing some "Linuxisms" in the build process. - New option for warning about compile time detected exception raises. Nuitka can now warn about exceptions that will be raised at run time. - Basic Python3.3 support. The test suite of CPython3.2 passes and fails in a compatible way. New feature ``yield from`` is not yet supported, and the improved argument parsing error messages are not implemented yet. Bug Fixes ========= - Nuitka already supported compilation of "main directories", i.e. directories with a "__main__.py" file inside. The resulting binary name was "__main__.exe" though, but now it is "directory.exe" .. code:: bash # ls directory __main__.py # nuitka --exe directory # ls directory directory.exe This makes this usage more obvious, and fixes an older issue for this feature. - Evaluation order of binary operators was not enforced. Nuitka already enforces evaluation order for just about everything. But not for binary operators it seems. - Providing an ``# coding: no-exist`` was crashing under Python2, and ignored under Python3, now it does the compatible thing for both. - Global statements on the compiler level are legal in Python, and were not handled by Nuitka, they now are. .. code:: python global a # Not in a function, but on module level. Pointless but legal! a = 1 Effectively these statements can be ignored. - Future imports are only legal when they are at the start of the file. This was not enforced by Nuitka, making it accept code, which CPython would reject. It now properly raises a syntax error. - Raising exceptions from context was leaking references. .. code:: python raise ValueError() from None Under CPython3.2 the above is not allowed (it is acceptable starting CPython3.3), and was also leaking references to its arguments. - Importing the module that became ``__main__`` through the module name, didn't recurse to it. This also gives a warning. PyBench does it, and then stumbles over the non-found "pybench" module. Of course, programmers should use ``sys.modules[ "__main__" ]`` to access main module code. Not only because the duplicated modules don't share data. - Compiled method ``repr`` leaked references when printed. When printing them, they would not be freed, and subsequently hold references to the object (and class) they belong to. This could trigger bugs for code that expects ``__del__`` to run at some point. - The ``super`` built-in leaked references to given object. This was added, because Python3 needs it. It supplies the arguments to ``super`` automatically, whereas for Python2 the programmer had to do it. And now it turns out that the object lost a reference, causing similar issues as above, preventing ``__del__`` to run. - The ``raise`` statement didn't enforce type of third argument. This Python2-only form of exception raising now checks the type of the third argument before using it. Plus, when it's None (which is also legal), no reference to None is leaked. - Python3 built-in exceptions were strings instead of exceptions. A gross mistake that went uncaught by test suites. I wonder how. Them being strings doesn't help their usage of course, fixed. - The ``-nan`` and ``nan`` both exist and make a difference. A older story continued. There is a sign to ``nan``, which can be copied away and should be present. This is now also supported by Nuitka. - Wrong optimization of ``a == a``, ``a != a``, ``a <= a`` on C++ level. While it's not done during Nuitka optimization, the rich comparison helpers still contained short cuts for ``==``, ``!=``, and ``<=``. - The ``sys.executable`` for ``nuitka-python --python-version 3.2`` was still ``python``. When determining the value for ``sys.executable`` the CPython library code looks at the name ``exec`` had received. It was ``python`` in all cases, but now it depends on the running version, so it propagates. - Keyword only functions with default values were losing references to defaults. .. code:: python def f(*, a=X()): pass f() f() # Can crash, X() should already be released. This is now corrected. Of course, a Python3 only issue. - Pressing CTRL-C didn't generate ``KeyboardInterrupt`` in compiled code. Nuitka never executes "pending calls". It now does, with the upside, that the solution used, appears to be suitable for threading in Nuitka too. Expect more to come out of this. - For ``with`` statements with ``return``, ``break``, or ``continue`` to leave their body, the ``__exit__`` was not called. .. code:: python with a: # This called a.__enter__(). return 2 # This didn't call a.__exit__(None, None, None). This is of course quite huge, and unfortunately wasn't covered by any test suite so far. Turns out, the re-formulation of ``with`` statements, was wrongly using ``try/except/else``, but these ignore the problematic statements. Only ``try/finally`` does. The enhanced re-formulation now does the correct thing. - Starting with Python3, absolute imports are now the default. This was already present for Python3.3, and it turns out that all of Python3 does it. Optimization ============ - Constants are now much less often created with ``pickle`` module, but created directly. This esp. applies for nested constants, now more values become ``is`` identical instead of only ``==`` identical, which indicates a reduced memory usage. .. code:: python a = ("something_special",) b = "something_special" assert a[0] is b # Now true This is not only about memory efficiency, but also about performance. Less memory usage is more cache friendly, and the "==" operator will be able to shortcut dramatically in cases of identical objects. Constants now created without ``pickle`` usage, cover ``float``, ``list``, and ``dict``, which is enough for PyStone to not use it at all, which has been added support for as well. - Continue statements might be optimized away. A terminal ``continue`` in a loop, was not optimized away: .. code:: python while 1: something continue # Now optimized away The trailing ``continue`` has no effect and can therefore be removed. .. code:: python while 1: something - Loops with only break statements are optimized away. .. code:: python while 1: break A loop immediately broken has of course no effect. Loop conditions are re-formulated to immediate "if ... : break" checks. Effectively this means that loops with conditions detected to be always false to see the loop entirely removed. New Tests ========= - Added tests for the found issues. - Running the programs test suite (i.e. recursion) for Python3.2 and Python3.2 as well, after making adaptation so that the absolute import changes are now covered. - Running the "CPython3.2" test suite with Python3.3 based Nuitka works and found a few minor issues. Organisational ============== - The `Downloads `__ page now offers RPMs for RHEL6, CentOS6, F17, F18, and openSUSE 12.1, 12.2, 12.3. This large coverage is thanks to openSUSE build service and "ownssh" for contributing an RPM spec file. The page got improved with logos for the distributions. - Added "ownssh" as contributor. - Revamped the `User Manual `__ in terms of layout, structure, and content. Summary ======= This release is the result of much validation work. The amount of fixes the largest of any release so far. New platforms, basic Python3.3 support, consolidation all around. ********************** Nuitka Release 0.4.1 ********************** This release is the first follow-up with a focus on optimization. The major highlight is progress towards SSA form in the node tree. Also a lot of cleanups have been performed, for both the tree building, which is now considered mostly finished, and will be only reviewed. And for the optimization part there have been large amounts of changes. New Features ============ - Python 3.3 experimental support - Now compiles many basic tests. Ported the dictionary quick access and update code to a more generic and useful interface. - Added support for ``__qualname__`` to classes and functions. - Small compatibility changes. Some exceptions changed, absolute imports are now default, etc. - For comparison tests, the hash randomization is disabled. - Python 3.2 support has been expanded. The Python 3.2 on Ubuntu is not providing a helper function that was used by Nuitka, replaced it with out own code. Bug fixes ========= - Default values were not "is" identical. .. code:: python def defaultKeepsIdentity(arg="str_value"): print arg is "str_value" defaultKeepsIdentity() This now prints "True" as it does with CPython. The solution is actually a general code optimization, see below. - Usage of ``unicode`` built-in with more than one argument could corrupt the encoding argument string. An implementation error of the ``unicode`` was releasing references to arguments converted to default encoding, which could corrupt it. - Assigning Python3 function annotations could cause a segmentation fault. Optimization ============ - Improved propagation of exception raise statements, eliminating more code. They are now also propagated from all kinds of expressions. Previously this was more limited. An assertion added will make sure that all raises are propagated. Also finally, raise expressions are converted into raise statements, but without any normalization. .. code:: python # Now optimizing: raise TypeError, 1 / 0 # into (minus normalization): raise ZeroDivisionError, "integer division or modulo by zero" # Now optimizing: (1 / 0).something # into (minus normalization): raise ZeroDivisionError, "integer division or modulo by zero" # Now optimizing: function(a, 1 / 0).something # into (minus normalization), notice the side effects of first checking # function and a as names to be defined, these may be removed only if # they can be demonstrated to have no effect. function a raise ZeroDivisionError, "integer division or modulo by zero" There is more examples, where the raise propagation is new, but you get the idea. - Conditional expression nodes are now optimized according to the truth value of the condition, and not only for compile time constants. This covers e.g. container creations, and other things. .. code:: python # This was already optimized, as it's a compile time constant. a if ("a",) else b a if True else b # These are now optimized, as their truth value is known. a if (c,) else b a if not (c,) else b This is simply taking advantage of infrastructure that now exists. Each node kind can overload "getTruthValue" and benefit from it. Help would be welcome to review which ones can be added. - Function creations only have side effects, when their defaults or annotations (Python3) do. This allows to remove them entirely, should they be found to be unused. - Code generation for constants now shares element values used in tuples. The general case is currently too complex to solve, but we now make sure constant tuples (as e.g. used in the default value for the compiled function), and string constants share the value. This should reduce memory usage and speed up program start-up. Cleanups ======== - Optimization was initially designed around visitors that each did one thing, and did it well. It turns out though, that this approach is unnecessary, and constraint collection, allows for the most consistent results. All remaining optimization has been merged into constraint collection. - The names of modules containing node classes were harmonized to always be plural. In the beginning, this was used to convey the information that only a single node kind would be contained, but that has long changed, and is unimportant information. - The class names of nodes were stripped from the "CPython" prefix. Originally the intent was to express strict correlation to CPython, but with increasing amounts of re-formulations, this was not used at all, and it's also not important enough to dominate the class name. - The re-formulations performed in tree building have moved out of the "Building" module, into names "ReformulationClasses" e.g., so they are easier to locate and review. Helpers for node building are now in a separate module, and generally it's much easier to find the content of interest now. - Added new re-formulation of ``print`` statements. The conversion to strings is now made explicit in the node tree. New Tests ========= - Added test to cover default value identity. Organisational ============== - The upload of `Nuitka to PyPI `__ has been repaired and now properly displays project information again. Summary ======= The quicker release is mostly a consolidation effort, without much actual performance progress. The progress towards SSA form matter a lot on the outlook front. Once this is finished, standard compiler algorithms can be added to Nuitka which go beyond the current peephole optimization. ********************** Nuitka Release 0.4.0 ********************** This release brings massive progress on all fronts. The big highlight is of course: Full Python3.2 support. With this release, the test suite of CPython3.2 is considered passing when compiled with Nuitka. Then lots of work on optimization and infrastructure. The major goal of this release was to get in shape for actual optimization. This is also why for the first time, it is tested that some things are indeed compile time optimized to spot regressions easier. And we are having performance diagrams, `even if weak ones `__: New Features ============ - Python3.2 is now fully supported. - Fully correct ``metaclass =`` semantics now correctly supported. It had been working somewhat previously, but now all the corner cases are covered too. - Keyword only parameters. - Annotations of functions return value and their arguments. - Exception causes, chaining, automatic deletion of exception handlers ``as`` values. - Added support for starred assigns. - Unicode variable names are also supported, although it's of course ugly, to find a way to translate these to C++ ones. Bug fixes ========= - Checking compiled code with ``instance(some_function, types.FunctionType)`` as "zope.interfaces" does, was causing compatibility problems. Now this kind of check passes for compiled functions too. - The frame of modules had an empty locals dictionary, which is not compatible to CPython which puts the globals dictionary there too. - For nested exceptions and interactions with generator objects, the exceptions in ``sys.exc_info()`` were not always fully compatible. They now are. - The ``range`` builtin was not raising exceptions if given arguments appeared to not have side effects, but were still illegal, e.g. ``range([], 1, -1)`` was optimized away if the value was not used. - Don't crash on imported modules with syntax errors. Instead, the attempted recursion is simply not done. - Doing a ``del`` on ``__defaults`` and ``__module__`` of compiled functions was crashing. This was noticed by a Python3 test for ``__kwdefaults__`` that exposed this compiled functions weakness. - Wasn't detecting duplicate arguments, if one of them was not a plain arguments. Star arguments could collide with normal ones. - The ``__doc__`` of classes is now only set, where it was in fact specified. Otherwise it only polluted the name space of ``locals()``. - When ``return`` from the tried statements of a ``try/finally`` block, was overridden, by the final block, a reference was leaked. Example code: .. code:: python try: return 1 finally: return 2 - Raising exception instances with value, was leaking references, and not raising the ``TypeError`` error it is supposed to do. - When raising with multiple arguments, the evaluation order of them was not enforced, it now is. This fixes a reference leak when raising exceptions, where building the exception was raising an exception. Optimization ============ - Optimizing attribute access to compile time constants for the first time. The old registry had no actual user yet. - Optimizing subscript and slices for all compile time constants beyond constant values, made easy by using inheritance. - Built-in references now convert to strings directly, e.g. when used in a print statement. Needed for the testing approach "compiled file contains only prints with constant value". - Optimizing calls to constant nodes directly into exceptions. - Optimizing built-in ``bool`` for arguments with known truth value. This would be creations of tuples, lists, and dictionaries. - Optimizing ``a is b`` and ``a is not b`` based on aliasing interface, which at this time effectively is limited to telling that ``a is a`` is true and ``a is not a`` is false, but this will expand. - Added support for optimizing ``hasattr``, ``getattr``, and ``setattr`` built-ins as well. The ``hasattr`` was needed for the ``class`` re-formulation of Python3 anyway. - Optimizing ``getattr`` with string argument and no default to simple attribute access. - Added support for optimizing ``isinstance`` built-in. - Was handling "BreakException" and "ContinueException" in all loops that used ``break`` or ``continue`` instead of only where necessary. - When catching "ReturnValueException", was raising an exception where a normal return was sufficient. Raising them now only where needed, which also means, function need not catch them ever. Cleanups ======== - The handling of classes for Python2 and Python3 have been re-formulated in Python more completely. - The calling of the determined "metaclass" is now in the node tree, so this call may possible to in-line in the future. This eliminated some static C++ code. - Passing of values into dictionary creation function is no longer using hard coded special parameters, but temporary variables can now have closure references, making this normal and visible to the optimization. - Class dictionary creation functions are therefore no longer as special as they used to be. - There is no class creation node anymore, it's merely a call to ``type`` or the metaclass detected. - Re-formulated complex calls through helper functions that process the star list and dict arguments and do merges, checks, etc. - Moves much C++ code into the node tree visibility. - Will allow optimization to eliminate checks and to compile time merge, once in-line functions and loop unrolling are supported. - Added "return None" to function bodies without a an aborting statement at the end, and removed the hard coded fallback from function templates. Makes it explicit in the node tree and available for optimization. - Merged C++ classes for frame exception keeper with frame guards. - The exception is now saved in the compiled frame object, making it potentially more compatible to start with. - Aligned module and function frame guard usage, now using the same class. - There is now a clear difference in the frame guard classes. One is for generators and one is for functions, allowing to implement their different exception behavior there. - The optimization registries for calls, subscripts, slices, and attributes have been replaced with attaching them to nodes. - The ensuing circular dependency has been resolved by more local imports for created nodes. - The package "nuitka.transform.optimization.registries" is no more. - New per node methods "computeNodeCall", "computeNodeSubscript", etc. dispatch the optimization process to the nodes directly. - Use the standard frame guard code generation for modules too. - Added a variant "once", that avoids caching of frames entirely. - The variable closure taking has been cleaned up. - Stages are now properly numbered. - Python3 only stage is not executed for Python2 anymore. - Added comments explaining things a bit better. - Now an early step done directly after building a tree. - The special code generation used for unpacking from iterators and catching "StopIteration" was cleaned up. - Now uses template, Generator functions, and proper identifiers. - The ``return`` statements in generators are now re-formulated into ``raise StopIteration`` for generators, because that's what they really are. Allowed to remove special handling of ``return`` nodes in generators. - The specialty of CPython2.6 yielding non-None values of lambda generators, was so far implemented in code generation. This was moved to tree building as a re-formulation, making it subject to normal optimization. - Mangling of attribute names in functions contained in classes, has been moved into the early tree building. So far it was done during code generation, making it invisible to the optimization stages. - Removed tags attribute from node classes. This was once intended to make up for non-inheritance of similar node kinds, but since we have function references, the structure got so clean, it's no more needed. - Introduced new package ``nuitka.tree``, where the building of node trees, and operations on them live, as well as recursion and variable closure. - Removed ``nuitka.transform`` and move its former children ``nuitka.optimization`` and ``nuitka.finalization`` one level up. The deeply nested structure turned out to have no advantage. - Checks for Python version was sometimes "> 300", where of course ">= 300" is the only thing that makes sense. - Split out helper code for exception raising from the handling of exception objects. New Tests ========= - The complete CPython3.2 test suite was adapted (no ``__code__``, no ``__closure__``, etc.) and is now passing, but only without "--debug", because otherwise some of the generated C++ triggers (harmless) warnings. - Added new test suite designed to prove that expressions that are known to be compile time constant are indeed so. This works using the XML output done with ``--dump-xml`` and then searching it to only have print statements with constant values. - Added new basic CPython3.2 test "Functions32" and "ParameterErrors32" to cover keyword only parameter handling. - Added tests to cover generator object and exception interactions. - Added tests to cover ``try/finally`` and ``return`` in one or both branches correctly handling the references. - Added tests to cover evaluation order of arguments when raising exceptions. Organisational ============== - Changed my email from GMX over to Gmail, the old one will still continue to work. Updated the copyright notices accordingly. - Uploaded `Nuitka to PyPI `__ as well. Summary ======= This release marks a milestone. The support of Python3 is here. The re-formulation of complex calls, and the code generation improvements are quite huge. More re-formulation could be done for argument parsing, but generally this is now mostly complete. The 0.3.x series had a lot releases. Many of which brought progress with re-formulations that aimed at making optimization easier or possible. Sometimes small things like making "return None" explicit. Sometimes bigger things, like making class creations normal functions, or getting rid of ``or`` and ``and``. All of this was important ground work, to make sure, that optimization doesn't deal with complex stuff. So, the 0.4.x series begins with this. The focus from now on can be almost purely optimization. This release contains already some of it, with frames being optimized away, with the assignment keepers from the ``or`` and ``and`` re-formulation being optimized away. This will be about achieving goals from the "ctypes" plan as discussed in the Developer Manual. Also the performance page will be expanded with more benchmarks and diagrams as I go forward. I have finally given up on "codespeed", and do my own diagrams. *********************** Nuitka Release 0.3.25 *********************** This release brings about changes on all fronts, bug fixes, new features. Also very importantly Nuitka no longer uses C++11 for its code, but mere C++03. There is new re-formulation work, and re-factoring of functions. But the most important part is this: Mercurial unit tests are working. Nearly. With the usual disclaimer of me being wrong, all remaining errors are errors of the test, or minor things. Hope is that these unit tests can be added as release tests to Nuitka. And once that is done, the next big Python application can come. Bug fixes ========= - Local variables were released when an exception was raised that escaped the local function. They should only be released, after another exception was raised somewhere. - Identifiers of nested tuples and lists could collide. .. code:: python a = ((1, 2), 3) b = ((1,), 2, 3) Both tuples had the same name previously, not the end of the tuple is marked too. Fixed in 0.3.24.1 already. - The ``__name__`` when used read-only in modules in packages was optimized to a string value that didn't contain the package name. - Exceptions set when entering compiled functions were unset at function exit. New Features ============ - Compiled frames support. Before, Nuitka was creating frames with the standard CPython C/API functions, and tried its best to cache them. This involved some difficulties, but as it turns out, it is actually possible to instead provide a compatible type of our own, that we have full control over. This will become the base of enhanced compatibility. Keeping references to local variables attached to exception tracebacks is something we may be able to solve now. - Enhanced Python3 support, added support for ``nonlocal`` declarations and many small corrections for it. - Writable ``__defaults__`` attribute for compiled functions, actually changes the default value used at call time. Not supported is changing the amount of default parameters. Cleanups ======== - Keep the functions along with the module and added "FunctionRef" node kind to point to them. - Reformulated ``or`` and ``and`` operators with the conditional expression construct which makes the "short-circuit" branch. - Access ``self`` in methods from the compiled function object instead of pointer to context object, making it possible to access the function object. - Removed "OverflowCheck" module and its usage, avoids one useless scan per function to determine the need for "locals dictionary". - Make "compileTree" of "MainControl" module to only do what the name says and moved the rest out, making the top level control clearer. - Don't export module entry points when building executable and not modules. These exports cause MinGW and MSVC compilers to create export libraries. Optimization ============ - More efficient code for conditional expressions in conditions: .. code:: python if a if b else c: ... See above, this code is now the typical pattern for each ``or`` and ``and``, so this was much needed now. Organisational ============== - The remaining uses of C++11 have been removed. Code generated with Nuitka and complementary C++ code now compile with standard C++03 compilers. This lowers the Nuitka requirements and enables at least g++ 4.4 to work with Nuitka. - The usages of the GNU extension operation ``a ?: b`` have replaced with standard C++ constructs. This is needed to support MSVC which doesn't have this. - Added examples for the typical use cases to the `User Manual `__. - The "compare_with_cpython" script has gained an option to immediately remove the Nuitka outputs (build directory and binary) if successful. Also the temporary files are now put under "/var/tmp" if available. - Debian package improvements, registering with ``doc-base`` the `User Manual `__ so it is easier to discover. Also suggest ``mingw32`` package which provides the cross compiler to Windows. - Partial support for MSVC (Visual Studio 2008 to be exact, the version that works with CPython2.6 and CPython2.7). All basic tests that do not use generators are working now, but those will currently cause crashes. - Renamed the ``--g++-only`` option to ``--c++-only``. The old name is no longer correct after clang and MSVC have gained support, and it could be misunderstood to influence compiler selection, rather than causing the C++ source code to not be updated, so manual changes will the used. - Catch exceptions for ``continue``, ``break``, and ``return`` only where needed for ``try``/``finally`` and loop constructs. New Tests ========= - Added CPython3.2 test suite as "tests/CPython32" from 3.2.3 and run it with CPython2.7 to check that Nuitka gives compatible error messages. It is not expected to pass yet on Python3.2, but work will be done towards this goal. - Make CPython2.7 test suite runner also execute the generated "doctest" modules. - Enabled tests for default parameters and their reference counts. Summary ======= This release marks an important point. The compiled frames are exciting new technology, that will allow even better integration with CPython, while improving speed. Lowering the requirements to C++03 means, we will become usable on Android and with MSVC, which will make adoption of Nuitka on Windows easier for many. Structurally the outstanding part is the function as references cleanup. This was a blocker for value propagation, because now functions references can be copied, whereas previously this was duplicating the whole function body, which didn't work, and wasn't acceptable. Now, work can resume in this domain. Also very exciting when it comes to optimization is the remove of special code for ``or`` and ``and`` operators, as these are now only mere conditional expressions. Again, this will make value propagation easier with two special cases less. And then of course, with Mercurial unit tests running compiled with Nuitka, an important milestone has been hit. For a while now, the focus will be on completing Python3 support, XML based optimization regression tests, benchmarks, and other open ends. Once that is done, and more certainty about Mercurial tests support, I may call it a 0.4 and start with local type inference for actual speed gains. *********************** Nuitka Release 0.3.24 *********************** This release contains progress on many fronts, except performance. The extended coverage from running the CPython 2.7 and CPython 3.2 (partially) test suites shows in a couple of bug fixes and general improvements in compatibility. Then there is a promised new feature that allows to compile whole packages. Also there is more Python3 compatibility, the CPython 3.2 test suite now succeeds up to "test_builtin.py", where it finds that ``str`` doesn't support the new parameters it has gained, future releases will improve on this. And then of course, more re-formulation work, in this case, class definitions are now mere simple functions. This and later function references, is the important and only progress towards type inference. Bug fixes ========= - The compiled method type can now be used with ``copy`` module. That means, instances with methods can now be copied too. Fixed in 0.3.23.1 already. - The ``assert`` statement as of Python2.7 creates the ``AssertionError`` object from a given value immediately, instead of delayed as it was with Python2.6. This makes a difference for the form with 2 arguments, and if the value is a tuple. Fixed in 0.3.23.1 already. - Sets written like this didn't work unless they were predicted at compile time: .. code:: python {value} This apparently rarely used Python2.7 syntax didn't have code generation yet and crashed the compiler. Fixed in 0.3.23.1 already. - For Python2, the default encoding for source files is ``ascii``, and it is now enforced by Nuitka as well, with the same ``SyntaxError``. - Corner cases of ``exec`` statements with nested functions now give proper ``SyntaxError`` exceptions under Python2. - The ``exec`` statement with a tuple of length 1 as argument, now also gives a ``TypeError`` exception under Python2. - For Python2, the ``del`` of a closure variable is a ``SyntaxError``. New Features ============ - Added support creating compiled packages. If you give Nuitka a directory with an "__init__.py" file, it will compile that package into a ".so" file. Adding the package contents with ``--recurse-dir`` allows to compile complete packages now. Later there will be a cleaner interface likely, where the later is automatic. - Added support for providing directories as main programs. It's OK if they contain a "__main__.py" file, then it's used instead, otherwise give compatible error message. - Added support for optimizing the ``super`` built-in. It was already working correctly, but not optimized on CPython2. But for CPython3, the variant without any arguments required dedicated code. - Added support for optimizing the ``unicode`` built-in under Python2. It was already working, but will become the basis for the ``str`` built-in of Python3 in future releases. - For Python3, lots of compatibility work has been done. The Unicode issues appear to be ironed out now. The ``del`` of closure variables is allowed and supported now. Built-ins like ``ord`` and ``chr`` work more correctly and attributes are now interned strings, so that monkey patching classes works. Organisational ============== - Migrated "bin/benchmark.sh" to Python as "misc/run-valgrind.py" and made it a bit more portable that way. Prefers "/var/tmp" if it exists and creates temporary files in a secure manner. Triggered by the Debian "insecure temp file" bug. - Migrated "bin/make-dependency-graph.sh" to Python as "misc/make-dependency-graph.py" and made a more portable and powerful that way. The filtering is done a more robust way. Also it creates temporary files in a secure manner, also triggered by the Debian "insecure temp file" bug. And it creates SVG files and no longer PostScript as the first one is more easily rendered these days. - Removed the "misc/gist" git sub-module, which was previously used by "misc/make-doc.py" to generate HTML from `User Manual `__ and `Developer Manual `__. These are now done with Nikola, which is much better at it and it integrates with the web site. - Lots of formatting improvements to the change log, and manuals: - Marking identifiers with better suited ReStructured Text markup. - Added links to the bug tracker all Issues. - Unified wordings, quotation, across the documents. Cleanups ======== - The creation of the class dictionaries is now done with normal function bodies, that only needed to learn how to throw an exception when directly called, instead of returning ``NULL``. Also the assignment of ``__module__`` and ``__doc__`` in these has become visible in the node tree, allowing their proper optimization. These re-formulation changes allowed to remove all sorts of special treatment of ``class`` code in the code generation phase, making things a lot simpler. - There was still a declaration of ``PRINT_ITEMS`` and uses of it, but no definition of it. - Code generation for "main" module and "other" modules are now merged, and no longer special. - The use of raw strings was found unnecessary and potentially still buggy and has been removed. The dependence on C++11 is getting less and less. New Tests ========= - Updated CPython2.6 test suite "tests/CPython26" to 2.6.8, adding tests for recent bug fixes in CPython. No changes to Nuitka were needed in order to pass, which is always good news. - Added CPython2.7 test suite as "tests/CPython27" from 2.7.3, making it public for the first time. Previously a private copy of some age, with many no longer needed changes had been used by me. Now it is up to par with what was done before for "tests/CPython26", so this pending action is finally done. - Added test to cover Python2 syntax error of having a function with closure variables nested inside a function that is an overflow function. - Added test "BuiltinSuper" to cover ``super`` usage details. - Added test to cover ``del`` on nested scope as syntax error. - Added test to cover ``exec`` with a tuple argument of length 1. - Added test to cover ``barry_as_FLUFL`` future import to work. - Removed "Unicode" from known error cases for CPython3.2, it's now working. Summary ======= This release brought forward the most important remaining re-formulation changes needed for Nuitka. Removing class bodies, makes optimization yet again simpler. Still, making function references, so they can be copied, is missing for value propagation to progress. Generally, as usual, a focus has been laid on correctness. This is also the first time, I am release with a known bug though, one which I believe now, may be the root cause of the mercurial tests not yet passing. The solution will be involved and take a bit of time. It will be about "compiled frames" and be a (invasive) solution. It likely will make Nuitka faster too. But this release includes lots of tiny improvements, for Python3 and also for Python2. So I wanted to get this out now. As usual, please check it out, and let me know how you fare. *********************** Nuitka Release 0.3.23 *********************** This release is the one that completes the Nuitka "sun rise phase". All of Nuitka is now released under `Apache License 2.0 `__ which is a very liberal license, and compatible with basically all Free Software licenses there are. It's only asking to allow integration, of what you send back, and patent grants for the code. In the first phase of Nuitka development, I wanted to keep control over Nuitka, so it wouldn't repeat mistakes of other projects. This is no longer a concern for me, it's not going to happen anymore. I would like to thank Debian Legal team, for originally bringing to my attention, that this license will be better suited, than any copyright assignment could be. Bug fixes ========= - The compiled functions could not be used with ``multiprocessing`` or ``copy.copy``. Fixed in 0.3.22.1 already. - In-place operations for slices with not both bounds specified crashed the compiler. Fixed in 0.3.22.1 already. - Cyclic imports could trigger an endless loop, because module import expressions became the parent of the imported module object. Fixed in 0.3.22.2 already. - Modules named ``proc`` or ``func`` could not be compiled to modules or embedded due to a collision with identifiers of CPython2.7 includes. Fixed in 0.3.22.2 already. New Features ============ - The function copying fix also makes pickling of compiled functions available. As it is the case for non-compiled functions in CPython, no code objects are stored, only names of module level variables. Organisational ============== - Using the Apache License 2.0 for all of Nuitka now. - Speedcenter has been re-activated, but is not yet having a lot of benchmarks yet, subject to change. .. admonition:: Update We have given up on this version of speedcenter meanwhile, and generate static pages with graphs instead. We can this still speedcenter. New Tests ========= - Changed the "CPython26" tests to no longer disable the parts that relied on copying of functions to work as that is now supported. - Extended in-place assignment tests to cover error cases of we had issues with. - Extended compile library test to also try and compile the path where ``numpy`` lives. This is apparently another path, where Debian installs some modules, and compiling this would have revealed issues sooner. Summary ======= The release contains bug fixes, and the huge step of changing `the license `__. It is made in preparation to `PyCON EU `__. *********************** Nuitka Release 0.3.22 *********************** This release is a continuation of the trend of previous releases, and added more re-formulations of Python that lower the burden on code generation and optimization. It also improves Python3 support substantially. In fact this is the first release to not only run itself under Python3, but for Nuitka to *compile itself* with Nuitka under Python3, which previously only worked for Python2. For the common language subset, it's quite fine now. Bug fixes ========= - List contractions produced extra entries on the call stack, after they became functions, these are no more existent. That was made possible my making frame stack entries an optional element in the node tree, left out for list contractions. - Calling a compiled function in an exception handler cleared the exception on return, it no longer does that. - Reference counter handling with generator ``throw`` method is now correct. - A module "builtins" conflicted with the handling of the Python ``builtins`` module. Those now use different identifiers. New Features ============ - New ``metaclass`` syntax for the ``class`` statement works, and the old ``__metaclass__`` attribute is properly ignored. .. code:: python # Metaclass syntax in Python3, illegal in Python2 class X(metaclass=Y): pass .. code:: python # Metaclass syntax in Python2, no effect in Python3 class X: __metaclass__ = Y .. note:: The way to make a use of a metaclass in a portable way, is to create a based class that has it and then inherit from it. Sad, isn' it. Surely, the support for ``__metaclass__`` could still live. .. code:: python # For Python2/3 compatible source, we create a base class that has the # metaclass used and doesn't require making a choice. CPythonNodeMetaClassBase = NodeCheckMetaClass("CPythonNodeMetaClassBase", (object,), {}) - The ``--dump-xml`` option works with Nuitka running under Python3. This was not previously supported. - Python3 now also has compatible parameter errors and compatible exception error messages. - Python3 has changed scope rules for list contractions (assignments don't affect outside values) and this is now respected as well. - Python3 has gained support for recursive programs and stand alone extension modules, these are now both possible as well. Optimization ============ - Avoid frame stack entries for functions that cannot raise exceptions, i.e. where they would not be used. This avoids overhead for the very simple functions. And example of this can be seen here: .. code:: python def simple(): return 7 - Optimize ``len`` built-in for non-constant, but known length values. An example can be seen here: .. code:: python # The range isn't constructed at compile time, but we still know its # length. len(range(10000000)) # The string isn't constructed at compile time, but we still know its # length. len("*" * 1000) # The tuple isn't constructed, instead it's known length is used, and # side effects are maintained. len((a(), b())) This new optimization applies to all kinds of container creations and the ``range`` built-in initially. - Optimize conditions for non-constant, but known truth values. At this time, known truth values of non-constants means ``range`` built-in calls with know size and container creations. An example can be seen here: .. code:: python if (a,): print "In Branch" It's clear, that the tuple will be true, we just need to maintain the side effect, which we do. - Optimize ``or`` and ``and`` operators for known truth values. See above for what has known truth values currently. This will be most useful to predict conditions that need not be evaluated at all due to short circuit nature, and to avoid checking against constant values. Previously this could not be optimized, but now it can: .. code:: python # The access and call to "something()" cannot possibly happen 0 and something() # Can be replaced with "something()", as "1" is true. If it had a side # effect, it would be maintained. 1 and something() # The access and call to "something()" cannot possibly happen, the value # is already decided, it's "1". 1 or something() # Can be replaced with "something()", as "0" is false. If it had a side # effect, it would be maintained. 0 or something() - Optimize print arguments to become strings. The arguments to ``print`` statements are now converted to strings at compile time if possible. .. code:: python print 1 becomes: .. code:: python print "1" - Combine print arguments to single ones. When multiple strings are printed, these are now combined. .. code:: python print "1+1=", 1 + 1 becomes: .. code:: python print "1+1= 2" Organisational ============== - Enhanced Python3 support, enabling support for most basic tests. - Check files with PyLint in deterministic (alphabetical) order. Cleanups ======== - Frame stack entries are now part of the node tree instead of part of the template for every function, generator, class or module. - The ``try``/``except``/``else`` has been re-formulated to use an indicator variable visible in the node tree, that tells if a handler has been executed or not. - Side effects are now a dedicated node, used in several optimization to maintain the effect of an expression with known value. New Tests ========= - Expanded and adapted basic tests to work for Python3 as well. - Added reference count tests for generator functions ``throw``, ``send``, and ``close`` methods. - Cover calling a function with ``try``/``except`` in an exception handler twice. No test was previously doing that. Summary ======= This release offers enhanced compatibility with Python3, as well as the solution to many structural problems. Calculating lengths of large non-constant values at compile time, is technically a break through, as is avoiding lengthy calculations. The frame guards as nodes is a huge improvement, making that costly operational possible to be optimized away. There still is more work ahead, before value propagation will be safe enough to enable, but we are seeing the glimpse of it already. Not for long, and looking at numbers will make sense. *********************** Nuitka Release 0.3.21 *********************** This releases contains some really major enhancements, all heading towards enabling value propagation inside Nuitka. Assignments of all forms are now all simple and explicit, and as a result, now it will be easy to start tracking them. Contractions have become functions internally, with statements use temporary variables, complex unpacking statement were reduced to more simple ones, etc. Also there are the usual few small bug fixes, and a bunch of organisational improvements, that make the release complete. Bug fixes ========= - The built-in ``next`` could causes a program crash when iterating past the end of an iterator. Fixed in 0.3.20.1 already. - The ``set`` constants could cause a compiler error, as that type was not considered in the "mutable" check yet. Fixed in 0.3.20.2 already. - Performance regression. Optimize expression for exception types caught as well again, this was lost in last release. - Functions that contain ``exec``, are supposed to have a writable locals. But when removing that ``exec`` statement as part of optimization, this property of the function could get lost. - The so called "overflow functions" are once again correctly handled. These once were left behind in some refactoring and had not been repaired until now. An overflow function is a nested function with an ``exec`` or a star import. - The syntax error for ``return`` outside of a function, was not given, instead the code returned at run time. Fixed to raise a ``SyntaxError`` at compile time. Optimization ============ - Avoid ``tuple`` objects to be created when catching multiple exception types, instead call exception match check function multiple times. - Removal of dead code following ``break``, ``continue``, ``return``, and ``raise``. Code that follows these statements, or conditional statements, where all branches end with it. .. note:: These may not actually occur often in actual code, but future optimization may produce them more frequently, and their removal may in turn make other possible optimization. - Detect module variables as "read only" after all writes have been detected to not be executed as removed. Previously the "read only indicator" was determined only once and then stayed the same. - Expanded conditional statement optimization to detect cases, where condition is a compile time constant, not just a constant value. - Optimize away assignments from a variable to the same variable, they have no effect. The potential side effect of accessing the variable is left intact though, so exceptions will be raised still. .. note:: An exception is where ``len = len`` actually does have an impact, because that variable becomes assignable. The "compile itself" test of Nuitka found that to happen with ``long`` from the ``nuitka.__past__`` module. - Created Python3 variant of quick ``unicode`` string access, there was no such thing in the CPython C/API, but we make the distinction in the source code, so it makes sense to have it. - Created an optimized implementation for the built-in ``iter`` with 2 parameters as well. This allows for slightly more efficient code to be created with regards to reference handling, rather than using the CPython C/API. - For all types of variable assigned in the generated code, there are now methods that accept already taken references or not, and the code generator picks the optimal variant. This avoids the drop of references, that e.g. the local variable will insist to take. - Don't use a "context" object for generator functions (and generator expressions) that don't need one. And even if it does to store e.g. the given parameter values, avoid to have a "common context" if there is no closure taken. This avoids useless ``malloc`` calls and speeds up repeated generator object creation. Organisational ============== - Changed the Scons build file database to reside in the build directory as opposed to the current directory, not polluting it anymore. Thanks for the patch go to Michael H Kent, very much appreciated. - The ``--experimental`` option is no longer available outside of checkouts of git, and even there not on stable branches (``master``, ``hotfix/...``). It only pollutes ``--help`` output as stable releases have no experimental code options, not even development version will make a difference. - The binary "bin/Nuitka.py" has been removed from the git repository. It was deprecated a while ago, not part of the distribution and served no good use, as it was a symbolic link only anyway. - The ``--python-version`` option is applied at Nuitka start time to re-launch Nuitka with the given Python version, to make sure that the Python run time used for computations and link time Python versions are the same. The allowed values are now checked (2.6, 2.7 and 3.2) and the user gets a nice error with wrong values. - Added ``--keep-pythonpath`` alias for ``--execute-with-pythonpath`` option, probably easier to remember. - Support ``--debug`` with clang, so it can also be used to check the generated code for all warnings, and perform assertions. Didn't report anything new. - The contents environment variable ``CXX`` determines the default C++ compiler when set, so that checking with ``CXX=g++-4.7 nuitka-python ...`` has become supported. - The ``check-with-pylint`` script now has a real command line option to control the display of ``TODO`` items. Cleanups ======== - Changed complex assignments, i.e. assignments with multiple targets to such using a temporary variable and multiple simple assignments instead. .. code:: python a = b = c .. code:: python _tmp = c b = _tmp a = _tmp In CPython, when one assignment raises an exception, the whole thing is aborted, so the complexity of having multiple targets is no more needed, now that we have temporary variables in a block. All that was really needed, was to evaluate the complete source expression only once, but that made code generation contain ugly loops that are no more needed. - Changed unpacking assignments to use temporary variables. Code like this: .. code:: python a, b = c Is handled more like this: .. code:: python _tmp_iter = iter(c) _tmp1 = next(_tmp_iter) _tmp2 = next(_tmp_iter) if not finished(_tmp_iter): raise ValueError("too many values to unpack") a = _tmp1 b = _tmp2 In reality, not really ``next`` is used, as it wouldn't raise the correct exception for unpacking, and the ``finished`` check is more condensed into it. Generally this cleanup allowed that the ``AssignTargetTuple`` and associated code generation was removed, and in the future value propagation may optimize these ``next`` and ``iter`` calls away where possible. At this time, this is not done yet. - Exception handlers assign caught exception value through assignment statement. Previously the code generated for assigning from the caught exception was not considered part of the handler. It now is the first statement of an exception handler or not present, this way it may be optimized as well. - Exception handlers now explicitly catch more than one type. Catching multiple types worked by merits of the created tuple object working with the Python C/API function called, but that was not explicit at all. Now every handler has a tuple of exceptions it catches, which may only be one, or if None, it's all. - Contractions are now functions as well. Contractions (list, dict, and set) are now re-formulated as function bodies that contain for loops and conditional statements. This allowed to remove a lot of special code that dealt with them and will make these easier to understand for optimization and value propagation. - Global is handled during tree building. Previously the global statement was its own node, which got removed during the optimization phase in a dedicated early optimization that applied its effect, and then removed the node. It was determined, that there is no reason to not immediately apply the effect of the global variable and take closure variables and add them to the provider of that ``global`` statement, allowing to remove the node class. - Read only module variable detection integrated to constraint collection. The detection of read only module variables was so far done as a separate step, which is no more necessary as the constraint collection tracks the usages of module variables anyway, so this separate and slow step could be removed. New Tests ========= - Added test to cover order of calls for complex assignments that unpack, to see that they make a fresh iterator for each part of a complex assignment. - Added test that unpacks in an exception catch. It worked, due to the generic handling of assignment targets by Nuitka, and I didn't even know it can be done, example: .. code:: python try: raise ValueError(1, 2) except ValueError as (a, b): print "Unpacking caught exception and unpacked", a, b Will assign ``a=1`` and ``b=2``. - Added test to cover return statements on module level and class level, they both must give syntax errors. - Cover exceptions from accessing unassigned global names. - Added syntax test to show that star imports do not allow other names to be imported at the same time as well. - Python3 is now also running the compile itself test successfully. Summary ======= The progress made towards value propagation and type inference is *very* significant, and makes those appears as if they are achievable. *********************** Nuitka Release 0.3.20 *********************** This time there are a few bug fixes and some really major cleanups, lots of new optimization and preparations for more. And then there is a new compiler clang and a new platform supported. macOS X appears to work mostly, thanks for the patches from Pete Hunt. Bug fixes ========= - The use of a local variable name as an expression was not covered and lead to a compiler crash. Totally amazing, but true, nothing in the test suite of CPython covered this. Fixed in release 0.3.19.1 already. - The use of a closure variable name as an expression was not covered as well. And in this case corrupted the reference count. Fixed in release 0.3.19.1 already. - The ``from x import *`` attempted to respect ``__all__`` but failed to do so. Fixed in release 0.3.19.2 already. - The ``from x import *`` didn't give a ``SyntaxError`` when used on Python3. Fixed in release 0.3.19.2 already. - The syntax error messages for "global for function argument name" and "duplicate function argument name" are now identical as well. - Parameter values of generator function could cause compilation errors when used in the closure of list contractions. Fixed. New Features ============ - Added support for disabling the console for Windows binaries. Thanks for the patch go to Michael H Kent. - Enhanced Python3 support for syntax errors, these are now also compatible. - Support for macOS X was added. - Support for using the clang compiler was added, it can be enforced via ``--clang`` option. Currently this option is mainly intended to allow testing the "macOS X" support as good as possible under Linux. Optimization ============ - Enhanced all optimization that previously worked on "constants" to work on "compile time constants" instead. A "compile time constant" can currently also be any form of a built-in name or exception reference. It is intended to expand this in the future. - Added support for built-ins ``bin``, ``oct``, and ``hex``, which also can be computed at compile time, if their arguments are compile time constant. - Added support for the ``iter`` built-in in both forms, one and two arguments. These cannot be computed at compile time, but now will execute faster. - Added support for the ``next`` built-in, also in its both forms, one and two arguments. These also cannot be computed at compile time, but now will execute faster as well. - Added support for the ``open`` built-in in all its form. We intend for future releases to be able to track file opens for including them into the executable if data files. - Optimize the ``__debug__`` built-in constant as well. It cannot be assigned, yet code can determine a mode of operation from it, and apparently some code does. When compiling the mode is decided. - Optimize the ``Ellipsis`` built-in constant as well. It falls in the same category as ``True``, ``False``, ``None``, i.e. names of built-in constants that a singletons. - Added support for anonymous built-in references, i.e. built-ins which have names that are not normally accessible. An example is ``type(None)`` which is not accessible from anywhere. Other examples of such names are ``compiled_method_or_function``. Having these as represented internally, and flagged as "compile time constants", allows the compiler to make more compile time optimization and to generate more efficient C++ code for it that won't e.g. call the ``type`` built-in with ``None`` as an argument. - All built-in names used in the program are now converted to "built-in name references" in a first step. Unsupported built-ins like e.g. ``zip``, for which Nuitka has no own code or understanding yet, remained as "module variables", which made access to them slow, and difficult to recognize. - Added optimization for module attributes ``__file__``, ``__doc__`` and ``__package__`` if they are read only. It's the same as was done for ``__name__`` so far only. - Added optimization for slices and subscripts of "compile time constant" values. These will play a more important role, once value propagation makes them more frequent. Organisational ============== - Created a "change log" from the previous release announcements. It's as ReStructured Text and converted to PDF for the release as well, but I chose not to include that in Debian, because it's so easy to generate the PDF on that yourself. - The posting of release announcements is now prepared by a script that converts the ReStructured Text to HTML and adds it to Wordpress as a draft posting or updates it, until it's release time. Simple, sweet and elegant. Cleanups ======== - Split out the ``nuitka.nodes.Nodes`` module into many topic nodes, so that there are now ``nuitka.nodes.BoolNodes`` or ``nuitka.nodes.LoopNodes`` to host nodes of similar kinds, so that it is now cleaner. - Split ``del`` statements into their own node kind, and use much simpler node structures for them. The following blocks are absolutely the same: .. code:: python del a, b.c, d .. code:: python del a del b.c del d So that's now represented in the node tree. And even more complex looking cases, like this one, also the same: .. code:: python del a, (b.c, d) This one gives a different parse tree, but the same bytecode. And so Nuitka need no longer concern itself with this at all, and can remove the tuple from the parse tree immediately. That makes them easy to handle. As you may have noted already, it also means, there is no way to enforce that two things are deleted or none at all. - Turned the function and class builder statements into mere assignment statements, where defaults and base classes are handled by wrapping expressions. Previously they are also kind of assignment statements too, which is not needed. Now they were reduced to only handle the ``bases`` for classes and the ``defaults`` for functions and make optional. - Refactored the decorator handling to the tree building stage, presenting them as function calls on "function body expression" or class body expression". This allowed to remove the special code for decorators from code generation and C++ templates, making decorations easy subjects for future optimization, as they practically are now just function calls. .. code:: python @some_classdecorator class C: @staticmethod def f(): pass It's just a different form of writing things. Nothing requires the implementation of decorators, it's just functions calls with function bodies before the assignment. The following is only similar: .. code:: python class C: def f(): pass f = staticmethod(f) C = some_classdecorator(C) It's only similar, because the assignment to an intermediate value of ``C`` and ``f`` is not done, and if an exception was raised by the decoration, that name could persist. For Nuitka, the function and class body, before having a name, are an expression, and so can of course be passed to decorators already. - The in-place assignments statements are now handled using temporary variable blocks Adding support for scoped temporary variables and references to them, it was possible to re-formulate in-place assignments expressions as normal look-ups, in-place operation call and then assignment statement. This allowed to remove static templates and will yield even better generated code in the future. - The for loop used to have has a "source" expression as child, and the iterator over it was only taken at the code generation level, so that step was therefore invisible to optimization. Moved it to tree building stage instead, where optimization can work on it then. - Tree building now generally allows statement sequences to be ``None`` everywhere, and pass statements are immediately eliminated from them immediately. Empty statement sequences are now forbidden to exist. - Moved the optimization for ``__name__`` to compute node of variable references, where it doesn't need anything complex to replace with the constant value if it's only read. - Added new bases classes and mix-in classes dedicated to expressions, giving a place for some defaults. - Made the built-in code more reusable. New Tests ========= - Added some more diagnostic tests about complex assignment and ``del`` statements. - Added syntax test for star import on function level, that must fail on Python3. - Added syntax test for duplicate argument name. - Added syntax test for global on a function argument name. Summary ======= The decorator and building changes, the assignment changes, and the node cleanups are all very important progress for the type inference work, because they remove special casing the that previously would have been required. Lambdas and functions now really are the same thing right after tree building. The in-place assignments are now merely done using standard assignment code, the built functions and classes are now assigned to names in assignment statements, much *more* consistency there. Yet, even more work will be needed in the same direction. There may e.g. be work required to cover ``with`` statements as well. And assignments will become no more complex than unpacking from a temporary variable. For this release, there is only minimal progress on the Python3 front, despite the syntax support, which is only minuscule progress. The remaining tasks appear all more or less difficult work that I don't want to touch now. There are still remaining steps, but we can foresee that a release may be done that finally actually does type inference and becomes the effective Python compiler this project is all about. *********************** Nuitka Release 0.3.19 *********************** This time there are a few bug fixes, major cleanups, more Python3 support, and even new features. A lot things in this are justifying a new release. Bug fixes ========= - The man pages of ``nuitka`` and ``nuitka-python`` had no special layout for the option groups and broken whitespace for ``--recurse-to`` option. Also ``--g++-only`` was only partially bold. Released as 0.3.18.1 hot fix already. - The command line length improvement we made to Scons for Windows was not portable to Python2.6. Released as 0.3.18.2 hot fix already. - Code to detect already considered packages detection was not portable to Windows, for one case, there was still a use of ``/`` instead of using a ``joinpath`` call. Released as 0.3.18.3 already. - A call to the range built-in with no arguments would crash the compiler, see Released as 0.3.18.4 already. - Compatibility Fix: When rich comparison operators returned false value other ``False``, for comparison chains, these would not be used, but ``False`` instead, see . - The support for ``__import__`` didn't cover keyword arguments, these were simply ignored. Fixed, but no warning is given yet. New Features ============ - A new option has been added, one can now specify ``--recurse-directory`` and Nuitka will attempt to embed these modules even if not obviously imported. This is not yet working perfect yet, but will receive future improvements. - Added support for the ``exec`` built-in of Python3, this enables us to run one more basic test, ``GlobalStatement.py`` with Python3. The test ``ExecEval.py`` nearly works now. Optimization ============ - The no arguments ``range()`` call now optimized into the static CPython exception it raises. - Parts of comparison chains with constant arguments are now optimized away. Cleanups ======== - Simplified the ``CPythonExpressionComparison`` node, it now always has only 2 operands. If there are more, the so called "comparison chain", it's done via ``and`` with assignments to temporary variables, which are expressed by a new node type ``CPythonExpressionTempVariableRef``. This allowed to remove ``expression_temps`` from C++ code templates and generation, reducing the overall complexity. - When executing a module (``--execute`` but not ``--exe``), no longer does Nuitka import it into itself, instead a new interpreter is launched with a fresh environment. - The calls to the variadic ``MAKE_TUPLE`` were replaced with calls the ``MAKE_TUPLExx`` (where ``xx`` is the number of arguments), that are generated on a as-needed basis. This gives more readable code, because no ``EVAL_ORDERED_xx`` is needed at call site anymore. - Many node classes have moved to new modules in ``nuitka.nodes`` and grouped by theme. That makes them more accessible. - The choosing of the debug python has moved from Scons to Nuitka itself. That way it can respect the ``sys.abiflags`` and works with Python3. - The replacing of ``.py`` in filenames was made more robust. No longer is ``str.replace`` used, but instead proper means to assure that having ``.py`` as other parts of the filenames won't be a trouble. - Module recursion was changed into its own module, instead of being hidden in the optimization that considers import statements. - As always, some PyLint work, and some minor ``TODO`` were solved. Organisational ============== - Added more information to the `Developer Manual `__, e.g. documenting the tree changes for ``assert`` to become a conditional statement with a raise statement, etc. - The Debian package is as of this version verified to be installable and functional on to Ubuntu Natty, Maverick, Oneiric, and Precise. - Added support to specify the binary under test with a ``NUITKA`` environment, so the test framework can run with installed version of Nuitka too. - Made sure the test runners work under Windows as well. Required making them more portable. And a workaround for ``os.execl`` not propagating exit codes under Windows. - For windows target the MinGW library is now linked statically. That means there is no requirement for MinGW to be in the ``PATH`` or even installed to execute the binary. New Tests ========= - The ``basic``, ``programs``, ``syntax``, and ``reflected`` were made executable under Windows. Occasionally this meant to make the test runners more portable, or to work around limitations. - Added test to cover return values of rich comparisons in comparison chains, and order of argument evaluation for comparison chains. - The ``Referencing.py`` test was made portable to Python3. - Cover no arguments ``range()`` exception as well. - Added test to demonstrate that ``--recurse-directory`` actually works. This is using an ``__import__`` that cannot be predicted at run time (yet). - The created source package is now tested on pbuilder chroots to be pass installation and the basic tests, in addition to the full tests during package build time on these chroots. This will make sure, that Nuitka works fine on Ubuntu Natty and doesn't break without notice. Summary ======= This releases contains many changes. The "temporary variable ref" and "assignment expression" work is ground breaking. I foresee that it will lead to even more simplifications of code generation in the future, when e.g. in-place assignments can be reduced to assignments to temporary variables and conditional statements. While there were many improvements related to Windows support and fixing portability bugs, or the Debian package, the real focus is the optimization work, which will ultimately end with "value propagation" working. These are the real focus. The old comparison chain handling was a big wart. Working, but no way understood by any form of analysis in Nuitka. Now they have a structure which makes their code generation based on semantics and allows for future optimization to see through them. Going down this route is an important preparatory step. And there will be more work like this needed. Consider e.g. handling of in-place assignments. With an "assignment expression" to a "temporary variable ref", these become the same as user code using such a variable. There will be more of these to find. So, that is where the focus is. The release now was mostly aiming at getting involved fixes out. The bug fixed by comparison chain reworking, and the ``__import__`` related one, were not suitable for hot fix releases, so that is why the 0.3.19 release had to occur now. But with plugin support, with this comparison chain cleanup, with improved Python3 support, and so on, there was plenty of good stuff already, also worth to get out. *********************** Nuitka Release 0.3.18 *********************** This is to inform you about the new stable release of Nuitka. This time there are a few bug fixes, and the important step that triggered the release: Nuitka has entered Debian Unstable. So you if want, you will get stable Nuitka releases from now on via ``apt-get install nuitka``. The release cycle was too short to have much focus. It merely includes fixes, which were available as hot fixes, and some additional optimization and node tree cleanups, as well as source cleanups. But not much else. Bug fixes ========= - Conditional statements with both branches empty were not optimized away in all cases, triggering an assertion of code generation. Released as 0.3.17a hot fix already. - Nuitka was considering directories to contain packages that had no "__init__.py" which could lead to errors when it couldn't find the package later in the compilation process. Released as 0.3.17a hot fix already. - When providing ``locals()`` to ``exec`` statements, this was not making the ``locals()`` writable. The logic to detect the case that default value is used (``None``) and be pessimistic about it, didn't consider the actual value ``locals()``. Released as 0.3.17b hot fix already. - Compatibility Fix: When no defaults are given, CPython uses ``None`` for ``func.func_defaults``, but Nuitka had been using ``None``. Optimization ============ - If the condition of assert statements can be predicted, these are now optimized in a static raise or removed. - For built-in name references, there is now dedicated code to look them up, that doesn't check the module level at all. Currently these are used in only a few cases though. - Cleaner code is generated for the simple case of ``print`` statements. This is not only faster code, it's also more readable. Cleanups ======== - Removed the ``CPythonStatementAssert`` node. It's not needed, instead at tree building, assert statements are converted to conditional statements with the asserted condition result inverted and a raise statement with ``AssertionError`` and the assertion argument. This allowed to remove code and complexity from the subsequent steps of Nuitka, and enabled existing optimization to work on assert statements as well. - Moved built-in exception names and built-in names to a new module ``nuitka.Builtins`` instead of having in other places. This was previously a bit spread-out and misplaced. - Added cumulative ``tags`` to node classes for use in checks. Use it annotate which node kinds to visit in e.g. per scope finalization steps. That avoids kinds and class checks. - New node for built-in name lookups This allowed to remove tricks played with adding module variable lookups for ``staticmethod`` when adding them for ``__new__`` or module variable lookups for ``str`` when predicting the result of ``type('a')``, which was unlikely to cause a problem, but an important ``TODO`` item still. Organisational ============== - The `"Download" `__ page is now finally updated for releases automatically. Up to this release, I had to manually edit that page, but now mastered the art of upload via XMLRCP and a Python script, so that don't loose as much time with editing, checking it, etc. - The Debian package is backportable to Ubuntu Natty, Maverick, Oneiric, I expect to make a separate announcement with links to packages. - Made sure the test runners worth with bare ``python2.6`` as well. New Tests ========= - Added some tests intended for type inference development. Summary ======= This releases contains not as much changes as others, mostly because it's the intended base for a Debian upload. The ``exec`` fix was detected by continued work on the branch ``feature/minimize_CPython26_tests_diff`` branch, but that work is now complete. It is being made pretty (many git rebase iterations) with lots of Issues being added to the bug tracker and referenced for each change. The intention is to have a clean commits repository with the changed made. But of course, the real excitement is the "type inference" work. It will give a huge boost to Nuitka. With this in place, new benchmarks may make sense. I am working on getting it off the ground, but also to make us more efficient. So when I learn something. e.g. ``assert`` is not special, I apply it to the ``develop`` branch immediately, to keep the differences as small as possible, and to immediately benefit from such improvements. *********************** Nuitka Release 0.3.17 *********************** This is to inform you about the new stable release of Nuitka. This time there are a few bug fixes, lots of very important organisational work, and yet again improved compatibility and cleanups. Also huge is the advance in making ``--deep`` go away and making the recursion of Nuitka controllable, which means a lot for scalability of projects that use a lot of packages that use other packages, because now you can choose which ones to embed and which ones one. The release cycle had a focus on improving the quality of the test scripts, the packaging, and generally to prepare the work on "type inference" in a new feature branch. I have also continued to work towards CPython3.2 compatibility, and this version, while not there, supports Python3 with a large subset of the basic tests programs running fine (of course via ``2to3`` conversion) without trouble. There is still work to do, exceptions don't seem to work fully yet, parameter parsing seems to have changed, etc. but it seems that CPython3.2 is going to work one day. And there has been a lot of effort, to address the Debian packaging to be cleaner and more complete, addressing issues that prevented it from entering the Debian repository. Bug fixes ========= - Fixed the handling of modules and packages of the same name, but with different casing. Problem showed under Windows only. Released as 0.3.16a hot fix already. - Fixed an error where the command line length of Windows was exceeded when many modules were embedded, Christopher Tott provided a fix for it. Released as 0.3.16a hot fix already. - Fix, avoid to introduce new variables for where built-in exception references are sufficient. Released as 0.3.16b hot fix already. - Fix, add the missing ``staticmethod`` decorator to ``__new__`` methods before resolving the scopes of variables, this avoids the use of that variable before it was assigned a scope. Released as 0.3.16b hot fix already. New Features ============ - Enhanced compatibility again, provide enough ``co_varnames`` in the code objects, so that slicing them up to ``code_object.co_argcount`` will work. They are needed by ``inspect`` module and might be used by some decorators as well. - New options to control the recursion: ``--recurse-none`` (do not warn about not-done recursions) ``--recurse-all`` (recurse to all otherwise warned modules) ``--recurse-to`` (confirm to recurse to those modules) ``--recurse-not-to`` (confirm to not recurse to those modules) Optimization ============ - The optimization of constant conditional expressions was not done yet. Added this missing constant propagation case. - Eliminate near empty statement sequences (only contain a pass statement) in more places, giving a cleaner node structure for many constructs. - Use the pickle "protocol 2" on CPython2 except for ``unicode`` strings where it does not work well. It gives a more compressed and binary representation, that is generally more efficient to un-stream as well. Also use the cPickle protocol, the use of ``pickle`` was not really necessary anymore. Organisational ============== - Added a `Developer Manual `__ to the release. It's incomplete, but it details some of the existing stuff, coding rules, plans for "type inference", etc. - Improved the ``--help`` output to use ``metavar`` where applicable. This makes it more readable for some options. - Instead of error message, give help output when no module or program file name was given. This makes Nuitka help out more convenient. - Consistently use ``#!/usr/bin/env python`` for all scripts, this was previously only done for some of them. - Ported the PyLint check script to Python as well, enhancing it on the way to check the exit code, and to only output changes things, as well as making the output of warnings for ``TODO`` items optional. - All scripts used for testing, PyLint checking, etc. now work with Python3 as well. Most useful on Arch Linux, where it's also already the default for ``Python``. - The help output of Nuitka was polished a lot more. It is now more readable and uses option groups to combine related options together. - Make the tests run without any dependence on ``PATH`` to contain the executables of Nuitka. This makes it easier to use. - Add license texts to 3rd party file that were missing them, apply ``licensecheck`` results to cleanup Nuitka. Also removed own copyright statement from in-line copy of Scons, it had been added by accident only. - Release the tests that I own as well as the Debian packaging I created under "Apache License 2.0" which is very liberal, meaning every project will be able to use it. - Don't require copyright assignment for contributions anymore, instead only "Apache License 2.0", the future Nuitka license, so that the code won't be a problem when changing the license of all of Nuitka to that license. - Give contributors listed in the `User Manual `__ an exception to the GPL terms until Nuitka is licensed under "Apache License 2.0" as well. - Added an ``--experimental`` option which can be used to control experimental features, like the one currently being added on branch ``feature/ctypes_annotation``, where "type inference" is currently only activated when that option is given. For this stable release, it does nothing. - Check the static C++ files of Nuitka with ``cppcheck`` as well. Didn't find anything. - Arch Linux packages have been contributed, these are linked for download, but the stable package may lag behind a bit. Cleanups ======== - Changed ``not`` boolean operation to become a normal operator. Changed ``and`` and ``or`` boolean operators to a new base class, and making their interface more similar to that of operations. - Added cumulative ``tags`` to node classes for use in checks. Use it annotate which node kinds to visit in e.g. per scope finalization steps. That avoids kinds and class checks. - Enhanced the "visitor" interface to provide more kinds of callbacks, enhanced the way "each scope" visiting is achieved by generalizing is as "child has not tag 'closure_taker'" and that for every "node that has tag 'closure_taker'". - Moved ``SyntaxHighlighting`` module to ``nuitka.gui`` package where it belongs. - More white listing work for imports. As recursion is now the default, and leads to warnings for non-existent modules, the CPython tests gave a lot of good candidates for import errors that were white listed. - Consistently use ``nuitka`` in test scripts, as there isn't a ``Nuitka.py`` on all platforms. The later is scheduled for removal. - Some more PyLint cleanups. New Tests ========= - Make sure the basic tests pass with CPython or else fail the test. This is to prevent false positives, where a test passes, but only because it fails in CPython early on and then does so with Nuitka too. For the syntax tests we make sure they fail. - The basic tests can now be run with ``PYTHON=python3.2`` and use ``2to3`` conversion in that case. Also the currently not passing tests are not run, so the passing tests continue to do so, with this run from the release test script ``check-release``. - Include the syntax tests in release tests as well. - Changed many existing tests so that they can run under CPython3 too. Of course this is via ``2to3`` conversion. - Don't fail if the CPython test suites are not there. Currently they remain largely unpublished, and as such are mostly only available to me (exception, ``feature/minimize_CPython26_tests_diff`` branch references the CPython2.6 tests repository, but that remains work in progress). - For the compile itself test: Make the presence of the Scons in-line copy optional, the Debian package doesn't contain it. - Also make it more portable, so it runs under Windows too, and allow to choose the Python version to test. Check this test with both CPython2.6 and CPython2.7 not only the default Python. - Before releasing, test that the created Debian package builds fine in a minimal Debian ``unstable`` chroot, and passes all the tests included in the package (``basics``, ``syntax``, ``programs``, ``reflected``). Also many other Debian packaging improvements. Summary ======= The "git flow" was used again in this release cycle and proved to be useful not only for hot fix, but also for creating the branch ``feature/ctypes_annotation`` and rebasing it often while things are still flowing. The few hot fixes didn't require a new release, but the many organisational improvements and the new features did warrant the new release, because of e.g. the much better test handling in this release and the improved recursion control. The work on Python3 support has slowed down a bit. I mostly only added some bits for compatibility, but generally it has slowed down. I wanted to make sure it doesn't regress by accident, so running with CPython3.2 is now part of the normal release tests. What's still missing is more "hg" completeness. Only the ``co_varnames`` work for ``inspect`` was going in that direction, and this has slowed down. It was more important to make Nuitka's recursion more accessible with the new options, so that was done first. And of course, the real excitement is the "type inference" work. It will give a huge boost to Nuitka, and I am happy that it seems to go well. With this in place, new benchmarks may make sense. I am working on getting it off the ground, so other people can work on it too. My idea of ``ctypes`` native calls may become true sooner than expected. To support that, I would like to add more tools to make sure we discover changes earlier on, checking the XML representations of tests to discover improvements and regressions more clearly. *********************** Nuitka Release 0.3.16 *********************** This time there are many bug fixes, some important scalability work, and again improved compatibility and cleanups. The release cycle had a focus on fixing the bug reports I received. I have also continued to look at CPython3 compatibility, and this is the first version to support Python3 somewhat, at least some of the basic tests programs run (of course via ``2to3`` conversion) without trouble. I don't know when, but it seems that it's going to work one day. Also there has an effort to make the Debian packaging cleaner, addressing all kinds of small issues that prevented it from entering the Debian repository. It's still not there, but it's making progress. Bug fixes ========= - Fixed a packaging problem for Linux and x64 platform, the new ``swapFiber.S`` file for the fiber management was not included. Released as 0.3.15a hot fix already. - Fixed an error where optimization was performed on removed unreachable code, which lead to an error. Released as 0.3.15b hot fix already. - Fixed an issue with ``__import__`` and recursion not happening in any case, because when it did, it failed due to not being ported to new internal APIs. Released as 0.3.15c hot fix already. - Fixed ``eval()`` and ``locals()`` to be supported in generator expressions and contractions too. Released as 0.3.15d hot fix already. - Fixed the Windows batch files ``nuitka.bat`` and ``nuitka-python.bat`` to not output the ``rem`` statements with the copyright header. Released as 0.3.15d hot fix already. - Fixed re-raise with ``raise``, but without a current exception set. Released as 0.3.15e hot fix already. - Fixed ``vars()`` call on the module level, needs to be treated as ``globals()``. Released as 0.3.15e hot fix already. - Fix handling of broken new lines in source files. Read the source code in "universal line ending mode". Released as 0.3.15f hot fix already. - Fixed handling of constant module attribute ``__name__`` being replaced. Don't replace local variables of the same name too. Released as 0.3.15g hot fix already. - Fixed assigning to ``True``, ``False`` or ``None``. There was this old ``TODO``, and some code has compatibility craft that does it. Released as 0.3.15g hot fix already. - Fix constant dictionaries not always being recognized as shared. Released as 0.3.15g hot fix already. - Fix generator function objects to not require a return frame to exist. In finalize cleanup it may not. - Fixed non-execution of cleanup codes that e.g. flush ``sys.stdout``, by adding ``Py_Finalize()``. - Fix ``throw()`` method of generator expression objects to not check arguments properly. - Fix missing fallback to subscript operations for slicing with non-indexable objects. - Fix, in-place subscript operations could fail to apply the update, if the intermediate object was e.g. a list and the handle just not changed by the operation, but e.g. the length did. - Fix, the future spec was not properly preserving the future division flag. Optimization ============ - The optimization scales now much better, because per-module optimization only require the module to be reconsidered, but not all modules all the time. With many modules recursed into, this makes a huge difference in compilation time. - The creation of dictionaries from constants is now also optimized. New Features ============ - As a new feature functions now have the ``func_defaults`` and ``__defaults__`` attribute. It works only well for non-nested parameters and is not yet fully integrated into the parameter parsing. This improves the compatibility somewhat already though. - The names ``True``, ``False`` and ``None`` are now converted to constants only when they are read-only module variables. - The ``PYTHONPATH`` variable is now cleared when immediately executing a compiled binary unless ``--execute-with-pythonpath`` is given, in which case it is preserved. This allows to make sure that a binary is in fact containing everything required. Organisational ============== - The help output of Nuitka was polished a lot more. It is now more readable and uses option groups to combine related options together. - The in-line copy of Scons is not checked with PyLint anymore. We of course don't care. - Program tests are no longer executed in the program directory, so failed module inclusions become immediately obvious. - The basic tests can now be run with ``PYTHON=python3.2`` and use ``2to3`` conversion in that case. Cleanups ======== - Moved ``tags`` to a separate module, make optimization emit only documented tags, checked against the list of allowed ones. - The Debian package has seen lots of improvements, to make it "lintian clean", even in pedantic mode. The homepage of Nuitka is listed, a watch file can check for new releases, the git repository and the gitweb are referenced, etc. - Use ``os.path.join`` in more of the test code to achieve more Windows portability for them. - Some more PyLint cleanups. New Tests ========= - There is now a ``Crasher`` test, for tests that crashed Nuitka previously. - Added a program test where the imported module does a ``sys.exit()`` and make sure it really doesn't continue after the ``SystemExit`` exception that creates. - Cover the type of ``__builtins__`` in the main program and in imported modules in tests too. It's funny and differs between module and dict in CPython2. - Cover a final ``print`` statement without newline in the test. Must still receive a newline, which only happens when ``Py_Finalize()`` is called. - Added test with functions that makes a ``raise`` without an exception set. - Cover the calling of ``vars()`` on module level too. - Cover the use of eval in contractions and generator expressions too. - Cover ``func_defaults`` and ``__default__`` attributes for a function too. - Added test function with two ``raise`` in an exception handler, so that one becomes dead code and removed without the crash. Summary ======= The "git flow" was really great in this release cycle. There were many hot fix releases being made, so that the bugs could be addressed immediately without requiring the overhead of a full release. I believe that this makes Nuitka clearly one of the best supported projects. This quick turn-around also encourages people to report more bugs, which is only good. And the structure is there to hold it. Of course, the many bug fixes meant that there is not as much new development, but that is not the priority, correctness is. The work on Python3 is a bit strange. I don't need Python3 at all. I also believe it is that evil project to remove cruft from the Python core and make developers of all relevant Python software, add compatibility cruft to their software instead. Yet, I can't really stop to work on it. It has that appeal of small fixups here and there, and then something else works too. Python3 work is like when I was first struggling with Nuitka to pass the CPython2 unit tests for a first time. It's fun. And then it finds real actual bugs that apply to CPython2 too. Not doing ``Py_Finalize`` (but having to), the slice operations shortcomings, the bug of subscript in-place, and so on. There is likely more things hidden, and the earlier Python3 is supported, the more benefit from increased test covered. What's missing is more "hg" completeness. I think only the ``raise`` without exception set and the ``func_defaults`` issue were going into its direction, but it won't be enough yet. *********************** Nuitka Release 0.3.15 *********************** This is to inform you about the new stable release of Nuitka. This time again many organisational improvements, some bug fixes, much improved compatibility and cleanups. This release cycle had a focus on packaging Nuitka for easier consumption, i.e. automatic packaging, making automatic uploads, improvement documentation, and generally cleaning things up, so that Nuitka becomes more compatible and ultimately capable to run the "hg" test suite. It's not there yet, but this is a huge jump for usability of Nuitka and its compatibility, again. Then lots of changes that make Nuitka approach Python3 support, the generated C++ for at least one large example is compiling with this new release. It won't link, but there will be later releases. And there is a lot of cleanup going on, geared towards compatibility with line numbers in the frame object. Bug fixes ========= - The main module was using ``__main__`` in tracebacks, but it must be ````. Released as 0.3.14a hot fix already. - Workaround for "execfile cannot be used as an expression". It wasn't possible to use ``execfile`` in an expression, only as a statement. But then there is crazy enough code in e.g. mercurial that uses it in a lambda function, which made the issue more prominent. The fix now allows it to be an expression, except on the class level, which wasn't seen yet. - The in-line copy of Scons was not complete enough to work for "Windows" or with ``--windows-target`` for cross compile. Fixed. - Cached frames didn't release the "back" frame, therefore holding variables of these longer than CPython does, which could cause ordering problems. Fixed for increased compatibility. - Handle "yield outside of function" syntax error in compiled source correctly. This one was giving a Nuitka backtrace, now it gives a ``SyntaxError`` as it needs to. - Made syntax/indentation error output absolutely identical to CPython. - Using the frame objects ``f_lineno`` may fix endless amounts bugs related to traceback line numbers. New Features ============ - Guesses the location of the MinGW compiler under Windows to default install location, so it need not be added to ``PATH`` environment variable. Removes the need to modify ``PATH`` environment just for Nuitka to find it. - Added support for "lambda generators". You don't want to know what it is. Lets just say, it was the last absurd language feature out there, plus that didn't work. It now works perfect. Organisational ============== - You can now download a Windows installer and a Debian package that works on Debian Testing, current Ubuntu and Mint Linux. - New release scripts give us the ability to have hot fix releases as download packages immediately. That means the "git flow" makes even more beneficial to the users. - Including the generated "README.pdf" in the distribution archives, so it can be read instead of "README.txt". The text file is fairly readable, due to the use of ReStructured Text, but the PDF is even nicer to read, due to e.g. syntax highlighting of the examples. - Renamed the main binaries to ``nuitka`` and ``nuitka-python``, so that there is no dependency on case sensitive file systems. - For Windows there are batch files ``nuitka.bat`` and ``nuitka-python.bat`` to make Nuitka directly executable without finding the ``Python.exe``, which the batch files can tell from their own location. - There are now man pages of ``nuitka`` and ``nuitka-python`` with examples for the most common use cases. They are of course included in the Debian package. - Don't strip the binary when executing it to analyse compiled binary with ``valgrind``. It will give better information that way, without changing the code. Optimization ============ - Implemented ``swapcontext`` alike (``swapFiber``) for x64 to achieve 8 times speedup for Generators. It doesn't do useless syscalls to preserve signal masks. Now Nuitka is faster at frame switching than CPython on x64, which is already good by design. Cleanups ======== - Using the frame objects to store current line of execution avoids the need to store it away in helper code at all. It ought to also help a lot with threading support, and makes Nuitka even more compatible, because now line numbers will be correct even outside tracebacks, but for mere stack frame dumps. - Moved the ``for_return`` detection from code generation to tree building where it belongs. Yield statements used as return statements need slightly different code for Python2.6 difference. That solved an old ``TODO``. - Much Python3 portability work. Sometimes even improving existing code, the Python compiler code had picked up a few points, where the latest Nuitka didn't work with Python3 anymore, when put to actual compile. The test covered only syntax, but e.g. meta classes need different code in CPython3, and that's now supported. Also helper code was made portable in more places, but not yet fully. This will need more work. - Cleaned up uses of debug defines, so they are now more consistent and in one place. - Some more PyLint cleanups. New Tests ========= - The tests are now executed by Python scripts and cover ``stderr`` output too. Before we only checked ``stdout``. This unveiled a bunch of issues Nuitka had, but went unnoticed so far, and triggered e.g. the frame line number improvements. - Separate syntax tests. - The scripts to run the tests now are all in pure Python. This means, no more MinGW shell is needed to execute the tests. Summary ======= The Debian package, Windows installer, etc. are now automatically updated and uploaded. From here on, there can be such packages for the hot fix releases too. The exception tracebacks are now correct by design, and better covered. The generator performance work showed that the approach taken by Nuitka is in fact fast. It was fast on ARM already, but it's nice to see that it's now also fast on x64. Programs using generators will be affected a lot by this. Overall, this release brings Nuitka closer to usability. Better binary names, man pages, improved documentation, issue tracker, etc. all there now. I am in fact now looking for a sponsor for the Debian package to upload it into Debian directly. .. admonition:: Update The upload to Debian happened for 0.3.18 and was done by Yaroslav Halchenko. What's missing is more "hg" completeness. The frame release issue helped it, but ``inspect.getargs()`` doesn't work yet, and is a topic for a future release. Won't be easy, as ``func_defaults`` will be an invasive change too. *********************** Nuitka Release 0.3.14 *********************** This is to inform you about the new stable release of Nuitka. This time it contains mostly organisational improvements, some bug fixes, improved compatibility and cleanups. It is again the result of working towards compilation of a real program (Mercurial). This time, I have added support for proper handling of compiled types by the ``inspect`` module. Bug fixes ========= - Fix for "Missing checks in parameter parsing with star list, star dict and positional arguments". There was whole in the checks for argument counts, now the correct error is given. Fixed in 0.3.13a already. - The simple slice operations with 2 values, not extended with 3 values, were not applying the correct order for evaluation. Fixed in 0.3.13a already. - The simple slice operations couldn't handle ``None`` as the value for lower or upper index. Fixed in 0.3.11a already. - The in-place simple slice operations evaluated the slice index expressions twice, which could cause problems if they had side effects. Fixed in 0.3.11a already. New Features ============ - Run time patching the ``inspect`` module so it accepts compiled functions, compiled methods, and compiled generator objects. The ``test_inspect`` test of CPython is nearly working unchanged with this. - The generator functions didn't have ``CO_GENERATOR`` set in their code object, setting it made compatible with CPython in this regard too. The inspect module will therefore return correct value for ``inspect.isgeneratorfunction()`` too. Optimization ============ - Slice indexes that are ``None`` are now constant propagated as well. - Slightly more efficient code generation for dual star arg functions, removing useless checks. Cleanups ======== - Moved the Scons, static C++ files, and assembler files to new package ``nuitka.build`` where also now ``SconsInterface`` module lives. - Moved the Qt dialog files to ``nuitka.gui`` - Moved the "unfreezer" code to its own static C++ file. - Some PyLint cleanups. New Tests ========= - New test ``Recursion`` to cover recursive functions. - New test ``Inspection`` to cover the patching of ``inspect`` module. - Cover ``execfile`` on the class level as well in ``ExecEval`` test. - Cover evaluation order of simple slices in ``OrderCheck`` too. Organisational ============== - There is a new issue tracker available (since migrated and removed) Please register and report issues you encounter with Nuitka. I have put all the known issues there and started to use it recently. It's Roundup based like https://bugs.python.org is, so people will find it familiar. - The ``setup.py`` is now apparently functional. The source releases for download are made it with, and it appears the binary distributions work too. We may now build a windows installer. It's currently in testing, we will make it available when finished. Summary ======= The new source organisation makes packaging Nuitka really easy now. From here, we can likely provide "binary" package of Nuitka soon. A windows installer will be nice. The patching of ``inspect`` works wonders for compatibility for those programs that insist on checking types, instead of doing duck typing. The function call problem, was an issue found by the Mercurial test suite. For the "hg.exe" to pass all of its test suite, more work may be needed, this is the overall goal I am currently striving for. Once real world programs like Mercurial work, we can use these as more meaningful benchmarks and resume work on optimization. *********************** Nuitka Release 0.3.13 *********************** This release is mostly the result of working towards compilation of a real programs (Mercurial) and to merge and finalize the frame stack work. Now Nuitka has a correct frame stack at all times, and supports ``func_code`` and ``gi_code`` objects, something previously thought to be impossible. Actually now it's only the "bytecode" objects that won't be there. And not attributes of ``func_code`` are meaningful yet, but in theory can be supported. Due to the use of the "git flow" for Nuitka, most of the bugs listed here were already fixed in on the stable release before this release. This time there were 5 such hot fix releases, sometimes fixing multiple bugs. Bug fixes ========= - In case of syntax errors in the main program, an exception stack was giving that included Nuitka code. Changed to make the same output as CPython does. Fixed in 0.3.12a already. - The star import (``from x import *``) didn't work for submodules. Providing ``*`` as the import list to the respective code allowed to drop the complex lookups we were doing before, and to simply trust CPython C/API to do it correctly. Fixed in 0.3.12 already. - The absolute import is *not* the default of CPython 2.7 it seems. A local ``posix`` package shadows the standard library one. Fixed in 0.3.12 already. - In ``--deep`` mode, a module may contain a syntax error. This is e.g. true of "PyQt" with ``port_v3`` included. These files contain Python3 syntax and fail to be imported in Python2, but that is not to be considered an error. These modules are now skipped with a warning. Fixed in 0.3.12b already. - The code to import modules wasn't using the ``__import__`` built-in, which prevented ``__import__`` overriding code to work. Changed import to use the built-in. Fixed in 0.3.12c already. - The code generated for the ``__import__`` built-in with constant values was doing relative imports only. It needs to attempt relative and absolute imports. Fixed in 0.3.12c already. - The code of packages in "__init__.py" believed it was outside of the package, giving problems for package local imports. Fixed in 0.3.12d already. - It appears that "Scons", which Nuitka uses internally and transparent to you, to execute the compilation and linking tasks, was sometimes not building the binaries or shared libraries, due to a false caching. As a workaround, these are now erased before doing the build. Fixed in 0.3.12d already. - The use of ``in`` and ``not in`` in comparison chains (e.g. ``a < b < c`` is one), wasn't supported yet. The use of these in comparison chains ``a in b in c`` is very strange. Only in the ``test_grammar.py`` it was ever used I believe. Anyway, it's supported now, solving this ``TODO`` and reducing the difference. Fixed in 0.3.12e already. - The order of evaluation for ``in`` and ``not in`` operators wasn't enforced in a portable way. Now it is correct on "ARM" too. Fixed in 0.3.12e already. Optimization ============ - The built-ins ``GeneratorExit`` and ``StopIteration`` are optimized to their Python C/API names where possible as well. Cleanups ======== - The ``__file__`` attribute of modules was the relative filename, but for absolute filenames these become a horrible mess at least on Linux. - Added assertion helpers for sane frame and code objects and use them. - Make use of ``assertObject`` in more places. - Instead of using ``os.path.sep`` all over, added a helper ``Utils.joinpath`` that hides this and using ``os.path.join``. This gives more readable code. - Added traces to the "unfreezer" guarded by a define. Helpful in analyzing import problems. - Some PyLint cleanups removing dead code, unused variables, useless pass statement, etc. New Tests ========= - New tests to cover ``SyntaxError`` and ``IndentationError`` from ``--deep`` imports and in main program. - New test to cover evaluation order of ``in`` and ``not in`` comparisons. - New test to cover package local imports made by the "__init__.py" of the package. Organisational ============== - Drop "compile_itself.sh" in favor of the new "compile_itself.py", because the later is more portable. - The logging output is now nicer, and for failed recursions, outputs the line that is having the problem. Summary ======= The frame stack work and the ``func_code`` are big for compatibility. The ``func_code`` was also needed for "hg" to work. For Mercurial to pass all of its test suite, more work will be needed, esp. the ``inspect`` module needs to be run-time patched to accept compiled functions and generators too. Once real world programs like Mercurial work, we can use these as more meaningful benchmarks and resume work on optimization. *********************** Nuitka Release 0.3.12 *********************** This is to inform you about the new release of Nuitka many bug fixes, and substantial improvements especially in the organisational area. There is a new `User Manual `__ (`PDF `__), with much improved content, a ``sys.meta_path`` based import mechanism for ``--deep`` mode, git flow goodness. This release is generally also the result of working towards compilation of a real programs (Mercurial) and to get things work more nicely on Windows by default. Thanks go to Liu Zhenhai for helping me with this goal. Due to the use of the "git flow", most of the bugs listed here were already fixed in on the stable release before this release. And there were many of these. Bug fixes ========= - The order of evaluation for base classes and class dictionaries was not enforced. Apparently nothing in the CPython test suite did that, I only noticed during debugging that Nuitka gave a different error than CPython did, for a class that had an undefined base class, because both class body and base classes were giving an error. Fixed in 0.3.11a already. - Method objects didn't hold a reference to the used class. The effect was only noticed when ``--python-debug`` was used, i.e. the debug version of Python linked, because then the garbage collector makes searches. Fixed in 0.3.11b already. - Set ``sys.executable`` on Linux as well. On Debian it is otherwise ``/usr/bin/python`` which might be a different version of Python entirely. Fixed in 0.3.11c already. - Embedded modules inside a package could hide package variables of the same name. Learned during PyCON DE about this corner case. Fixed in 0.3.11d already. - Packages could be duplicated internally. This had no effect on generated code other than appearing twice in the list if frozen modules. Fixed in 0.3.11d already. - When embedding modules from outside current directory, the look-up failed. The embedding only ever worked for the compile itself and programs test cases, because they are all in the current directory then. Fixed in 0.3.11e already. - The check for ARM target broke Windows support in the Scons file. Fixed in 0.3.11f already. - The star import from external modules failed with an error in ``--deep`` mode. Fixed in 0.3.11g already. - Modules with a parent package could cause a problem under some circumstances. Fixed in 0.3.11h already. - One call variant, with both list and dict star arguments and keyword arguments, but no positional parameters, didn't have the required C++ helper function implemented. Fixed in 0.3.11h already. - The detection of the CPU core count was broken on my hexacore at least. Gave 36 instead of 6, which is a problem for large programs. Fixed in 0.3.11h already. - The in-line copy of Scons didn't really work on Windows, which was sad, because we added it to simplify installation on Windows precisely because of this. - Cleaning up the build directory from old sources and object files wasn't portable to Windows and therefore wasn't effective there. - From imports where part of the imported were found modules and parts were not, didn't work. Solved by the feature branch ``meta_path_import`` that was merged for this release. - Newer MinGW gave warnings about the default visibility not being possible to apply to class members. Fixed by not setting this default visibility anymore on Windows. - The ``sys.executable`` gave warnings on Windows because of backslashes in the path. Using a raw string to prevent such problems. - The standard library path was hard coded. Changed to run time detection. Cleanups ======== - Version checks on Python runtime now use a new define ``PYTHON_VERSION`` that makes it easier. I don't like ``PY_VERSION_HEX``, because it is so unreadable. Makes some of the checks a lot more safe. - The ``sys.meta_path`` based import from the ``meta_path_import`` feature branch allowed the cleanup the way importing is done. It's a lot less code now. - Removed some unused code. We will aim at making Nuitka the tool to detect dead code really. - Moved ``nuitka.Nodes`` to ``nuitka.nodes.Nodes``, that is what the package is intended for, the split will come later. New Tests ========= - New tests for import variants that previously didn't work: Mixed imports. Imports from a package one level up. Modules hidden by a package variable, etc. - Added test of function call variant that had no test previously. Only found it when compiling "hg". Amazing how nothing in my tests, CPython tests, etc. used it. - Added test to cover the partial success of import statements. - Added test to cover evaluation order of class definitions. Organisational ============== - Migrated the "README.txt" from org-mode to ReStructured Text, which allows for a more readable document, and to generate a nice `User Manual `__ in PDF form. - The amount of information in "README.txt" was increased, with many more subjects are now covered, e.g. "git flow" and how to join Nuitka development. It's also impressive to see what code blocks and syntax highlighting can do for readability. - The Nuitka git repository has seen multiple hot fixes. These allowed to publish bug fixes immediately after they were made, and avoided the need for a new release just to get these out. This really saves me a lot of time too, because I can postpone releasing the new version until it makes sense because of other things. - Then there was a feature branch ``meta_path_import`` that lived until being merged to ``develop`` to improve the import code, which is now released on ``master`` as stable. Getting that feature right took a while. - And there is the feature branch ``minimize_CPython26_tests_diff`` which has some success already in documenting the required changes to the "CPython26" test suite and in reducing the amount of differences, while doing it. We have a frame stack working there, albeit in too ugly code form. - The release archives are now built using ``setuptools``. You can now also download a zip file, which is probably more Windows friendly. The intention is to work on that to make ``setup.py`` produce a Nuitka install that won't rely on any environment variables at all. Right now ``setup.py`` won't even allow any other options than ``sdist`` to be given. - Ported "compile_itself.sh" to "compile_itself.py", i.e. ported it to Python. This way, we can execute it easily on Windows too, where it currently still fails. Replacing ``diff``, ``rm -rf``, etc. is a challenge, but it reduces the dependency on MSYS tools on Windows. - The compilation of standard library is disabled by default, but ``site`` or ``dist`` packages are now embedded. To include even standard library, there is a ``--really-deep`` option that has to be given in addition to ``--deep``, which forces this. Summary ======= Again, huge progress. The improved import mechanism is very beautiful. It appears that little is missing to compile real world programs like "hg" with Nuitka. The next release cycle will focus on that and continue to improve the Windows support which appears to have some issues. *********************** Nuitka Release 0.3.11 *********************** This is to inform you about the new release of Nuitka with some bug fixes and portability work. This release is generally cleaning up things, and makes Nuitka portable to ARM Linux. I used to host the Nuitka homepage on that machine, but now that it's no longer so, I can run heavy compile jobs on it. To my surprise, it found many portability problems. So I chose to fix that first, the result being that Nuitka now works on ARM Linux too. Bug fixes ========= - The order of slice expressions was not correct on x86 as well, and I found that with new tests only. So the porting to ARM revealed a bug category, I previously didn't consider. - The use of ``linux2`` in the Scons file is potentially incompatible with Linux 3.0, although it seems that at least on Debian the ``sys.platform`` was changed back to ``linux2``. Anyway, it's probably best to allow just anything that starts with ``linux`` these days. - The ``print`` statement worked like a ``print`` function, i.e. it first evaluated all printed expressions, and did the output only then. That is incompatible in case of exceptions, where partial outputs need to be done, and so that got fixed. Optimization ============ - Function calls now each have a dedicated helper function, avoiding in some cases unnecessary work. We will may build further on this and in-line ``PyObject_Call`` differently for the special cases. Cleanups ======== - Moved many C++ helper declarations and in-line implementations to dedicated header files for better organisation. - Some dependencies were removed and consolidated to make the dependency graph sane. - Multiple decorators were in reverse order in the node tree. The code generation reversed it back, so no bug, yet that was a distorted tree. Finding this came from the ARM work, because the "reversal" was in fact just the argument evaluation order of C++ under x86/x64, but on ARM that broke. Correcting it highlighted this issue. - The deletion of slices, was not using ``Py_ssize`` for indexes, disallowing some kinds of optimization, so that was harmonized. - The function call code generation got a general overhaul. It is now more consistent, has more helpers available, and creates more readable code. - PyLint is again happier than ever. New Tests ========= - There is a new basic test ``OrderChecks`` that covers the order of expression evaluation. These problems were otherwise very hard to detect, and in some cases not previously covered at all. - Executing Nuitka with Python3 (it won't produce correct Python3 C/API code) is now part of the release tests, so non-portable code of Nuitka gets caught. Organisational ============== - Support for ARM Linux. I will make a separate posting on the challenges of this. Suffice to say now, that C++ leaves way too much things unspecified. - The Nuitka git repository now uses "git flow". The new git policy will be detailed in another `separate posting `__. - There is an unstable ``develop`` branch in which the development occurs. For this release ca. 40 commits were done to this branch, before merging it. I am also doing more fine grained commits now. - Unlike previously, there is ``master`` branch for the stable release. - There is a script "make-dependency-graph.sh" (Update: meanwhile it was renamed to "make-dependency-graph.py") to produce a dependency graphs of Nuitka. I detected a couple of strange things through this. - The Python3 ``__pycache__`` directories get removed too by the cleanup script. Numbers ======= We only have "PyStone" now, and on a new machine, so the numbers cannot be compared to previous releases: python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.48 This machine benchmarks at 104167 pystones/second Nuitka 0.3.11 (driven by python 2.6): .. code:: Pystone(1.1) time for 50000 passes = 0.19 This machine benchmarks at 263158 pystones/second So this a speedup factor of 258%, last time on another machine it was 240%. Yet it only proves that the generated and compiled are more efficient than bytecode, but Nuitka doesn't yet do the relevant optimization. Only once it does, the factor will be significantly higher. Summary ======= Overall, there is quite some progress. Nuitka is a lot cleaner now, which will help us later only. I wanted to get this out, mostly because of the bug fixes, and of course just in case somebody attempts to use it on ARM. *********************** Nuitka Release 0.3.10 *********************** This new release is major milestone 2 work, enhancing practically all areas of Nuitka. The focus was roundup and breaking new grounds with structural optimization enhancements. Bug fixes ========= - Exceptions now correctly stack. When you catch an exception, there always was the exception set, but calling a new function, and it catching the exception, the values of ``sys.exc_info()`` didn't get reset after the function returned. This was a small difference (of which there are nearly none left now) but one that might effect existing code, which affects code that calls functions in exception handling to check something about it. So it's good this is resolved now too. Also because it is difficult to understand, and now it's just like CPython behaves, which means that we don't have to document anything at all about it. - Using ``exec`` in generator functions got fixed up. I realized that this wouldn't work while working on other things. It's obscure yes, but it ought to work. - Lambda generator functions can now be nested and in generator functions. There were some problems here with the allocation of closure variables that got resolved. - List contractions could not be returned by lambda functions. Also a closure issue. - When using a mapping for globals to ``exec`` or ``eval`` that had a side effect on lookup, it was evident that the lookup was made twice. Correcting this also improves the performance for the normal case. Optimization ============ - Statically raised as well as predicted exceptions are propagated upwards, leading to code and block removal where possible, while maintaining the side effects. This is brand new and doesn't do everything possible yet. Most notable, the matching of raised exception to handlers is not yet performed. - Built-in exception name references and creation of instances of them are now optimized as well, which leads to faster exception raising/catching for these cases. - More kinds of calls to built-ins are handled, positional parameters are checked and more built-ins are covered. Notable is that now checks are performed if you didn't potentially overload e.g. the ``len`` with your own version in the module. Locally it was always detected already. So it's now also safe. - All operations and comparisons are now simulated if possible and replaced with their result. - In the case of predictable true or false conditions, not taken branches are removed. - Empty branches are now removed from most constructs, leading to sometimes cleaner code generated. Cleanups ======== - Removed the lambda body node and replaced it with function body. This is a great win for the split into body and builder. Regular functions and lambda functions now only differ in how the created body is used. - Large cleanup of the operation/comparison code. There is now only use of a simulator function, which exists for every operator and comparison. This one is then used in a prediction call, shared with the built-in predictions. - Added a ``Tracing`` module to avoid future imports of ``print_function``, which annoyed me many times by causing syntax failures for when I quickly added a print statement, not noting it must have the braces. - PyLint is happier than ever. New Tests ========= - Enhanced ``OverflowFunctions`` test to cover even deeper nesting of overflow functions taking closure from each level. While it's not yet working, this makes clearer what will be needed. Even if this code is obscure, I would like to be that correct here. - Made ``Operators`` test to cover the `` operator as well. - Added to ``ListContractions`` the case where a contraction is returned by a lambda function, but still needs to leak its loop variable. - Enhanced ``GeneratorExpressions`` test to cover lambda generators, which is really crazy code: .. code:: python def y(): yield ((yield 1), (yield 2)) - Added to ``ExecEval`` a case where the ``exec`` is inside a generator, to cover that too. - Activated the testing of ``sys.exc_info()`` in ``ExceptionRaising`` test. This was previously commented out, and now I added stuff to illustrate all of the behavior of CPython there. - Enhanced ``ComparisonChains`` test to demonstrate that the order of evaluations is done right and that side effects are maintained. - Added ``BuiltinOverload`` test to show that overloaded built-ins are actually called and not the optimized version. So code like this has to print 2 lines: .. code:: python from __builtin__ import len as _len def len(x): print x return _len(x) print len(range(9)) Organisational ============== - Changed "README.txt" to no longer say that "Scons" is a requirement. Now that it's included (patched up to work with ``ctypes`` on Windows), we don't have to say that anymore. - Documented the status of optimization and added some more ideas. - There is now an option to dump the node tree after optimization as XML. Not currently use, but is for regression testing, to identify where new optimization and changes have an impact. This make it more feasible to be sure that Nuitka is only becoming better. - Executable with Python3 again, although it won't do anything, the necessary code changes were done. Summary ======= It's nice to see, that I some long standing issues were resolved, and that structural optimization has become almost a reality. The difficult parts of exception propagation are all in place, now it's only details. With that we can eliminate and predict even more of the stupid code of "pybench" at compile time, achieving more infinite speedups. ********************** Nuitka Release 0.3.9 ********************** This is about the new release of Nuitka which some bug fixes and offers a good speed improvement. This new release is major milestone 2 work, enhancing practically all areas of Nuitka. The main focus was on faster function calls, faster class attributes (not instance), faster unpacking, and more built-ins detected and more thoroughly optimizing them. Bug fixes ========= - Exceptions raised inside with statements had references to the exception and traceback leaked. - On Windows the binaries ``sys.executable`` pointed to the binary itself instead of the Python interpreter. Changed, because some code uses ``sys.executable`` to know how to start Python scripts. - There is a bug (fixed in their repository) related to C++ raw strings and C++ "trigraphs" that affects Nuitka, added a workaround that makes Nuitka not emit "trigraphs" at all. - The check for mutable constants was erroneous for tuples, which could lead to assuming a tuple with only mutable elements to be not mutable, which is of course wrong. Optimization ============ This time there are so many new optimization, it makes sense to group them by the subject. Exceptions ---------- - The code to add a traceback is now our own, which made it possible to use frames that do not contain line numbers and a code object capable of lookups. - Raising exceptions or adding to tracebacks has been made way faster by reusing a cached frame objects for the task. - The class used for saving exceptions temporarily (e.g. used in ``try``/``finally`` code, or with statement) has been improved. It now doesn't make a copy of the exception with a C++ ``new`` call, but it simply stores the exception properties itself and creates the exception object only on demand, which is more efficient. - When catching exceptions, the addition of tracebacks is now done without exporting and re-importing the exception to Python, but directly on the exception objects traceback, this avoids a useless round trip. Function Calls -------------- - Uses of PyObject_Call provide ``NULL`` as the dictionary, instead of an empty dictionary, which is slightly faster for function calls. - There are now dedicated variants for complex function calls with ``*`` and ``**`` arguments in all forms. These can take advantage of easier cases. For example, a merge with star arguments is only needed if there actually were any of these. - The check for non-string values in the ``**`` arguments can now be completely short-cut for the case of a dictionary that has never had a string added. There is now code that detects this case and skips the check, eliminating it as a performance concern. Parameter Parsing ----------------- - Reversed the order in which parameters are checked. Now the keyword dictionary is iterated first and only then the positional arguments after that is done. This iteration is not only much faster (avoiding repeated lookups for each possible parameter), it also can be more correct, in case the keyword argument is derived from a dictionary and its keys mutate it when being compared. - Comparing parameter names is now done with a fast path, in which the pointer values are compare first. This can avoid a call to the comparison at all, which has become very likely due to the interning of parameter name strings, see below. - Added a dedicated call to check for parameter equality with rich equality comparison, which doesn't raise an exception. - Unpacking of tuples is now using dedicated variants of the normal unpacking code instead of rolling out everything themselves. Attribute Access ---------------- - The class type (in executables, not yet for extension modules) is changed to a faster variant of our own making that doesn't consider the restricted mode a possibility. This avoids very expensive calls, and makes accessing class attributes in compiled code and in non-compiled code faster. - Access to attributes (but not of instances) got in-lined and therefore much faster. Due to other optimization, a specific step to intern the string used for attribute access is not necessary with Nuitka at all anymore. This made access to attributes about 50% faster which is big of course. Constants --------- - The bug for mutable tuples also caused non-mutable tuples to be considered as mutable, which lead to less efficient code. - The constant creation with the g++ bug worked around, can now use raw strings to create string constants, without resorting to un-pickling them as a work around. This allows us to use ``PyString_FromStringAndSize`` to create strings again, which is obviously faster, and had not been done, because of the confusion caused by the g++ bug. - For string constants that are usable as attributes (i.e. match the identifier regular expression), these are now interned, directly after creation. With this, the check for identical value of pointers for parameters has a bigger chance to succeed, and this saves some memory too. - For empty containers (set, dict, list, tuple) the constants created are now are not unstreamed, but created with the dedicated API calls, saving a bit of code and being less ugly. - For mutable empty constant access (set, dict, list) the values are no longer made by copying the constant, but instead with the API functions to create new ones. This makes code like ``a = []`` a tiny bit faster. - For slice indices the code generation now takes advantage of creating a C++ ``Py_ssize_t`` from constant value if possible. Before it was converting the integer constant at run time, which was of course wasteful even if not (very) slow. Iteration --------- - The creation of iterators got our own code. This avoids a function call and is otherwise only a small gain for anything but sequence iterators. These may be much faster to create now, as it avoids another call and repeated checks. - The next on iterator got our own code too, which has simpler code flow, because it avoids the double check in case of NULL returned. - The unpack check got similar code to the next iterator, it also has simpler code flow now and avoids double checks. Built-ins --------- - Added support for the ``list``, ``tuple``, ``dict``, ``str``, ``float`` and ``bool`` built-ins along with optimizing their use with constant parameter. - Added support for the ``int`` and ``long`` built-ins, based on a new "call spec" object, that detects parameter errors at compile time and raises appropriate exceptions as required, plus it deals with keyword arguments just as well. So, to Nuitka it doesn't matter now it you write ``int(value) ``or ``int(x = value)`` anymore. The ``base`` parameter of these built-ins is also supported. The use of this call spec mechanism will the expanded, currently it is not applied to the built-ins that take only one parameter. This is a work in progress as is the whole built-ins business as not all the built-ins are covered yet. Cleanups -------- - In 0.3.8 per module global classes were introduced, but the ``IMPORT_MODULE`` kept using the old universal class, this got resolved and the old class is now fully gone. - Using ``assertObject`` in more cases, and in more places at all, catches errors earlier on. - Moved the addition to tracebacks into the ``_PythonException`` class, where it works directly on the contained traceback. This is cleaner as it no longer requires to export exceptions to Python, just to add a traceback entry. - Some ``PyLint`` cleanups were done, reducing the number of reports a bit, but there is still a lot to do. - Added a ``DefaultValueIdentifier`` class that encapsulates the access to default values in the parameter parsing more cleanly. - The module ``CodeTemplatesListContractions`` was renamed to ``CodeTemplatesContractions`` to reflect the fact that it deals with all kinds of contractions (also set and dict contractions), not just list contractions. - Moved the with related template to its own module ``CodeTemplatesWith``, so its easier to find. - The options handling for g++ based compilers was cleaned up, so that g++ 4.6 and MinGW are better supported now. - Documented more aspects of the Scons build file. - Some more generated code white space fixes. - Moved some helpers to dedicated files. There is now ``calling.hpp`` for function calls, an ``importing.cpp`` for import related stuff. - Moved the manifest generation to the scons file, which now produces ready to use executables. New Tests ========= - Added a improved version of "pybench" that can cope with the "0 ms" execution time that Nuitka has for some if its sub-tests. - Reference counting test for with statement was added. - Micro benchmarks to demonstrate try finally performance when an exception travels through it. - Micro benchmark for with statement that eats up exceptions raised inside the block. - Micro benchmarks for the read and write access to class attributes. - Enhanced ``Printing`` test to cover the trigraphs constant bug case. Output is required to make the error detectable. - Enhanced ``Constants`` test to cover repeated mutation of mutable tuple constants, this covers the bug mentioned. Organisational ============== - Added a credits section to the "README.txt" where I give credit to the people who contributed to Nuitka, and the projects it is using. I will make it a separate posting to cite these. - Documented the requirements on the compiler more clearly, document the fact that we require scons and which version of Python (2.6 or 2.7). - The is now a codespeed implementation up and running with historical data for up to Nuitka 0.3.8 runs of "PyStone" and with pybench. It will be updated for 0.3.9 once I have the infrastructure in place to do that automatically. - The cleanup script now also removes .so files. - The handling of options for g++ got improved, so it's the same for g++ and MinGW compilers, plus adequate errors messages are given, if the compiler version is too low. - There is now a ``--unstriped`` option that just keeps the debug information in the file, but doesn't keep the assertions. This will be helpful when looking at generated assembler code from Nuitka to not have the distortions that ``--debug`` causes (reduced optimization level, assertions, etc.) and instead a clear view. ********************** Nuitka Release 0.3.8 ********************** This is to inform you about the new release of Nuitka with some real news and a slight performance increase. The significant news is added "Windows Support". You can now hope to run Nuitka on Windows too and have it produce working executables against either the standard Python distribution or a MinGW compiled Python. There are still some small things to iron out, and clearly documentation needs to be created, and esp. the DLL hell problem of ``msvcr90.dll`` vs. ``msvcrt.dll``, is not yet fully resolved, but appears to be not as harmful, at least not on native Windows. I am thanking Khalid Abu Bakr for making this possible. I was surprised to see this happen. I clearly didn't make it easy. He found a good way around ``ucontext``, identifier clashes, and a very tricky symbol problems where the CPython library under Windows exports less than under Linux. Thanks a whole lot. Currently the Windows support is considered experimental and works with MinGW 4.5 or higher only. Otherwise there have been the usual round of performance improvements and more cleanups. This release is otherwise milestone 2 work only, which will have to continue for some time more. Bug fixes ========= - Lambda generators were not fully compatible, their simple form could yield an extra value. The behavior for Python 2.6 and 2.7 is also different and Nuitka now mimics both correctly, depending on the used Python version - The given parameter count cited in the error message in case of too many parameters, didn't include the given keyword parameters in the error message. - There was an ``assert False`` right after warning about not found modules in the ``--deep`` mode, which was of course unnecessary. Optimization ============ - When unpacking variables in assignments, the temporary variables are now held in a new temporary class that is designed for the task specifically. This avoids the taking of a reference just because the ``PyObjectTemporary`` destructor insisted on releasing one. The new class ``PyObjectTempHolder`` hands the existing reference over and releases only in case of exceptions. - When unpacking variable in for loops, the value from the iterator may be directly assigned, if it's to a variable. In general this would be possible for every assignment target that cannot raise, but the infrastructure cannot tell yet, which these would be. This will improve with more milestone 3 work. - Branches with only ``pass`` inside are removed, ``pass`` statements are removed before the code generation stage. This makes it easier to achieve and decide empty branches. - There is now a global variable class per module. It appears that it is indeed faster to roll out a class per module accessing the ``module *`` rather than having one class and use a ``module **``, which is quite disappointing from the C++ compiler. - Also ``MAKE_LIST`` and ``MAKE_TUPLE`` have gained special cases for the 0 arguments case. Even when the size of the variadic template parameters should be known to the compiler, it seems, it wasn't eliminating the branch, so this was a speedup measured with valgrind. - Empty tried branches are now replaced when possible with ``try``/``except`` statements, ``try``/``finally`` is simplified in this case. This gives a cleaner tree structure and less verbose C++ code which the compiler threw away, but was strange to have in the first place. - In conditions the ``or`` and ``and`` were evaluated with Python objects instead of with C++ bool, which was unnecessary overhead. - List contractions got more clever in how they assign from the iterator value. It now uses a ``PyObjectTemporary`` if it's assigned to multiple values, a ``PyObjectTempHolder`` if it's only assigned once, to something that could raise, or a ``PyObject *`` if an exception cannot be raised. This avoids temporary references completely for the common case. Cleanups ======== - The ``if``, ``for``, and ``while`` statements had always empty ``else`` nodes which were then also in the generated C++ code as empty branches. No harm to performance, but this got cleaned up. - Some more generated code white space fixes. New Tests ========= - The CPython 2.7 test suite now also has the ``doctests`` extracted to static tests, which improves test coverage for Nuitka again. This was previously only done for CPython 2.6 test suite, but the test suites are different enough to make this useful, e.g. to discover newly changed behavior like with the lambda generators. - Added Shed Skin 0.7.1 examples as benchmarks, so we can start to compare Nuitka performance in these tests. These will be the focus of numbers for the 0.4.x release series. - Added a micro benchmark to check unpacking behavior. Some of these are needed to prove that a change is an actual improvement, when its effect can go under in noise of in-line vs. no in-line behavior of the C++ compiler. - Added "pybench" benchmark which reveals that Nuitka is for some things much faster, but there are still fields to work on. This version needed changes to stand the speed of Nuitka. These will be subject of a later posting. Organisational ============== - There is now a "tests/benchmarks/micro" directory to contain tiny benchmarks that just look at a single aspect, but have no other meaning, e.g. the "PyStone" extracts fall into this category. - There is now a ``--windows-target`` option that attempts a cross-platform build on Linux to Windows executable. This is using "MingGW-cross-env" cross compilation tool chain. It's not yet working fully correctly due to the DLL hell problem with the C runtime. I hope to get this right in subsequent releases. - The ``--execute`` option uses wine to execute the binary if it's a cross-compile for windows. - Native windows build is recognized and handled with MinGW 4.5, the VC++ is not supported yet due to missing C++0x support. - The basic test suite ran with Windows so far only and some adaptations were necessary. Windows new lines are now ignored in difference check, and addresses under Windows are upper case, small things. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.8 (driven by python 2.6): .. code:: Pystone(1.1) time for 50000 passes = 0.27 This machine benchmarks at 185185 pystones/second This is a 140% speed increase of 0.3.8 compared to CPython, up from 132% compared to the previous release. ********************** Nuitka Release 0.3.7 ********************** This is about the new release with focus on performance and cleanups. It indicates significant progress with the milestone this release series really is about as it adds a ``compiled_method`` type. So far functions, generator function, generator expressions were compiled objects, but in the context of classes, functions were wrapped in CPython ``instancemethod`` objects. The new ``compiled_method`` is specifically designed for wrapping ``compiled_function`` and therefore more efficient at it. Bug fixes ========= - When using ``Python`` or ``Nuitka.py`` to execute some script, the exit code in case of "file not found" was not the same as CPython. It should be 2, not 1. - The exit code of the created programs (``--deep`` mode) in case of an uncaught exception was 0, now it an error exit with value 1, like CPython does it. - Exception tracebacks created inside ``with`` statements could contain duplicate lines, this was corrected. Optimization ============ - Global variable assignments now also use ``assign0`` where no reference exists. The assignment code for module variables is actually faster if it needs not drop the reference, but clearly the code shouldn't bother to take it on the outside just for that. This variant existed, but wasn't used as much so far. - The instance method objects are now Nuitka's own compiled type too. This should make things slightly faster by itself. - Our new compiled method objects support dedicated method parsing code, where ``self`` is passed directly, allowing to make calls taking a fast path in parameter parsing. This avoids allocating/freeing a ``tuple`` object per method call, while reduced 3% ticks in "PyStone" benchmark, so that's significant. - Solved a ``TODO`` of ``BUILTIN_RANGE`` to change it to pre-allocating the list in the final size as we normally do everywhere else. This was a tick reduction of 0.4% in "PyStone" benchmark, but the measurement method normalizes on loop speed, so it's not visible in the numbers output. - Parameter variables cannot possibly be uninitialized at creation and most often they are never subject to a ``del`` statement. Adding dedicated C++ variable classes gave a big speedup, around 3% of "PyStone" benchmark ticks. - Some abstract object operations were re-implemented, which allows to avoid function calls e.g. in the ``ITERATOR_NEXT`` case, this gave a few percent on "PyStone" as well. Cleanups ======== - New package ``nuitka.codegen`` to contain all code generation related stuff, moved ``nuitka.templates`` to ``nuitka.codegen.templates`` as part of that. - Inside the ``nuitka.codegen`` package the ``MainControl`` module now longer reaches into ``Generator`` for simple things, but goes through ``CodeGeneration`` for everything now. - The ``Generator`` module uses almost no tree nodes anymore, but instead gets information passed in function calls. This allows for a cleanup of the interface towards ``CodeGeneration``. Gives a cleaner view on the C++ code generation, and generally furthers the goal of other than C++ language backends. - More "PyLint" work, many of the reported warnings have been addressed, but it's not yet happy. - Defaults for ``yield`` and ``return`` are ``None`` and these values are now already added (as constants) during tree building so that no such special cases need to be dealt with in ``CodeGeneration`` and future analysis steps. - Parameter parsing code has been unified even further, now the whole entry point is generated by one of the function in the new ``nuitka.codegen.ParameterParsing`` module. - Split variable, exception, built-in helper classes into separate header files. New Tests ========= - The exit codes of CPython execution and Nuitka compiled programs are now compared as well. - Errors messages of methods are now covered by the ``ParameterErrors`` test as well. Organisational ============== - A new script "benchmark.sh" (now called "run-valgrind.py") script now starts "kcachegrind" to display the valgrind result directly. One can now use it to execute a test and inspect valgrind information right away, then improve it. Very useful to discover methods for improvements, test them, then refine some more. - The "check-release.sh" script needs to unset ``NUITKA_EXTRA_OPTIONS`` or else the reflection test will trip over the changed output paths. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.7 (driven by python 2.6): .. code:: Pystone(1.1) time for 50000 passes = 0.28 This machine benchmarks at 178571 pystones/second This is a 132% speed of 0.3.7 compared to CPython, up from 109% compare to the previous release. This is a another small increase, that can be fully attributed to milestone 2 measures, i.e. not analysis, but purely more efficient C++ code generation and the new compiled method type. One can now safely assume that it is at least twice as fast, but I will try and get the PyPy or Shedskin test suite to run as benchmarks to prove it. No milestone 3 work in this release. I believe it's best to finish with milestone 2 first, because these are quite universal gains that we should have covered. ********************** Nuitka Release 0.3.6 ********************** The major point this for this release is cleanup work, and generally bug fixes, esp. in the field of importing. This release cleans up many small open ends of Nuitka, closing quite a bunch of consistency ``TODO`` items, and then aims at cleaner structures internally, so optimization analysis shall become "easy". It is a correctness and framework release, not a performance improvement at all. Bug fixes ========= - Imports were not respecting the ``level`` yet. Code like this was not working, now it is: .. code:: python from .. import something - Absolute and relative imports were e.g. both tried all the time, now if you specify absolute or relative imports, it will be attempted in the same way than CPython does. This can make a difference with compatibility. - Functions with a "locals dict" (using ``locals`` built-in or ``exec`` statement) were not 100% compatible in the way the locals dictionary was updated, this got fixed. It seems that directly updating a dict is not what CPython does at all, instead it only pushes things to the dictionary, when it believes it has to. Nuitka now does the same thing, making it faster and more compatible at the same time with these kind of corner cases. - Nested packages didn't work, they do now. Nuitka itself is now successfully using nested packages (e.g. ``nuitka.transform.optimizations``) New Features ============ - The ``--lto`` option becomes usable. It's not measurably faster immediately, and it requires g++ 4.6 to be available, but then it at least creates smaller binaries and may provide more optimization in the future. Optimization ============ - Exceptions raised by pre-computed built-ins, unpacking, etc. are now transformed to raising the exception statically. Cleanups ======== - There is now a ``getVariableForClosure`` that a variable provider can use. Before that it guessed from ``getVariableForReference`` or ``getVariableForAssignment`` what might be the intention. This makes some corner cases easier. - Classes, functions and lambdas now also have separate builder and body nodes, which enabled to make getSameScopeNodes() really simple. Either something has children which are all in a new scope or it has them in the same scope. - Twisted workarounds like ``TransitiveProvider`` are no longer needed, because class builder and class body were separated. - New packages ``nuitka.transform.optimizations`` and ``nuitka.transform.finalizations``, where the first was ``nuitka.optimizations`` before. There is also code in ``nuitka.transform`` that was previously in a dedicated module. This allowed to move a lot of displaced code. - ``TreeBuilding`` now has fast paths for all 3 forms, things that need a "provider", "node", and "source_ref"; things that need "node" and "source_ref"; things that need nothing at all, e.g. pass. - Variables now avoid building duplicated instances, but instead share one. Better for analysis of them. New Tests ========= - The Python 2.7 test suite is no longer run with Python 2.6 as it will just crash with the same exception all the time, there is no ``importlib`` in 2.6, but every test is using that through test_support. - Nested packages are now covered with tests too. - Imports of upper level packages are covered now too. Organisational ============== - Updated the "README.txt" with the current plan on optimization. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.6 (driven by python 2.6): .. code:: Pystone(1.1) time for 50000 passes = 0.31 This machine benchmarks at 161290 pystones/second This is 109% for 0.3.6, but no change from the previous release. No surprise, because no new effective new optimization means have been implemented. Stay tuned for future release for actual progress. ********************** Nuitka Release 0.3.5 ********************** This new release of Nuitka is an overall improvement on many fronts, there is no real focus this time, likely due to the long time it was in the making. The major points are more optimization work, largely enhanced import handling and another improvement on the performance side. But there are also many bug fixes, more test coverage, usability and compatibility. Something esp. noteworthy to me and valued is that many important changes were performed or at least triggered by Nicolas Dumazet, who contributed a lot of high quality commits as you can see from the gitweb history. He appears to try and compile Mercurial and Nuitka, and this resulted in important contributions. Bug fixes ========= - Nicolas found a reference counting bug with nested parameter calls. Where a function had parameters of the form ``a, (b,c)`` it could crash. This got fixed and covered with a reference count test. - Another reference count problem when accessing the locals dictionary was corrected. - Values ``0.0`` and ``-0.0`` were treated as the same. They are not though, they have a different sign that should not get lost. - Nested contractions didn't work correctly, when the contraction was to iterate over another contraction which needs a closure. The problem was addressing by splitting the building of a contraction from the body of the contraction, so that these are now 2 nodes, making it easy for the closure handling to get things right. - Global statements in function with local ``exec()`` would still use the value from the locals dictionary. Nuitka is now compatible to CPython with this too. - Nicolas fixed problems with modules of the same name inside different packages. We now use the full name including parent package names for code generation and look-ups. - The ``__module__`` attribute of classes was only set after the class was created. Now it is already available in the class body. - The ``__doc__`` attribute of classes was not set at all. Now it is. - The relative import inside nested packages now works correctly. With Nicolas moving all of Nuitka to a package, the compile itself exposed many weaknesses. - A local re-raise of an exception didn't have the original line attached but the re-raise statement line. New Features ============ - Modules and packages have been unified. Packages can now also have code in "__init__.py" and then it will be executed when the package is imported. - Nicolas added the ability to create deep output directory structures without having to create them beforehand. This makes ``--output-dir=some/deep/path`` usable. - Parallel build by Scons was added as an option and enabled by default, which enhances scalability for ``--deep`` compilations a lot. - Nicolas enhanced the CPU count detection used for the parallel build. Turned out that ``multithreading.cpu_count()`` doesn't give us the number of available cores, so he contributed code to determine that. - Support for upcoming g++ 4.6 has been added. The use of the new option ``--lto`` has been been prepared, but right now it appears that the C++ compiler will need more fixes, before we can this feature with Nuitka. - The ``--display-tree`` feature got an overhaul and now displays the node tree along with the source code. It puts the cursor on the line of the node you selected. Unfortunately I cannot get it to work two-way yet. I will ask for help with this in a separate posting as we can really use a "python-qt" expert it seems. - Added meaningful error messages in the "file not found" case. Previously I just didn't care, but we sort of approach end user usability with this. Optimization ============ - Added optimization for the built-in ``range()`` which otherwise requires a module and ``builtin`` module lookup, then parameter parsing. Now this is much faster with Nuitka and small ranges (less than 256 values) are converted to constants directly, avoiding run time overhead entirely. - Code for re-raise statements now use a simple re-throw of the exception where possible, and only do the hard work where the re-throw is not inside an exception handler. - Constant folding of operations and comparisons is now performed if the operands are constants. - Values of some built-ins are pre-computed if the operands are constants. - The value of module attribute ``__name__`` is replaced by a constant unless it is assigned to. This is the first sign of upcoming constant propagation, even if only a weak one. - Conditional statement and/or their branches are eliminated where constant conditions allow it. Cleanups ======== - Nicolas moved the Nuitka source code to its own ``nuitka`` package. That is going to make packaging it a lot easier and allows cleaner code. - Nicolas introduced a fast path in the tree building which often delegates (or should do that) to a function. This reduced a lot of the dispatching code and highlights more clearly where such is missing right now. - Together we worked on the line length issues of Nuitka. We agreed on a style and very long lines will vanish from Nuitka with time. Thanks for pushing me there. - Nicolas also did provide many style fixes and general improvements, e.g. using ``PyObjectTemporary`` in more places in the C++ code, or not using ``str.find`` where ``x in y`` is a better choice. - The node structure got cleaned up towards the direction that assignments always have an assignment as a child. A function definition, or a class definition, are effectively assignments, and in order to not have to treat this as special cases everywhere, they need to have assignment targets as child nodes. Without such changes, optimization will have to take too many things into account. This is not yet completed. - Nicolas merged some node tree building functions that previously handled deletion and assigning differently, giving us better code reuse. - The constants code generation was moved to a ``__constants.cpp`` where it doesn't make __main__.cpp so much harder to read anymore. - The module declarations have been moved to their own header files. - Nicolas cleaned up the scripts used to test Nuitka big time, removing repetitive code and improving the logic. Very much appreciated. - Nicolas also documented a things in the Nuitka source code or got me to document things that looked strange, but have reasons behind it. - Nicolas solved the ``TODO`` related to built-in module accesses. These will now be way faster than before. - Nicolas also solved the ``TODO`` related to the performance of "locals dict" variable accesses. - Generator.py no longer contains classes. The Contexts objects are supposed to contain the state, and as such the generator objects never made much sense. - Also with the help of Scons community, I figured out how to avoid having object files inside the ``src`` directory of Nuitka. That should also help packaging, now all build products go to the .build directory as they should. - The vertical white space of the generated C++ got a few cleanups, trailing/leading new line is more consistent now, and there were some assertions added that it doesn't happen. New Tests ========= - The CPython 2.6 tests are now also run by CPython 2.7 and the other way around and need to report the same test failure reports, which found a couple of issues. - Now the test suite is run with and without ``--debug`` mode. - Basic tests got extended to cover more topics and catch more issues. - Program tests got extended to cover code in packages. - Added more exec scope tests. Currently inlining of exec statements is disabled though, because it requires entirely different rules to be done right, it has been pushed back to the next release. Organisational ============== - The ``g++-nuitka`` script is no more. With the help of the Scons community, this is now performed inside the scons and only once instead of each time for every C++ file. - When using ``--debug``, the generated C++ is compiled with ``-Wall`` and ``-Werror`` so that some form of bugs in the generated C++ code will be detected immediately. This found a few issues already. - There is a new git merge policy in place. Basically it says, that if you submit me a pull request, that I will deal with it before publishing anything new, so you can rely on the current git to provide you a good base to work on. I am doing more frequent pre-releases already and I would like to merge from your git. - The "README.txt" was updated to reflect current optimization status and plans. There is still a lot to do before constant propagation can work, but this explains things a bit better now. I hope to expand this more and more with time. - There is now a "misc/clean-up.sh" script that prints the commands to erase all the temporary files sticking around in the source tree. That is for you if you like me, have other directories inside, ignored, that you don't want to delete. - Then there is now a script that prints all source filenames, so you can more easily open them all in your editor. - And very important, there is now a "check-release.sh" script that performs all the tests I think should be done before making a release. - Pylint got more happy with the current Nuitka source. In some places, I added comments where rules should be granted exceptions. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.5 (driven by python 2.6): .. code:: Pystone(1.1) time for 50000 passes = 0.31 This machine benchmarks at 161290 pystones/second This is 109% for 0.3.5, up from 91% before. Overall this release is primarily an improvement in the domain of compatibility and contains important bug and feature fixes to the users. The optimization framework only makes a first showing of with the framework to organize them. There is still work to do to migrate optimization previously present It will take more time before we will see effect from these. I believe that even more cleanups of ``TreeBuilding``, ``Nodes`` and ``CodeGeneration`` will be required, before everything is in place for the big jump in performance numbers. But still, passing 100% feels good. Time to rejoice. ********************** Nuitka Release 0.3.4 ********************** This new release of Nuitka has a focus on re-organizing the Nuitka generated source code and a modest improvement on the performance side. For a long time now, Nuitka has generated a single C++ file and asked the C++ compiler to translate it to an executable or shared library for CPython to load. This was done even when embedding many modules into one (the "deep" compilation mode, option ``--deep``). This was simple to do and in theory ought to allow the compiler to do the most optimization. But for large programs, the resulting source code could have exponential compile time behavior in the C++ compiler. At least for the GNU g++ this was the case, others probably as well. This is of course at the end a scalability issue of Nuitka, which now has been addressed. So the major advancement of this release is to make the ``--deep`` option useful. But also there have been a performance improvements, which end up giving us another boost for the "PyStone" benchmark. Bug fixes ========= - Imports of modules local to packages now work correctly, closing the small compatibility gap that was there. - Modules with a "-" in their name are allowed in CPython through dynamic imports. This lead to wrong C++ code created. (Thanks to Li Xuan Ji for reporting and submitting a patch to fix it.) - There were warnings about wrong format used for ``Ssize_t`` type of CPython. (Again, thanks to Li Xuan Ji for reporting and submitting the patch to fix it.) - When a wrong exception type is raised, the traceback should still be the one of the original one. - Set and dict contractions (Python 2.7 features) declared local variables for global variables used. This went unnoticed, because list contractions don't generate code for local variables at all, as they cannot have such. - Using the ``type()`` built-in to create a new class could attribute it to the wrong module, this is now corrected. New Features ============ - Uses Scons to execute the actual C++ build, giving some immediate improvements. - Now caches build results and Scons will only rebuild as needed. - The direct use of ``__import__()`` with a constant module name as parameter is also followed in "deep" mode. With time, non-constants may still become predictable, right now it must be a real CPython constant string. Optimization ============ - Added optimization for the built-ins ``ord()`` and ``chr()``, these require a module and built-in module lookup, then parameter parsing. Now these are really quick with Nuitka. - Added optimization for the ``type()`` built-in with one parameter. As above, using from builtin module can be very slow. Now it is instantaneous. - Added optimization for the ``type()`` built-in with three parameters. It's rarely used, but providing our own variant, allowed to fix the bug mentioned above. Cleanups ======== - Using scons is a big cleanup for the way how C++ compiler related options are applied. It also makes it easier to re-build without Nuitka, e.g. if you were using Nuitka in your packages, you can easily build in the same way than Nuitka does. - Static helpers source code has been moved to ".hpp" and ".cpp" files, instead of being in ".py" files. This makes C++ compiler messages more readable and allows us to use C++ mode in Emacs etc., making it easier to write things. - Generated code for each module ends up in a separate file per module or package. - Constants etc. go to their own file (although not named sensible yet, likely going to change too) - Module variables are now created by the ``CPythonModule`` node only and are unique, this is to make optimization of these feasible. This is a pre-step to module variable optimization. New Tests ========= - Added "ExtremeClosure" from my Python quiz, it was not covered by existing tests. - Added test case for program that imports a module with a dash in its name. - Added test case for main program that starts with a dash. - Extended the built-in tests to cover ``type()`` as well. Organisational ============== - There is now a new environment variable ``NUITKA_SCONS`` which should point to the directory with the ``SingleExe.scons`` file for Nuitka. The scons file could be named better, because it is actually one and the same who builds extension modules and executables. - There is now a new environment variable ``NUITKA_CPP`` which should point to the directory with the C++ helper code of Nuitka. - The script "create-environment.sh" can now be sourced (if you are in the top level directory of Nuitka) or be used with eval. In either case it also reports what it does. .. admonition:: Update The script has become obsolete now, as the environment variables are no longer necessary. - To cleanup the many "Program.build" directories, there is now a "clean-up.sh" script for your use. Can be handy, but if you use git, you may prefer its clean command. .. admonition:: Update The script has become obsolete now, as Nuitka test executions now by default delete the build results. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.4: .. code:: Pystone(1.1) time for 50000 passes = 0.34 This machine benchmarks at 147059 pystones/second This is 91% for 0.3.4, up from 80% before. ********************** Nuitka Release 0.3.3 ********************** This release of Nuitka continues the focus on performance. It also cleans up a few open topics. One is "doctests", these are now extracted from the CPython 2.6 test suite more completely. The other is that the CPython 2.7 test suite is now passed completely. There is some more work ahead though, to extract all of the "doctests" and to do that for both versions of the tests. This means an even higher level of compatibility has been achieved, then there is performance improvements, and ever cleaner structure. Bug fixes ========= Generators ---------- - Generator functions tracked references to the common and the instance context independently, now the common context is not released before the instance contexts are. - Generator functions didn't check the arguments to ``throw()`` the way they are in CPython, now they do. - Generator functions didn't trace exceptions to "stderr" if they occurred while closing unfinished ones in "del". - Generator functions used the slightly different wordings for some error messages. Function Calls -------------- - Extended call syntax with ``**`` allows that to use a mapping, and it is now checked if it really is a mapping and if the contents has string keys. - Similarly, extended call syntax with ``*`` allows a sequence, it is now checked if it really is a sequence. - Error message for duplicate keyword arguments or too little arguments now describe the duplicate parameter and the callable the same way CPython does. - Now checks to the keyword argument list first before considering the parameter counts. This is slower in the error case, but more compatible with CPython. Classes ------- - The "locals()" built-in when used in the class scope (not in a method) now is correctly writable and writes to it change the resulting class. - Name mangling for private identifiers was not always done entirely correct. Others ------ - Exceptions didn't always have the correct stack reported. - The pickling of some tuples showed that "cPickle" can have non-reproducible results, using "pickle" to stream constants now Optimization ============ - Access to instance attributes has become faster by writing specific code for the case. This is done in JIT way, attempting at run time to optimize attribute access for instances. - Assignments now often consider what's cheaper for the other side, instead of taking a reference to a global variable, just to have to release it. - The function call code built argument tuples and dictionaries as constants, now that is true for every tuple usage. Cleanups ======== - The static helper classes, and the prelude code needed have been moved to separate C++ files and are now accessed "#include". This makes the code inside C++ files as opposed to a Python string and therefore easier to read and or change. New Features ============ - The generator functions and generator expressions have the attribute "gi_running" now. These indicate if they are currently running. New Tests ========= - The script to extract the "doctests" from the CPython test suite has been rewritten entirely and works with more doctests now. Running these tests created increased the test coverage a lot. - The Python 2.7 test suite has been added. Organisational ============== - One can now run multiple "compare_with_cpython" instances in parallel, which enables background test runs. - There is now a new environment variable "NUITKA_INCLUDE" which needs to point to the directory Nuitka's C++ includes live in. Of course the "create-environment.sh" script generates that for you easily. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.3: .. code:: Pystone(1.1) time for 50000 passes = 0.36 This machine benchmarks at 138889 pystones/second This is 80% for 0.3.3, up from 66% before. ********************** Nuitka Release 0.3.2 ********************** This release of Nuitka continues the focus on performance. But this release also revisits the topic of feature parity. Before, feature parity had been reached "only" with Python 2.6. This is of course a big thing, but you know there is always more, e.g. Python 2.7. With the addition of set contractions and dict contractions in this very release, Nuitka is approaching Python support for 2.7, and then there are some bug fixes. Bug fixes ========= - Calling a function with ``**`` and using a non-dict for it was leading to wrong behavior. Now a mapping is good enough as input for the ``**`` parameter and it's checked. - Deeply nested packages "package.subpackage.module" were not found and gave a warning from Nuitka, with the consequence that they were not embedded in the executable. They now are. - Some error messages for wrong parameters didn't match literally. For example "function got multiple..." as opposed to "function() got multiple..." and alike. - Files that ended in line with a "#" but without a new line gave an error from "ast.parse". As a workaround, a new line is added to the end of the file if it's "missing". - More correct exception locations for complex code lines. I noted that the current line indication should not only be restored when the call at hand failed, but in any case. Otherwise sometimes the exception stack would not be correct. It now is - more often. Right now, this has no systematic test. - Re-raised exceptions didn't appear on the stack if caught inside the same function, these are now correct. - For ``exec`` the globals argument needs to have "__builtins__" added, but the check was performed with the mapping interface. That is not how CPython does it, and so e.g. the mapping could use a default value for "__builtins__" which could lead to incorrect behavior. Clearly a corner case, but one that works fully compatible now. Optimization ============ - The local and shared local variable C++ classes have a flag "free_value" to indicate if an "PY_DECREF" needs to be done when releasing the object. But still the code used "Py_XDECREF" (which allows for "NULL" values to be ignored.) when the releasing of the object was done. Now the inconsistency of using "NULL" as "object" value with "free_value" set to true was removed. - Tuple constants were copied before using them without a point. They are immutable anyway. Cleanups ======== - Improved more of the indentation of the generated C++ which was not very good for contractions so far. Now it is. Also assignments should be better now. - The generation of code for contractions was made more general and templates split into multiple parts. This enabled reuse of the code for list contractions in dictionary and set contractions. - The with statement has its own template now and got cleaned up regarding indentation. New Tests ========= - There is now a script to extract the "doctests" from the CPython test suite and it generates Python source code from them. This can be compiled with Nuitka and output compared to CPython. Without this, the doctest parts of the CPython test suite is mostly useless. Solving this improved test coverage, leading to many small fixes. I will dedicate a later posting to the tool, maybe it is useful in other contexts as well. - Reference count tests have been expanded to cover assignment to multiple assignment targets, and to attributes. - The deep program test case, now also have a module in a sub-package to cover this case as well. Organisational ============== - The `gitweb interface `__ (since disabled) might be considered an alternative to downloading the source if you want to provide a pointer, or want to take a quick glance at the source code. You can already download with git, follow the link below to the page explaining it. - The "README.txt" has documented more of the differences and I consequently updated the Differences page. There is now a distinction between generally missing functionality and things that don't work in ``--deep`` mode, where Nuitka is supposed to create one executable. I will make it a priority to remove the (minor) issues of ``--deep`` mode in the next release, as this is only relatively little work, and not a good difference to have. We want these to be empty, right? But for the time being, I document the known differences there. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.2: .. code:: Pystone(1.1) time for 50000 passes = 0.39 This machine benchmarks at 128205 pystones/second This is 66% for 0.3.2, slightly up from the 58% of 0.3.1 before. The optimization done were somewhat fruitful, but as you can see, they were also more cleanups, not the big things. ********************** Nuitka Release 0.3.1 ********************** This release of Nuitka continues the focus on performance and contains only cleanups and optimization. Most go into the direction of more readable code, some aim at making the basic things faster, with good results as to performance as you can see below. Optimization ============ - Constants in conditions of conditional expressions (``a if cond else d``), ``if``/``elif`` or ``while`` are now evaluated to ``true`` or ``false`` directly. Before there would be temporary python object created from it which was then checked if it had a truth value. All of that is obviously overhead only. And it hurts the typically ``while 1:`` infinite loop case badly. - Do not generate code to catch ``BreakException`` or ``ContinueException`` unless a ``break`` or ``continue`` statement being in a ``try: finally:`` block inside that loop actually require this. Even while uncaught exceptions are cheap, it is still an improvement worthwhile and it clearly improves the readability for the normal case. - The compiler more aggressively prepares tuples, lists and dicts from the source code as constants if their contents is "immutable" instead of building at run time. An example of a "mutable" tuple would be ``({},)`` which is not safe to share, and therefore will still be built at run time. For dictionaries and lists, copies will be made, under the assumption that copying a dictionary will always be faster, than making it from scratch. - The parameter parsing code was dynamically building the tuple of argument names to check if an argument name was allowed by checking the equivalent of ``name in argument_names``. This was of course wasteful and now a pre-built constant is used for this, so it should be much faster to call functions with keyword arguments. - There are new templates files and also actual templates now for the ``while`` and ``for`` loop code generation. And I started work on having a template for assignments. Cleanups ======== - Do not generate code for the else of ``while`` and ``for`` loops if there is no such branch. This uncluttered the generated code somewhat. - The indentation of the generated C++ was not very good and whitespace was often trailing, or e.g. a real tab was used instead of "\t". Some things didn't play well together here. Now much of the generated C++ code is much more readable and white space cleaner. For optimization to be done, the humans need to be able to read the generated code too. Mind you, the aim is not to produce usable C++, but on the other hand, it must be possible to understand it. - To the same end of readability, the empty ``else {}`` branches are avoided for ``if``, ``while`` and ``for`` loops. While the C++ compiler can be expected to remove these, they seriously cluttered up things. - The constant management code in ``Context`` was largely simplified. Now the code is using the ``Constant`` class to find its way around the problem that dicts, sets, etc. are not hashable, or that ``complex`` is not being ordered; this was necessary to allow deeply nested constants, but it is also a simpler code now. - The C++ code generated for functions now has two entry points, one for Python calls (arguments as a list and dictionary for parsing) and one where this has happened successfully. In the future this should allow for faster function calls avoiding the building of argument tuples and dictionaries all-together. - For every function there was a "traceback adder" which was only used in the C++ exception handling before exit to CPython to add to the traceback object. This was now in-lined, as it won't be shared ever. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.1: .. code:: Pystone(1.1) time for 50000 passes = 0.41 This machine benchmarks at 121951 pystones/second This is 58% for 0.3.1, up from the 25% before. So it's getting somewhere. As always you will find its latest version here. ********************** Nuitka Release 0.3.0 ********************** This release 0.3.0 is the first release to focus on performance. In the 0.2.x series Nuitka achieved feature parity with CPython 2.6 and that was very important, but now it is time to make it really useful. Optimization has been one of the main points, although I was also a bit forward looking to Python 2.7 language constructs. This release is the first where I really started to measure things and removed the most important bottlenecks. New Features ============ - Added option to control ``--debug``. With this option the C++ debug information is present in the file, otherwise it is not. This will give much smaller ".so" and ".exe" files than before. - Added option ``--no-optimization`` to disable all optimization. It enables C++ asserts and compiles with less aggressive C++ compiler optimization, so it can be used for debugging purposes. - Support for Python 2.7 set literals has been added. Performance Enhancements ======================== - Fast global variables: Reads of global variables were fast already. This was due to a trick that is now also used to check them and to do a much quicker update if they are already set. - Fast ``break``/``continue`` statements: To make sure these statements execute the finally handlers if inside a try, these used C++ exceptions that were caught by ``try``/``finally`` in ``while`` or ``for`` loops. This was very slow and had very bad performance. Now it is checked if this is at all necessary and then it's only done for the rare case where a ``break``/``continue`` really is inside the tried block. Otherwise it is now translated to a C++ ``break``/``continue`` which the C++ compiler handles more efficiently. - Added ``unlikely()`` compiler hints to all errors handling cases to allow the C++ compiler to generate more efficient branch code. - The for loop code was using an exception handler to make sure the iterated value was released, using ``PyObjectTemporary`` for that instead now, which should lead to better generated code. - Using constant dictionaries and copy from them instead of building them at run time even when contents was constant. New Tests ========= - Merged some bits from the CPython 2.7 test suite that do not harm 2.6, but generally it's a lot due to some ``unittest`` module interface changes. - Added CPython 2.7 tests ``test_dictcomps.py`` and ``test_dictviews.py`` which both pass when using Python 2.7. - Added another benchmark extract from "PyStone" which uses a while loop with break. Numbers ======= python 2.6: .. code:: Pystone(1.1) time for 50000 passes = 0.65 This machine benchmarks at 76923.1 pystones/second Nuitka 0.3.0: .. code:: Pystone(1.1) time for 50000 passes = 0.52 This machine benchmarks at 96153.8 pystones/second That's a 25% speedup now and a good start clearly. It's not yet in the range of where i want it to be, but there is always room for more. And the ``break``/``continue`` exception was an important performance regression fix. ********************** Nuitka Release 0.2.4 ********************** This release 0.2.4 is likely the last 0.2.x release, as it's the one that achieved feature parity with CPython 2.6, which was the whole point of the release series, so time to celebrate. I have stayed away (mostly) from any optimization, so as to not be premature. From now on speed optimization is going to be the focus though. Because right now, frankly, there is not much of a point to use Nuitka yet, with only a minor run time speed gain in trade for a long compile time. But hopefully we can change that quickly now. New Features ============ - The use of exec in a local function now adds local variables to scope it is in. - The same applies to ``from module_name import *`` which is now compiled correctly and adds variables to the local variables. Bug Fixes ========= - Raises ``UnboundLocalError`` when deleting a local variable with ``del`` twice. - Raises ``NameError`` when deleting a global variable with ``del`` twice. - Read of to uninitialized closure variables gave ``NameError``, but ``UnboundLocalError`` is correct and raised now. Cleanups ======== - There is now a dedicated pass over the node tree right before code generation starts, so that some analysis can be done as late as that. Currently this is used for determining which functions should have a dictionary of locals. - Checking the exported symbols list, fixed all the cases where a ``static`` was missing. This reduces the "module.so" sizes. - With gcc the "visibility=hidden" is used to avoid exporting the helper classes. Also reduces the "module.so" sizes, because classes cannot be made static otherwise. New Tests ========= - Added "DoubleDeletions" to cover behaviour of ``del``. It seems that this is not part of the CPython test suite. - The "OverflowFunctions" (those with dynamic local variables) now has an interesting test, exec on a local scope, effectively adding a local variable while a closure variable is still accessible, and a module variable too. This is also not in the CPython test suite. - Restored the parts of the CPython test suite that did local star imports or exec to provide new variables. Previously these have been removed. - Also "test_with.py" which covers PEP 343 has been reactivated, the with statement works as expected. ********************** Nuitka Release 0.2.3 ********************** This new release is marking a closing in on feature parity to CPython 2.6 which is an important mile stone. Once this is reached, a "Nuitka 0.3.x" series will strive for performance. Bug Fixes ========= - Generator functions no longer leak references when started, but not finished. - Yield can in fact be used as an expression and returns values that the generator user ``send()`` to it. Reduced Differences / New Features ================================== - Generator functions already worked quite fine, but now they have the ``throw()``, ``send()`` and ``close()`` methods. - Yield is now an expression as is ought to be, it returns values put in by ``send()`` on the generator user. - Support for extended slices: .. code:: python x = d[:42, ..., :24:, 24, 100] d[:42, ..., :24:, 24, 100] = "Strange" del d[:42, ..., :24:, 24, 100] Tests Work ========== - The "test_contextlib" is now working perfectly due to the generator functions having a correct ``throw()``. Added that test back, so context managers are now fully covered. - Added a basic test for "overflow functions" has been added, these are the ones which have an unknown number of locals due to the use of language constructs ``exec`` or ``from bla import *`` on the function level. This one currently only highlights the failure to support it. - Reverted removals of extended slice syntax from some parts of the CPython test suite. Cleanups ======== - The compiled generator types are using the new C++0x type safe enums feature. - Resolved a circular dependency between ``TreeBuilding`` and ``TreeTransforming`` modules. ********************** Nuitka Release 0.2.2 ********************** This is some significant progress, a lot of important things were addressed. Bug Fixes ========= - Scope analysis is now done during the tree building instead of sometimes during code generation, this fixed a few issues that didn't show up in tests previously. - Reference leaks of generator expressions that were not fishing, but then deleted are not more. - Inlining of exec is more correct now. - More accurate exception lines when iterator creation executes compiled code, e.g. in a for loop - The list of base classes of a class was evaluated in the context of the class, now it is done in the context of the containing scope. - The first iterated of a generator expression was evaluated in its own context, now it is done in the context of the containing scope. Reduced Differences =================== - With the enhanced scope analysis, ``UnboundLocalError`` is now correctly supported. - Generator expressions (but not yet functions) have a ``throw()``, ``send()`` and ``close()`` method. - Exec can now write to local function namespace even if ``None`` is provided at run time. - Relative imports inside packages are now correctly resolved at compile time when using ``--deep``. Cleanups ======== - The compiled function type got further enhanced and cleaned up. - The compiled generator expression function type lead to a massive cleanup of the code for generator expressions. - Cleaned up namespaces, was still using old names, or "Py*" which is reserved to core CPython. - Overhaul of the code responsible for ``eval`` and ``exec``, it has been split, and it pushed the detection defaults to the C++ compiler which means, we can do it at run time or compile time, depending on circumstances. - Made ``PyTemporaryObject`` safer to use, disabling copy constructor it should be also a relief to the C++ compiler if it doesn't have to eliminate all its uses. - The way delayed work is handled in ``TreeBuilding`` step has been changed to use closured functions, should be more readable. - Some more code templates have been created, making the code generation more readable in some parts. More to come. New Features ============ - As I start to consider announcing Nuitka, I moved the version logic so that the version can now be queried with ``--version``. Optimization ============ - Name lookups for ``None``, ``True`` and ``False`` and now always detected as constants, eliminating many useless module variable lookups. New Tests ========= - More complete test of generator expressions. - Added test program for packages with relative imports inside the package. - The built-in ``dir()`` in a function was not having fully deterministic output list, now it does. Summary ======= Overall, the amount of differences between CPython and Nuitka is heading towards zero. Also most of the improvements done in this release were very straightforward cleanups and not much work was required, mostly things are about cleanups and then it becomes easily right. The new type for the compiled generator expressions was simple to create, esp. as I could check what CPython does in its source code. For optimization purposes, I decided that generator expressions and generator functions will be separate compiled types, as most of their behavior will not be shared. I believe optimizing generator expressions to run well is an important enough goal to warrant that they have their own implementation. Now that this is done, I will repeat it with generator functions. Generator functions already work quite fine, but like generator expressions did before this release, they can leak references if not finished , and they don't have the ``throw()`` method, which seems very important to the correct operation of ``contextlib``. So I will introduce a decicated type for these too, possibly in the next release. ********************** Nuitka Release 0.2.1 ********************** The march goes on, this is another minor release with a bunch of substantial improvements: Bug Fixes ========= - Packages now also can be embedded with the ``--deep`` option too, before they could not be imported from the executable. - In-lined exec with their own future statements leaked these to the surrounding code. Reduced Differences =================== - The future print function import is now supported too. Cleanups ======== - Independence of the compiled function type. When I started it was merely ``PyCFunction`` and then a copy of it patched at run time, using increasingly less code from CPython. Now it's nothing at all anymore. - This lead to major cleanup of run time compiled function creation code, no more ``methoddefs``, ``PyCObject`` holding context, etc. - PyLint was used to find the more important style issues and potential bugs, also helping to identify some dead code. Summary ======= The major difference now is the lack of a throw method for generator functions. I will try to address that in a 0.2.2 release if possible. The plan is that the 0.2.x series will complete these tasks, and 0.3 could aim at some basic optimization finally. ******************** Nuitka Release 0.2 ******************** Good day, this is a major step ahead, improvements everywhere. Bug fixes ========= - Migrated the Python parser from the deprecated and problematic ``compiler`` module to the ``ast`` module which fixes the ``d[a,] = b`` parser problem. A pity it was not available at the time I started, but the migration was relatively painless now. - I found and fixed wrong encoding of binary data into C++ literals. Now Nuitka uses C++0x raw strings, and these problems are gone. - The decoding of constants was done with the ``marshal`` module, but that appears to not deeply care enough about unicode encoding it seems. Using ``cPickle`` now, which seems less efficient, but is more correct. - Another difference is gone: The ``continue`` and ``break`` inside loops do no longer prevent the execution of finally blocks inside the loop. Organisational ============== - I now maintain the "README.txt" in org-mode, and intend to use it as the issue tracker, but I am still a beginner at that. .. admonition:: Update Turned out I never master it, and used ReStructured Text instead. - There is a public git repository for you to track Nuitka releases. Make your changes and then ``git pull --rebase``. If you encounter conflicts in things you consider useful, please submit the patches and a pull request. When you make your clones of Nuitka public, use ``nuitka-unofficial`` or not the name ``Nuitka`` at all. - There is a now a mailing list (since closed). Reduced Differences =================== - Did you know you could write ``lambda : (yield something)`` and it gives you a lambda that creates a generator that produces that one value? Well, now Nuitka has support for lambda generator functions. - The ``from __future__ import division`` statement works as expected now, leading to some newly passing CPython tests. - Same for ``from __future__ import unicode_literals`` statement, these work as expected now, removing many differences in the CPython tests that use this already. New Features ============ - The ``Python`` binary provided and ``Nuitka.py`` are now capable of accepting parameters for the program executed, in order to make it even more of a drop-in replacement to ``python``. - Inlining of ``exec`` statements with constant expressions. These are now compiled at compile time, not at run time anymore. I observed that an increasing number of CPython tests use exec to do things in isolation or to avoid warnings, and many more these tests will now be more effective. I intend to do the same with eval expressions too, probably in a minor release. Summary ======= So give it a whirl. I consider it to be substantially better than before, and the list of differences to CPython is getting small enough, plus there is already a fair bit of polish to it. Just watch out that it needs gcc-4.5 or higher now. ********************** Nuitka Release 0.1.1 ********************** I just have just updated Nuitka to version 0.1.1 which is a bug fix release to 0.1, which corrects many of the small things: - Updated the CPython test suite to 2.6.6rc and minimized much of existing differences in the course. - Compiles standalone executable that includes modules (with --deep option), but packages are not yet included successfully. - Reference leaks with exceptions are no more. - ``sys.exc_info()`` works now mostly as expected (it's not a stack of exceptions). - More readable generated code, better organisation of C++ template code. - Restored debug option ``--g++-only``. The biggest thing probably is the progress with exception tracebacks objects in exception handlers, which were not there before (always ``None``). Having these in place will make it much more compatible. Also with manually raised exceptions and assertions, tracebacks will now be more correct to the line. On a bad news, I discovered that the ``compiler`` module that I use to create the AST from Python source code, is not only deprecated, but also broken. I created the `CPython bug `__ about it, basically it cannot distinguish some code of the form ``d[1,] = None`` from ``d[1] = None``. This will require a migration of the ``ast`` module, which should not be too challenging, but will take some time. I am aiming at it for a 0.2 release. Generating wrong code (Nuitka sees ``d[1] = None`` in both cases) is a show blocker and needs a solution. So, yeah. It's better, it's there, but still experimental. You will find its latest version here. Please try it out and let me know what you think in the comments section. **************************************************** Nuitka Release 0.1 (Releasing Nuitka to the World) **************************************************** Obviously this is very exciting step for me. I am releasing Nuitka today. Finally. For a long time I knew I would, but actually doing it, is a different beast. Reaching my goals for release turned out to be less far away than I hope, so instead of end of August, I can already release it now. Currently it's not more than 4% faster than CPython. No surprise there, if all you did, is removing the bytecode interpretation so far. It's not impressive at all. It's not even a reason to use it. But it's also only a start. Clearly, once I get into optimizing the code generation of Nuitka, it will only get better, and then probably in sometimes dramatic steps. But I see this as a long term goal. I want to have infrastructure in the code place, before doing lots of possible optimization that just make Nuitka unmaintainable. And I will want to have a look at what others did so far in the domain of type inference and how to apply that for my project. I look forward to the reactions about getting this far. The supported language volume is amazing, and I have a set of nice tricks used. For example the way generator functions are done is a clever hack. Where to go from here? Well, I guess, I am going to judge it by the feedback I receive. I personally see "constant propagation" as a laudable first low hanging fruit, that could be solved. Consider this readable code on the module level: .. code:: python meters_per_nautical_mile = 1852 def convertMetersToNauticalMiles(meters): return meters / meters_per_nautical_mile def convertNauticalMilesToMeters(miles): return miles * meters_per_nautical_mile Now imagine you are using this very frequently in code. Quickly you determine that the following will be much faster: .. code:: python def convertMetersToNauticalMiles(meters): return meters / 1852 def convertNauticalMilesToMeters(miles): return miles * 1852 Still good? Well, probably next step you are going to in-line the function calls entirely. For optimization, you are making your code less readable. I do not all appreciate that. My first goal is there to make the more readable code perform as well or better as the less readable variant. Nuitka-0.6.19.1/MANIFEST.in0000600000372100037210000000255214166627112022031 0ustar nuitka-buildslavenuitka-buildslave00000000000000include LICENSE.txt include MANIFEST.in include README.rst README.pdf include Changelog.rst Changelog.pdf include Developer_Manual.rst Developer_Manual.pdf include doc/*.1 include bin/compare_with_cpython include bin/compare_with_xml include bin/check-nuitka-with-pylint include bin/autoformat-nuitka-source include bin/measure-construct-performance # Runners, mainly for source distribution. include bin/nuitka include bin/nuitka-run include misc/*.sh include misc/*.bat include tests/run-tests include nuitka/plugins/standard/*.yml # Logo with source include doc/Logo/Nuitka-Logo-Symbol.svg include doc/Logo/Nuitka-Logo-Vertical.svg include doc/Logo/Nuitka-Logo-Horizontal.svg include doc/images/Nuitka-Logo-Symbol.png include doc/images/Nuitka-Logo-Vertical.png include doc/images/Nuitka-Logo-Horizontal.png recursive-include lib *.py # Core tests are included along with Nuitka itself. recursive-include tests/basics *.py recursive-include tests/syntax *.py recursive-include tests/packages *.py recursive-include tests/programs *.py include tests/programs/pkgutil_usage/package/DATA_FILE.txt recursive-include tests/optimizations *.py recursive-include tests/standalone *.py recursive-include tests/onefile *.py recursive-include tests/reflected *.py recursive-include tests/plugins *.py # C templates for code generation. recursive-include nuitka/codegen/templates_c *.j2 Nuitka-0.6.19.1/setup.cfg0000600000372100037210000000004614167275622022116 0ustar nuitka-buildslavenuitka-buildslave00000000000000[egg_info] tag_build = tag_date = 0 Nuitka-0.6.19.1/Developer_Manual.rst0000600000372100037210000045043014166627112024251 0ustar nuitka-buildslavenuitka-buildslave00000000000000######################### Nuitka Developer Manual ######################### .. image:: doc/images/Nuitka-Logo-Symbol.png :alt: Nuitka Logo .. contents:: The purpose of this Developer Manual is to present the current design of Nuitka, the project rules, and the motivations for choices made. It is intended to be a guide to the source code, and to give explanations that don't fit into the source code in comments form. It should be used as a reference for the process of planning and documenting decisions we made. Therefore we are e.g. presenting here the type inference plans before implementing them. And we update them as we proceed. It grows out of discussions and presentations made at conferences as well as private conversations or issue tracker. ************ Milestones ************ #. Feature parity with CPython, understand all the language construct and behave absolutely compatible. Feature parity has been reached for CPython 2.6 and 2.7. We do not target any older CPython release. For CPython 3.3 up to 3.8 it also has been reached. We do not target the older and practically unused CPython 3.0 to 3.2 releases. This milestone was reached. Dropping support for Python 2.6 and 3.3 is an option, should this prove to be any benefit. Currently it is not, as it extends the test coverage only. #. Create the most efficient native code from this. This means to be fast with the basic Python object handling. This milestone was reached, although of course, micro optimizations to this are happening all the time. #. Then do constant propagation, determine as many values and useful constraints as possible at compile time and create more efficient code. This milestone is considered almost reached. We continue to discover new things, but the infrastructure is there, and these are easy to add. #. Type inference, detect and special case the handling of strings, integers, lists in the program. This milestone is considered in progress. #. Add interfacing to C code, so Nuitka can turn a ``ctypes`` binding into an efficient binding as written with C. This milestone is planned only. #. Add hints module with a useful Python implementation that the compiler can use to learn about types from the programmer. This milestone is planned only. ***************** Version Numbers ***************** For Nuitka we use a defensive version numbering system to indicate that it is not yet ready for everything. We have defined milestones and the version numbers should express which of these, we consider done. - So far: Before milestone 1, we used ``0.1.x`` version numbers. After reaching it, we used ``0.2.x`` version numbers. Before milestone 2 and 3, we used ``0.3.x`` version numbers. After almost reaching 3, and beginning with 4, we use "0.4.x" version numbers. Due to an interface change, ``0.5.x`` version numbers are being used. Due to reaching type inference in code generation, even if only starting, the ``0.6.x`` version numbers were started to be used. This stage should allow quick progress in performance for individual releases. - Future: With ``ctypes`` bindings in a usable state it will be ``0.7.x``. - Final: We will then round it up and call it Nuitka ``1.0`` when this works as expected for a bunch of people. The plan is to reach this goal during 2021. This is based on positive assumptions that may not hold up though. Of course, all of this may be subject to change. *************** Current State *************** Nuitka top level works like this: - ``nuitka.tree.Building`` outputs node tree - ``nuitka.optimization`` enhances it as best as it can - ``nuitka.finalization`` prepares the tree for code generation - ``nuitka.codegen.CodeGeneration`` orchestrates the creation of code snippets - ``nuitka.codegen.*Codes`` knows how specific code kinds are created - ``nuitka.MainControl`` keeps it all together This design is intended to last. Regarding types, the state is: - Types are always ``PyObject *``, and only a few C types, e.g. ``nuitka_bool`` and ``nuitka_void`` and more are coming. Even for objects, often it's know that things are e.g. really a ``PyTupleObject **``, but no C type is available for that yet. - There are a some specific use of types beyond "compile time constant", that are encoded in type and value shapes, which can be used to predict some operations, conditions, etc. if they raise, and result types they give. - In code generation, the supported C types are used, and sometimes we have specialized code generation, e.g. a binary operation that takes an ``int`` and a ``float`` and produces a ``float`` value. There will be fallbacks to less specific types. The expansion with more C types is currently in progress, and there will also be alternative C types, where e.g. ``PyObject *`` and ``C long`` are in an enum that indicates which value is valid, and where special code will be available that can avoid creating the ``PyObject **`` unless the later overflows. *************************************************** Setting up the Development Environment for Nuitka *************************************************** Currently there are very different kinds of files that we need support for. This is best addressed with an IDE. We cover here how to setup the most common one. Visual Studio Code ================== Download Visual Studio Code from here: https://code.visualstudio.com/download At this time, this is the recommended IDE for Linux and Windows. This is going to cover the plugins to install. Configuration is part of the ``.vscode`` in your Nuitka checkout. If you are not familiar with Eclipse, this is Free Software IDE,designed to be universally extended, and it truly is. There are plugins available for nearly everything. The extensions to be installed are part of the Visual Code recommendations in ``.vscode/extensions.json`` and you will be prompted about that and ought to install these. Eclipse / PyCharm ================= Don't use these anymore, we consider Visual Studio Code to be far superior for delivering a nice out of the box environment. ************************* Commit and Code Hygiene ************************* In Nuitka we have tools to autoformat code, you can execute them manually, but it's probably best to execute them at commit time, to make sure when we share code, it's already well format, and to avoid noise doing cleanups. The kinds of changes also often cause unnecessary merge conflicts, while the autoformat is designed to format code also in a way that it avoids merge conflicts in the normal case, e.g. by doing imports one item per line. In order to set up hooks, you need to execute these commands: .. code:: bash # Where python is the one you use with Nuitka, this then gets all # development requirements, can be full PATH. python -m pip install -r requirements-devel.txt python ./misc/install-git-hooks.py These commands will make sure that the ``autoformat-nuitka-source`` is run on every staged file content at the time you do the commit. For C files, it may complain unavailability of ``clang-format``, follow it's advice. You may call the above tool at all times, without arguments to format call Nuitka source code. Should you encounter problems with applying the changes to the checked out file, you can always execute it with ``COMMIT_UNCHECKED=1`` environment set. ********************* Coding Rules Python ********************* These rules should generally be adhered when working on Nuitka code. It's not library code and it's optimized for readability, and avoids all performance optimization for itself. Tool to format ============== There is a tool ``bin/autoformat-nuitka-source`` which is to apply automatic formatting to code as much as possible. It uses ``black`` (internally) for consistent code formatting. The imports are sorted with ``isort`` for proper order. The tool (mostly ``black`` and ``isort``) encodes all formatting rules, and makes the decisions for us. The idea being that we can focus on actual code and do not have to care as much about other things. It also deals with Windows new lines, trailing space, etc. and even sorts pylint disable statements. Identifiers =========== Classes are camel case with leading upper case. Functions and methods are with leading verb in lower case, but also camel case. Variables and arguments are lower case with ``_`` as a separator. .. code:: python class SomeClass: def doSomething(some_parameter): some_var = ("foo", "bar") Base classes that are abstract have their name end with ``Base``, so that a meta class can use that convention, and readers immediately know, that it will not be instantiated like that. Function calls use keyword argument preferably. These are slower in CPython, but more readable: .. code:: python getSequenceCreationCode( sequence_kind=sequence_kind, element_identifiers=identifiers, context=context ) When the names don't add much value, sequential calls can be done: .. code:: python context.setLoopContinueTarget(handler_start_target) Here, ``setLoopContinueTarget`` will be so well known that the reader is expected to know the argument names and their meaning, but it would be still better to add them. But in this instance, the variable name already indicates that it is. Module/Package Names ==================== Normal modules are named in camel case with leading upper case, because of their role as singleton classes. The difference between a module and a class is small enough and in the source code they are also used similarly. For the packages, no real code is allowed in their ``__init__.py`` and they must be lower case, like e.g. ``nuitka`` or ``codegen``. This is to distinguish them from the modules. Packages shall only be used to group things. In ``nuitka.codegen`` the code generation packages are located, while the main interface is ``nuitka.codegen.CodeGeneration`` and may then use most of the entries as local imports. There is no code in packages themselves. For programs, we use ``__main__`` package to carry the actual code. Names of modules should be plurals if they contain classes. Example is that a ``Nodes`` module that contains a ``Node`` class. Names for context manages start with ``with`` ============================================= In order to easily recognize that something is to be used as a context manager, we follow a pattern of naming them ``withSomething``, to make that easily recognized. .. code:: python with withEnvironmentPathAdded(os.path.join(sys.prefix, "bin")): with withDirectoryChange(self.qt_datadir): ... This makes these easy to recognize even in their definition. Prefer list contractions over built-ins ======================================= This concerns ``map``, ``filter``, and ``apply``. Usage of these built-ins is highly discouraged within Nuitka source code. Using them is considered worth a warning by "PyLint" e.g. "Used built-in function 'map'". We should use list contractions instead, because they are more readable. List contractions are a generalization for all of them. We love readability and with Nuitka as a compiler, there won't be any performance difference at all. There are cases where a list contraction is faster because you can avoid to make a function call. And there may be cases, where map is faster, if a function must be called. These calls can be very expensive in CPython, and if you introduce a function, just for ``map``, then it might be slower. But of course, Nuitka is the project to free us from what is faster and to allow us to use what is more readable, so whatever is faster, we don't care. We make all options equally fast and let people choose. For Nuitka the choice is list contractions as these are more easily changed and readable. Look at this code examples from Python: .. code:: python class A: def getX(self): return 1 x = property(getX) class B(A): def getX(self): return 2 A().x == 1 # True B().x == 1 # True (!) This pretty much is what makes properties bad. One would hope ``B().x`` to be ``2``, but instead it's not changed. Because of the way properties take the functions and not members, and because they then are not part of the class, they cannot be overloaded without re-declaring them. Overloading is then not at all obvious anymore. Now imagine having a setter and only overloading the getter. How to update the property easily? So, that's not likable about them. And then we are also for clarity in these internal APIs too. Properties try and hide the fact that code needs to run and may do things. So let's not use them. For an external API you may exactly want to hide things, but internally that has no use, and in Nuitka, every API is internal API. One exception may be the ``hints`` module, which will gladly use such tricks for an easier write syntax. **************** Coding Rules C **************** For the static C parts, e.g. compiled types, helper codes, the ``clang-format`` from LLVM project is used, the tool ``autoformat-nuitka-source`` does this for us. We always have blocks for conditional statements to avoid typical mistakes made by adding a statement to a branch, forgetting to make it a block. ********************** The "git flow" model ********************** - The flow is used for releases and occasionally subsequent hot fixes. A few feature branches were used so far. It allows for quick delivery of fixes to both the stable and the development version, supported by a git plug-in, that can be installed via "apt-get install git-flow". - Stable (``main`` branch) The stable version, is expected to pass all the tests at all times and is fully supported. As soon as bugs are discovered, they are fixed as hot fixes, and then merged to develop by the "git flow" automatically. - Development (``develop`` branch) The future release, supposedly in almost ready for release state at nearly all times, but this is as strict. It is not officially supported, and may have problems and at times inconsistencies. Normally this branch is supposed to not be rebased. For severe problems it may be done though. - Factory (default feature branch) Code under construction. We publish commits there, that may not hold up in testing, and before it enters develop branch. Factory may have severe regressions frequently, and commits become **rebased all the time**, so do not base your patches on it, please prefer the ``develop`` branch for that, unless of course, it's about factory code itself. - Personal branches (jorj, orsiris, others as well) We are currently not using this, but it's an option. - Feature Branches We are not currently using these. They could be used for long lived changes that extend for multiple release cycles and are not ready yet. Currently we perform all changes in steps that can be included in releases or delay making those changes. ****************************** Nuitka "git/github" Workflow ****************************** - Forking and cloning You need to have git installed and GitHub account. Goto Nuitka repository and fork the repository. To clone it to your local machine execute the following your git bash: .. code:: bash git clone https://github.com/your-user-name/Nuitka.git cd Nuitka git remote add upstream https://github.com/Nuitka/Nuitka.git - Create a Branch .. code:: bash git checkout develop git pull --rebase upstream git checkout -b feature_branch If you are having merge conflicts while doing the previous step, then check out (DON'T FORGET TO SAVE YOUR CHANGES FIRST IF ANY): - In case you have an existing branch rebase it to develop .. code:: bash git fetch upstream git rebase upstream/develop Fix the merge conflicts if any, stash them and continue: .. code:: bash git rebase --continue If anything goes wrong while rebasing: .. code:: bash git rebase --abort - Making changes .. code:: bash git commit -a -m "Commit Message" git push -u origin # once, later always: git push ********************************** API Documentation and Guidelines ********************************** There is API documentation generated with ``doxygen``, available at `this location `__ . To ensure meaningful ``doxygen`` output, the following guidelines must be observed when creating or updating Python source: Use of Standard Python ``__doc__`` Strings ========================================== Every class and every method should be documented via the standard Python delimiters (``""" ... """``) in the usual way. Special ``doxygen`` Anatomy of ``__doc__`` ========================================== .. note:: We are replacing doxygen with sphinx, this is all obsolete - Immediately after the leading ``"""``, and after 1 space on the same line, enter a brief description or title of the class or method. This must be 1 line and be followed by at least 1 empty line. - Depending on the item, choose from the following "sections" to describe what the item is and does. Each section name is coded on its own line, aligned with the leading ``"""`` and followed by a colon ":". Anything following the section, must start on a new line and be indented by 4 spaces relative to the section. Except for the first section (``Notes:``) after the title, sections need not be preceded by empty lines -- but it is good practice to still do that. - ``Notes:`` detailed description of the item, any length. May contain line breaks with each new line starting aligned with previous one. The text will automatically be joined across line breaks and be reformatted in the browser. If you describe details for a class, you can do so **without** using this section header and all formatting will still work fine. If you however omit the ``Notes:`` for methods, then the text will be interpreted **as code**, be shown in an ugly monospaced font, and no automatic line breaks will occur in the browser. - ``Args:`` positional arguments. Each argument then follows, starting on a new line and indented by 4 spaces. The argument name must be followed by a colon ``:`` or double hash ``--``, followed by a description of arbitrary length. The description can be separated by line breaks. - ``Kwargs:`` keyword arguments. Same rules as for args. - ``Returns:`` description of what will be returned if applicable (any length). - ``Yields:`` synonymous for ``Returns:``. - ``Raises:`` name any exceptions that may be raised. - ``Examples:`` specify any example code. .. code:: python def foo(p1, p2, kw1=None, kw2=None): """This is an example method. Notes: It does one or the other indispensable things based on some parameters and proudly returns a dictionary. Args: p1: parameter one p2: parameter two Kwargs: kw1: keyword one kw2: keyword two Returns: A dictionary calculated from the input. Raises: ValueError, IndexError Examples: >>> foo(1, 2, kw1=3, kw2=4) {'a': 4, 'b': 6} """ ********************* Checking the Source ********************* The static checking for errors is currently done with ``PyLint``. In the future, Nuitka itself will gain the ability to present its findings in a similar way, but this is not a priority, and we are not there yet. So, we currently use ``PyLint`` with options defined in a script. .. code:: bash ./bin/check-nuitka-with-pylint The above command is expected to give no warnings. It is also run on our CI and we will not merge branches that do not pass. ******************* Running the Tests ******************* This section describes how to run Nuitka tests. Running all Tests ================= The top level access to the tests is as simple as this: .. code:: bash ./tests/run-tests For fine grained control, it has the following options: .. code:: --skip-basic-tests The basic tests, execute these to check if Nuitka is healthy. Default is True. --skip-syntax-tests The syntax tests, execute these to check if Nuitka handles Syntax errors fine. Default is True. --skip-program-tests The programs tests, execute these to check if Nuitka handles programs, e.g. import recursions, etc. fine. Default is True. --skip-package-tests The packages tests, execute these to check if Nuitka handles packages, e.g. import recursions, etc. fine. Default is True. --skip-optimizations-tests The optimization tests, execute these to check if Nuitka does optimize certain constructs fully away. Default is True. --skip-standalone-tests The standalone tests, execute these to check if Nuitka standalone mode, e.g. not referring to outside, important 3rd library packages like PyQt fine. Default is True. --skip-reflection-test The reflection test compiles Nuitka with Nuitka, and then Nuitka with the compile Nuitka and compares the outputs. Default is True. --skip-cpython26-tests The standard CPython2.6 test suite. Execute this for all corner cases to be covered. With Python 2.7 this covers exception behavior quite well. Default is True. --skip-cpython27-tests The standard CPython2.7 test suite. Execute this for all corner cases to be covered. With Python 2.6 these are not run. Default is True. --skip-cpython32-tests The standard CPython3.2 test suite. Execute this for all corner cases to be covered. With Python 2.6 these are not run. Default is True. --skip-cpython33-tests The standard CPython3.3 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython34-tests The standard CPython3.4 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython35-tests The standard CPython3.5 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython36-tests The standard CPython3.6 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython37-tests The standard CPython3.7 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython38-tests The standard CPython3.8 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython39-tests The standard CPython3.9 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --skip-cpython310-tests The standard CPython3.10 test suite. Execute this for all corner cases to be covered. With Python 2.x these are not run. Default is True. --no-python2.6 Do not use Python 2.6 even if available on the system. Default is False. --no-python2.7 Do not use Python 2.7 even if available on the system. Default is False. --no-python3.3 Do not use Python 3.3 even if available on the system. Default is False. --no-python3.4 Do not use Python 3.4 even if available on the system. Default is False. --no-python3.5 Do not use Python 3.5 even if available on the system. Default is False. --no-python3.6 Do not use Python 3.6 even if available on the system. Default is False. --no-python3.7 Do not use Python 3.7 even if available on the system. Default is False. --no-python3.8 Do not use Python 3.8 even if available on the system. Default is False. --no-python3.9 Do not use Python 3.9 even if available on the system. Default is False. --no-python3.10 Do not use Python 3.10 even if available on the system. Default is False. --coverage Make a coverage analysis, that does not really check. Default is False. You will only run the CPython test suites, if you have the submodules of the Nuitka git repository checked out. Otherwise, these will be skipped with a warning that they are not available. The policy is generally, that ``./test/run-tests`` running and passing all the tests on Linux and Windows shall be considered sufficient for a release, but of course, depending on changes going on, that might have to be expanded. Basic Tests =========== You can run the "basic" tests like this: .. code:: bash ./tests/basics/run_all.py search These tests normally give sufficient coverage to assume that a change is correct, if these "basic" tests pass. The most important constructs and built-ins are exercised. To control the Python version used for testing, you can set the ``PYTHON`` environment variable to e.g. ``python3.5`` (can also be full path), or simply execute the ``run_all.py`` script directly with the intended version, as it is portable across all supported Python versions, and defaults testing with the Python version is run with. Syntax Tests ============ Then there are "syntax" tests, i.e. language constructs that need to give a syntax error. It sometimes so happens that Nuitka must do this itself, because the ``ast.parse`` doesn't see the problem and raises no ``SyntaxError`` of its own. These cases are then covered by tests to make sure they work as expected. Using the ``global`` statement on a function argument is an example of this. These tests make sure that the errors of Nuitka and CPython are totally the same for this: .. code:: bash ./tests/syntax/run_all.py search Program Tests ============= Then there are small "programs" tests, that e.g. exercise many kinds of import tricks and are designed to reveal problems with inter-module behavior. These can be run like this: .. code:: bash ./tests/programs/run_all.py search Generated Tests =============== There are tests, which are generated from Jinja2 templates. They aim at e.g. combining at types with operations, in-place or not, or large constants. These can be run like this: .. code:: bash ./tests/generated/run_all.py search Compile Nuitka with Nuitka ========================== And there is the "compile itself" or "reflected" test. This test makes Nuitka compile itself and compare the resulting C++ when running compiled to non-compiled, which helps to find in-determinism. The test compiles every module of Nuitka into an extension module and all of Nuitka into a single binary. That test case also gives good coverage of the ``import`` mechanisms, because Nuitka uses a lot of packages and imports between them. .. code:: bash ./tests/reflected/compile_itself.py ********************* Internal/Plugin API ********************* The documentation from the source code for both the Python and the C parts are published as `Nuitka API `__ and argumently in a relatively bad shape as we started generating those with Doxygen only relatively late. .. code:: bash doxygen ./doc/Doxyfile xdg-open html Improvements have already been implemented for plugins: The plugin base class defined in ``PluginBase.py`` (which is used as a template for all plugins) is fully documented in Doxygen now. The same is true for the recently added standard plugins ``NumpyPlugin.py`` and ``TkinterPlugin.py``. These will be uploaded very soon. Going forward, this will also happen for the remaining standard plugins. Please find `here `__ a detailed description of how to write your own plugin. To learn about plugin option specification consult `this document `__. ********************************* Working with the CPython suites ********************************* The CPython test suites are different branches of the same submodule. When you update your git checkout, they will frequently become detached. In this case, simply execute this command: .. code:: bash git submodule foreach 'git fetch && git checkout $(basename $(pwd)) && \ git reset --hard origin/$(basename $(pwd))' When adding a test suite, for a new version, proceed like this: .. code:: bash # Switch to a new branch. git checkout CPython39 git branch CPython310 git checkout CPython310 # Delete all but root commit git rebase -i root rm -rf test cp ~/repos/Nuitka-references/final/Python-3.10.0/Lib/test test git add test # Update commit message to mention proper Python version. git commit --amend # Push to github, setting upstream for branch. git push -u # Cherry pick the removal commits from previous branches. git log origin/CPython39 --reverse --oneline | grep ' Removed' | cut -d' ' -f1 | xargs git cherry-pick # While being prompted for merge conflicts with the deleted files: git status | sed -n 's/deleted by them://p' | xargs git rm --ignore-unmatch x ; git cherry-pick --continue # Push to github, this is useful. git push # Cherry pick the first commit of 'run_all.py', the copy it from the last state, and amend the commits. git log --reverse origin/CPython39 --oneline -- run_all.py | head -1 | cut -d' ' -f1 | xargs git cherry-pick git checkout origin/CPython39 -- run_all.py chmod +x run_all.py sed -i -e 's#python3.9#python3.10#' run_all.py git commit --amend --no-edit run_all.py # Same for 'update_doctest_generated.py' git log --reverse origin/CPython39 --oneline -- update_doctest_generated.py | head -1 | cut -d' ' -f1 | xargs git cherry-pick git checkout origin/CPython39 -- update_doctest_generated.py chmod +x update_doctest_generated.py sed -i -e 's#python3.9#python3.10#' update_doctest_generated.py git commit --amend --no-edit update_doctest_generated.py # Same for .gitignore git log --reverse origin/CPython39 --oneline -- .gitignore | head -1 | cut -d' ' -f1 | xargs git cherry-pick git checkout origin/CPython39 -- .gitignore git commit --amend --no-edit .gitignore # Now cherry-pick all commits of test support, these disable network, audio, GUI, random filenames and more # and are crucial for determistic outputs and non-reliance on outside stuff. git log --reverse origin/CPython39 --oneline -- test/support/__init__.py | tail -n +2 | cut -d' ' -f1 | xargs git cherry-pick git push ********************* Design Descriptions ********************* These should be a lot more and contain graphics from presentations given. It will be filled in, but not now. Nuitka Logo =========== The logo was submitted by "dr. Equivalent". It's source is contained in ``doc/Logo`` where 3 variants of the logo in SVG are placed. - Symbol only (symbol) .. code:: rest .. image:: doc/images/Nuitka-Logo-Symbol.png :alt: Nuitka Logo - Text next to symbol (horizontal) .. code:: rest .. image:: doc/images/Nuitka-Logo-Horizontal.png :alt: Nuitka Logo - Text beneath symbol (vertical) .. code:: rest .. image:: doc/images/Nuitka-Logo-Vertical.png :alt: Nuitka Logo From these logos, PNG images, and "favicons", and are derived. The exact ImageMagick commands are in ``nuitka/tools/release/Documentation``, but are not executed each time, the commands are also replicated here: .. code:: bash convert -background none doc/Logo/Nuitka-Logo-Symbol.svg doc/images/Nuitka-Logo-Symbol.png convert -background none doc/Logo/Nuitka-Logo-Vertical.svg doc/images/Nuitka-Logo-Vertical.png convert -background none doc/Logo/Nuitka-Logo-Horizontal.svg doc/images/Nuitka-Logo-Horizontal.png optipng -o2 doc/images/Nuitka-Logo-Symbol.png optipng -o2 doc/images/Nuitka-Logo-Vertical.png optipng -o2 doc/images/Nuitka-Logo-Horizontal.png Choice of the Target Language ============================= - Choosing the target language was important decision. factors were: - The portability of Nuitka is decided here - How difficult is it to generate the code? - Does the Python C-API have bindings? - Is that language known? - Does the language aid to find bugs? The *decision for C11* is ultimately one for portability, general knowledge of the language and for control over created code, e.g. being able to edit and try that quickly. The current status is to use pure C11. All code compiles as C11, and also in terms of workaround to missing compiler support as C++03. This is mostly needed, because MSVC does not support C. Naturally we are not using any C++ features, just the allowances of C++ features that made it into C11, which is e.g. allowing late definitions of variables. Use of Scons internally ======================= Nuitka does not involve Scons in its user interface at all; Scons is purely used internally. Nuitka itself, being pure Python, will run without any build process just fine. Nuitka simply prepares ``.build`` folders with lots of files and tasks scons to execute the final build, after which Nuitka again will take control and do more work as necessary. .. note:: When we speak of "standalone" mode, this is handled outside of Scons, and after it, creating the ".dist" folder. This is done in ``nuitka.MainControl`` module. For interfacing to Scons, there is the module ``nuitka.build.SconsInterface`` that will support calling ``scons`` - potentially from one of two inline copies (one for before / one for Python 3.5 or later). These are mainly used on Windows or when using source releases - and passing arguments to it. These arguments are passed as ``key=value``, and decoded in the scons file of Nuitka. The scons file is named ``SingleExe.scons`` for lack of better name. It's really wrong now, but we have yet to find a better name. It once expressed the intention to be used to create executables, but the same works for modules too, as in terms of building, and to Scons, things really are the same. The scons file supports operation in multiple modes for many things, and modules is just one of them. It runs outside of Nuitka process scope, even with a different Python version potentially, so all the information must be passed on the command line. What follows is the (lengthy) list of arguments that the scons file processes: - ``source_dir`` Where is the generated C source code. Scons will just compile everything it finds there. No list of files is passed, but instead this directory is being scanned. - ``nuitka_src`` Where do the include files and static C parts of Nuitka live. These provide e.g. the implementation of compiled function, generators, and other helper codes, this will point to where ``nuitka.build`` package lives normally. - ``module_mode`` Build a module instead of a program. - ``result_base`` This is not a full name, merely the basename for the result to be produced, but with path included, and the suffix comes from module or executable mode. - ``debug_mode`` Enable debug mode, which is a mode, where Nuitka tries to help identify errors in itself, and will generate less optimal code. This also asks for warnings, and makes the build fail if there are any. Scons will pass different compiler options in this case. - ``python_debug`` Compile and link against Python debug mode, which does assertions and extra checks, to identify errors, mostly related to reference counting. May make the build fail, if no debug build library of CPython is available. On Windows it is possible to install it for CPython3.5 or higher. - ``full_compat_mode`` Full compatibility, even where it's stupid, i.e. do not provide information, even if available, in order to assert maximum compatibility. Intended to control the level of compatibility to absurd. - ``experimental_mode`` Do things that are not yet accepted to be safe. - ``lto_mode`` Make use of link time optimization of gcc compiler if available and known good with the compiler in question. So far, this was not found to make major differences. - ``disable_console`` Windows subsystem mode: Disable console for windows builds. - ``unstriped_mode`` Unstriped mode: Do not remove debug symbols. - ``clang_mode`` Clang compiler mode, default on macOS X and FreeBSD, optional on Linux. - ``mingw_mode`` MinGW compiler mode, optional and useful on Windows only. - ``standalone_mode`` Building a standalone distribution for the binary. - ``show_scons`` Show scons mode, output information about Scons operation. This will e.g. also output the actual compiler used, output from compilation process, and generally debug information relating to be build process. - ``python_prefix`` Home of Python to be compiled against, used to locate headers and libraries. - ``target_arch`` Target architecture to build. Only meaningful on Windows. - ``python_version`` The major version of Python built against. - ``abiflags`` The flags needed for the Python ABI chosen. Might be necessary to find the folders for Python installations on some systems. - ``icon_path`` The icon to use for Windows programs if given. Locating Modules and Packages ============================= The search for modules used is driven by ``nuitka.importing.Importing`` module. - Quoting the ``nuitka.importing.Importing`` documentation: Locating modules and package source on disk. The actual import of a module would already execute code that changes things. Imagine a module that does ``os.system()``, it would be done during compilation. People often connect to databases, and these kind of things, at import time. Therefore CPython exhibits the interfaces in an ``imp`` module in standard library, which one can use those to know ahead of time, what file import would load. For us unfortunately there is nothing in CPython that is easily accessible and gives us this functionality for packages and search paths exactly like CPython does, so we implement here a multi step search process that is compatible. This approach is much safer of course and there is no loss. To determine if it's from the standard library, one can abuse the attribute ``__file__`` of the ``os`` module like it's done in ``isStandardLibraryPath`` of this module. End quoting the ``nuitka.importing.Importing`` documentation. - Role This module serves the recursion into modules and analysis if a module is a known one. It will give warnings for modules attempted to be located, but not found. These warnings are controlled by a while list inside the module. The decision making and caching are located in the ``nuitka.tree`` package, in modules ``nuitka.tree.Recursion`` and ``nuitka.tree.ImportCache``. Each module is only considered once (then cached), and we need to obey lots of user choices, e.g. to compile a standard library or not. Hooking for module ``import`` process ===================================== Currently, in generated code, for every ``import`` a normal ``__import__()`` built-in call is executed. The ``nuitka/build/static_src/MetaPathBasedLoader.c`` file provides the implementation of a ``sys.meta_path`` hook. This meta path based importer allows us to have the Nuitka provided module imported even when imported by non-compiled code. .. note:: Of course, it would make sense to compile time detect which module it is that is being imported and then to make it directly. At this time, we don't have this inter-module optimization yet, mid-term it should become easy to add. Supporting ``__class__`` of Python3 =================================== In Python3 the handling of ``__class__`` and ``super`` is different from Python2. It used to be a normal variable, and now the following things have changed. - The use of the ``super`` variable name triggers the addition of a closure variable ``__class__``, as can be witnessed by the following code: .. code:: python class X: def f1(self): print(locals()) def f2(self): print(locals()) super # Just using the name, not even calling it. x = X() x.f1() x.f2() Output is: .. code:: {'self': <__main__.X object at 0x7f1773762390>''} {'self': <__main__.X object at 0x7f1773762390>, '__class__': } - This value of ``__class__`` is also available in the child functions. - The parser marks up code objects usage of "super". It doesn't have to be a call, it can also be a local variable. If the ``super`` built-in is assigned to another name and that is used without arguments, it won't work unless ``__class__`` is taken as a closure variable. - As can be seen in the CPython3 code, the closure value is added after the class creation is performed. - It appears, that only functions locally defined to the class are affected and take the closure. This left Nuitka with the strange problem, of how to emulate that. The solution is this: - Under Python3, usage of ``__class__`` as a reference in a child function body is mandatory. It remains that way until all variable names have been resolved. - When recognizing calls to ``super`` without arguments, make the arguments into variable reference to ``__class__`` and potentially ``self`` (actually first argument name). - After all variables have been known, and no suspicious unresolved calls to anything named ``super`` are down, then unused references are optimized away by the normal unused closure variable. - Class dictionary definitions are added. These are special direct function calls, ready to propagate also "bases" and "metaclass" values, which need to be calculated outside. The function bodies used for classes will automatically store ``__class__`` as a shared local variable, if anything uses it. And if it's not assigned by user code, it doesn't show up in the "locals()" used for dictionary creation. Existing ``__class__`` local variable values are in fact provided as closure, and overridden with the built class , but they should be used for the closure giving, before the class is finished. So ``__class__`` will be local variable of the class body, until the class is built, then it will be the ``__class__`` itself. Frame Stack =========== In Python, every function, class, and module has a frame. It creates created when the scope is entered, and there is a stack of these at run time, which becomes visible in tracebacks in case of exceptions. The choice of Nuitka is to make this an explicit element of the node tree, that are as such subject to optimization. In cases, where they are not needed, they may be removed. Consider the following code. .. code:: python def f(): if someNotRaisingCall(): return somePotentiallyRaisingCall() else: return None In this example, the frame is not needed for all the code, because the condition checked wouldn't possibly raise at all. The idea is the make the frame guard explicit and then to reduce its scope whenever possible. So we start out with code like this one: .. code:: python def f(): with frame_guard("f"): if someNotRaisingCall(): return somePotentiallyRaisingCall() else: return None This is to be optimized into: .. code:: python def f(): if someNotRaisingCall(): with frame_guard("f"): return somePotentiallyRaisingCall() else: return None Notice how the frame guard taking is limited and may be avoided, or in best cases, it might be removed completely. Also this will play a role when in-lining function. The frame stack entry will then be automatically preserved without extra care. .. note:: In the actual code, ``nuitka.nodes.FrameNodes.StatementsFrame`` is represents this as a set of statements to be guarded by a frame presence. Parameter Parsing ================= The parsing of parameters is very convoluted in Python, and doing it in a compatible way is not that easy. This is a description of the required process, for an easier overview. Input ----- The input is an argument ``tuple`` (the type is fixed), which contains the positional arguments, and potentially an argument ``dict`` (type is fixed as well, but could also be ``NULL``, indicating that there are no keyword arguments. Keyword dictionary ------------------ The keyword argument dictionary is checked first. Anything in there, that cannot be associated, either raise an error, or is added to a potentially given star dict argument. So there are two major cases. - No star dict argument: Iterate over dictionary, and assign or raise errors. This check covers extra arguments given. - With star dict argument: Iterate over dictionary, and assign or raise errors. Interesting case for optimization are no positional arguments, then no check is needed, and the keyword argument dictionary could be used as the star argument. Should it change, a copy is needed though. What's noteworthy here, is that in comparison to the keywords, we can hope that they are the same value as we use. The interning of strings increases chances for non-compiled code to do that, esp. for short names. We then can do a simple ``is`` comparison and only fall back to real string ``==`` comparisons, after all of these failed. That means more code, but also a lot faster code in the positive case. Argument tuple -------------- After this completed, the argument tuple is up for processing. The first thing it needs to do is to check if it's too many of them, and then to complain. For arguments in Python2, there is the possibility of them being nested, in which case they cannot be provided in the keyword dictionary, and merely should get picked from the argument tuple. Otherwise, the length of the argument tuple should be checked against its position and if possible, values should be taken from there. If it's already set (from the keyword dictionary), raise an error instead. SSA form for Nuitka =================== The SSA form is critical to how optimization works. The so called trace collections builds up traces. These are facts about how this works: - Assignments draw from a counter unique for the variable, which becomes the variable version. This happens during tree building phase. - References are associated with the version of the variable active. This can be a merge of branches. Trace collection does do that and provides nodes with the currently active trace for a variable. The data structures used for trace collection need to be relatively compact as the trace information can become easily much more data than the program itself. Every trace collection has these: - variable_actives Dictionary, where per "variable" the currently used version is. Used to track situations changes in branches. This is the main input for merge process. - variable_traces Dictionary, where "variable" and "version" form the key. The values are objects with or without an assignment, and a list of usages, which starts out empty. These objects have usages appended to them. In "onVariableSet", a new version is allocated, which gives a new object for the dictionary, with an empty usages list, because each write starts a new version. In "onVariableUsage" the version is detected from the current version. It may be not set yet, which means, it's a read of an undefined value (local variable, not a parameter name), or unknown in case of global variable. These objects may be told that their value has escaped. This should influence the value friend they attached to the initial assignment. Each usage may have a current value friend state that is different. When merging branches of conditional statements, the merge shall apply as follows: - Branches have their own collection Thee have potentially deviating sets of ``variable_actives``. These are children of an outer collections. - Case a) One branch only. For that branch a collection is performed. As usual new assignments generate a new version making it "active", references then related to these "active" versions. Then, when the branch is merged, for all "active" variables, it is considered, if that is a change related to before the branch. If it's not the same, a merge trace with the branch condition is created with the one active in the collection before that statement. - Case b) Two branches. When there are two branches, they both as are treated as above, except for the merge. When merging, a difference in active variables between the two branches creates the merge trace. .. note:: For conditional expressions, there are always only two branches. Even if you think you have more than one branch, you do not. It's always nested branches, already when it comes out of the ``ast`` parser. Trace structure, there are different kinds of traces. - Initial write of the version There may be an initial write for each version. It can only occur at the start of the scope, but not later, and there is only one. This might be known to be "initialized" (parameter variables of functions are like that) or "uninitialized", or "unknown". - Merge of other one or two other versions This combines two or more previous versions. In cases of loop exits or entries, there are multiple branches to combine potentially. These branches can have vastly different properties. - Becoming unknown. When control flow escapes, e.g. for a module variable, any write can occur to it, and it's value cannot be trusted to be unchanged. These are then traced as unknown. All traces have a base class ``ValueTraceBase`` which provides the interface to query facts about the state of a variable in that trace. It's e.g. of some interest, if a variable must have a value or must not. This allows to e.g. omit checks, know what exceptions might raise. Loop SSA ======== For loops we have the addition difficulty that we need would need to look ahead what types a variable has at loop exit, but that is a cyclic dependency. Our solution is to consider the variable types at loop entry. When these change, we drop all gained information from inside the loop. We may e.g. think that a variable is a ``int`` or ``float``, but later recognize that it can only be a float. Derivations from ``int`` must be discarded, and the loop analysis restarted. Then during the loop, we assign an incomplete loop trace shape to the variable, which e.g. says it was an ``int`` initially and additional type shapes, e.g. ``int or long`` are then derived. If at the end of the loop, a type produced no new types, we know we are finished and mark the trace as a complete loop trace. If it is not, and next time, we have the same initial types, we add the ones derived from this to the starting values, and see if this gives more types. Python Slots in Optimization ============================ Basic Slot Idea --------------- For almost all the operations in Python, a form of overloading is available. That is what makes it so powerful. So when you write an expression like this one: .. code:: python 1.0 + something This something will not just blindly work when it's a float, but go through a slot mechanism, which then can be overloaded. .. code:: python class SomeStrangeFloat: def __float__(self): return 3.14 something = SomeStrangeFloat() # ... 1.0 + float(something) // 4.140000000000001 Here it is the case, that this is used by user code, but more often this is used internally. Not all types have all slots, e.g. ``list`` does not have ``__float__`` and therefore will refuse an addition to a ``float`` value, based on that. Another slot is working here, that we didn't mention yet, and that is ``__add__`` which for some times will be these kinds of conversions or it will not do that kind of thing, e.g. something do hard checks, which is why this fails to work: .. code:: python [] + () As a deliberate choice, there is no ``__list__`` slot used. The Python designers are aiming at solving many things with slots, but they also accept limitations. There are many slots that are frequently used, most often behind your back (``__iter__``, ``__next__``, ``__lt__``, etc.). The list is large, and tends to grow with Python releases, but it is not endless. Representation in Nuitka ------------------------ So a slot in Nuitka typically has an owning node. We use ``__len__`` as an example here. In the ``computeExpression`` the ``len`` node named ``ExpressionBuiltinLen`` has to defer the decision what it computes to its argument. .. code:: python def computeExpression(self, trace_collection): return self.subnode_value.computeExpressionLen( len_node=self, trace_collection=trace_collection ) That decision then, in the absence of any type knowledge, must be done absolutely carefully and conservative, as could see anything executing here. That examples this code in ``ExpressionBase`` which every expression by default uses: .. code:: python def computeExpressionLen(self, len_node, trace_collection): shape = self.getValueShape() has_len = shape.hasShapeSlotLen() if has_len is False: return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="object of type '%s' has no len()", operation="len", original_node=len_node, value_node=self, ) elif has_len is True: iter_length = self.getIterationLength() if iter_length is not None: from .ConstantRefNodes import makeConstantRefNode result = makeConstantRefNode( constant=int(iter_length), # make sure to downcast long source_ref=len_node.getSourceReference(), ) result = wrapExpressionWithNodeSideEffects(new_node=result, old_node=self) return ( result, "new_constant", "Predicted 'len' result from value shape.", ) self.onContentEscapes(trace_collection) # Any code could be run, note that. trace_collection.onControlFlowEscape(self) # Any exception may be raised. trace_collection.onExceptionRaiseExit(BaseException) return len_node, None, None Notice how by default, known ``__len__`` but unpredictable or even unknown if a ``__len__`` slot is there, the code indicates that its contents and the control flow escapes (could change things behind out back) and any exception could happen. Other expressions can know better, e.g. for compile time constants we can be a whole lot more certain: .. code:: python def computeExpressionLen(self, len_node, trace_collection): return trace_collection.getCompileTimeComputationResult( node=len_node, computation=lambda: len(self.getCompileTimeConstant()), description="""Compile time constant len value pre-computed.""", ) In this case, we are using a function that will produce a concrete value or the exception that the ``computation`` function raised. In this case, we can let the Python interpreter that runs Nuitka do all the hard work. This lives in ``CompileTimeConstantExpressionBase`` and is the base for all kinds of constant values, or even built-in references like the name ``len`` itself and would be used in case of doing ``len(len)`` which obviously gives an exception. Other overloads do not currently exist in Nuitka, but through the iteration length, most cases could be addressed, e.g. ``list`` nodes typical know their element counts. The C side ========== When a slot is not optimized away at compile time however, we need to generate actual code for it. We figure out what this could be by looking at the original CPython implementation. .. code:: C PyObject *builtin_len(PyObject *self, PyObject *v) { Py_ssize_t res; res = PyObject_Size(v); if (res < 0 && PyErr_Occurred()) return NULL; return PyInt_FromSsize_t(res); } We find a pointer to ``PyObject_Size`` which is a generic Python C/API function used in the ``builtin_len`` implementation: .. code:: C Py_ssize_t PyObject_Size(PyObject *o) { PySequenceMethods *m; if (o == NULL) { null_error(); return -1; } m = o->ob_type->tp_as_sequence; if (m && m->sq_length) return m->sq_length(o); return PyMapping_Size(o); } On the C level, every Python object (the ``PyObject *``) as a type named ``ob_type`` and most of its elements are slots. Sometimes they form a group, here ``tp_as_sequence`` and then it may or may not contain a function. This one is tried in preference. Then, if that fails, next up the mapping size is tried. .. code:: C Py_ssize_t PyMapping_Size(PyObject *o) { PyMappingMethods *m; if (o == NULL) { null_error(); return -1; } m = o->ob_type->tp_as_mapping; if (m && m->mp_length) return m->mp_length(o); type_error("object of type '%.200s' has no len()", o); return -1; } This is the same principle, except with ``tp_as_mapping`` and ``mp_length`` used. So from this, we can tell how ``len`` gets at what could be a Python class ``__len__`` or other built-in types. In principle, every slot needs to be dealt with in Nuitka, and it is assumed that currently all slots are supported on at least a very defensive level, to avoid unnoticed escapes of control flow. Built-in call optimization ========================== For calls to built-in names, there is typically a function in Python that delegates to the type constructor (e.g. when we talk about ``int`` that just creates an object passing the arguments of the call) or its own special implementation as we saw with the ``len``. For each built-in called, we have a specialized node, that presents to optimization the actions of the built-in. What are the impact, what are the results. We have seen the resulting example for ``len`` above, but how do we get there. In Python, built-in names are used only if there is no module level variable of the name, and of course no local variable of that name. Therefore, optimization of a built-in name is only done if it turns out the actually assigned in other code, and then when the call comes, arguments are checked and a relatively static node is created. Code Generation towards C ========================= Currently, Nuitka uses Pure C and no C++ patterns at all. The use of C11 requires on some platforms to compile the C11 using a C++ compiler, which works relatively well, but also limits the amount of C11 that can be used. Exceptions ---------- To handle and work with exceptions, every construct that can raise has either a ``bool`` or ``int`` return code or ``PyObject *`` with ``NULL`` return value. This is very much in line with that the Python C-API does. Every helper function that contains code that might raise needs these variables. After a failed call, our variant of ``PyErr_Fetch`` called ``FETCH_ERROR_OCCURRED`` must be used to catch the defined error, unless some quick exception cases apply. The quick exception means, ``NULL`` return from C-API without a set exception means e.g. ``StopIteration``. As an optimization, functions that raise exceptions, but are known not to do so, for whatever reason, could only be asserted to not do so. Statement Temporary Variables ----------------------------- For statements and larger constructs the context object track temporary values, that represent references. For some, these should be released at the end of the statement, or they represent a leak. The larger scope temporary variables, are tracked in the function or module context, where they are supposed to have explicit ``del`` to release their references. Local Variables Storage ----------------------- Closure variables taken are to be released when the function object is later destroyed. For in-lined calls, variables are just passed, and it does not become an issue to release anything. For function exit, owned variables, local or shared to other functions, must be released. This cannot be a ``del`` operation, as it also involves setting a value, which would be wrong for shared variables (and wasteful to local variables, as that would be its last usage). Therefore we need a special operation that simply releases the reference to the cell or object variable. Exit Targets ------------ Each error or other exit releases statement temporary values and then executes a ``goto`` to the exit target. These targets need to be setup. The ``try``/``except`` will e.g. catch error exits. Other exits are ``continue``, ``break``, and ``return`` exits. They all work alike. Generally, the exits stack of with constructs that need to register themselves for some exit types. A loop e.g. registers the ``continue`` exit, and a contained ``try``/``finally`` too, so it can execute the final code should it be needed. Frames ------ Frames are containers for variable declarations and cleanups. As such, frames provide error exits and success exits, which remove the frame from the frame stack, and then proceed to the parent exit. With the use of non ``PyObject **`` C types, but frame exception exits, the need to convert those types becomes apparent. Exceptions should still resolve the C version. When using different C types at frame exception exits, there is a need to trace the active type, so it can be used in the correct form. Abortive Statements ------------------- The way ``try``/``finally`` is handled, copies of the ``finally`` block are made, and optimized independently for each abort method. The ones there are of course, ``return``, ``continue``, and ``break``, but also implicit and explicit ``raise`` of an exception. Code trailing an abortive statement can be discarded, and the control flow will follow these "exits". Constant Preparation ==================== Early versions of Nuitka, created all constants for the whole program for ready access to generated code, before the program launches. It did so in a single file, but that approach didn't scale well. Problems were - Even unused code contributed to start-up time, this can become a lot for large programs, especially in standalone mode. - The massive amount of constant creation codes gave backend C compilers a much harder time than necessary to analyse it all at once. The current approach is as follows. Code generation detects constants used in only one module, and declared ``static`` there, if the module is the only user, or ``extern`` if it is not. Some values are forced to be global, as they are used pre-main or in helpers. These ``extern`` values are globally created before anything is used. The ``static`` values are created when the module is loaded, i.e. something did import it. We trace used constants per module, and for nested ones, we also associate them. The global constants code is special in that it can only use ``static`` for nested values it exclusively uses, and has to export values that others use. Language Conversions to make things simpler =========================================== There are some cases, where the Python language has things that can in fact be expressed in a simpler or more general way, and where we choose to do that at either tree building or optimization time. The ``assert`` statement ------------------------ The ``assert`` statement is a special statement in Python, allowed by the syntax. It has two forms, with and without a second argument. The later is probably less known, as is the fact that raise statements can have multiple arguments too. The handling in Nuitka is: .. code:: python assert value # Absolutely the same as: if not value: raise AssertionError .. code:: python assert value, raise_arg # Absolutely the same as: if not value: raise AssertionError(raise_arg) This makes assertions absolutely the same as a raise exception in a conditional statement. This transformation is performed at tree building already, so Nuitka never knows about ``assert`` as an element and standard optimizations apply. If e.g. the truth value of the assertion can be predicted, the conditional statement will have the branch statically executed or removed. The "comparison chain" expressions ---------------------------------- In Nuitka we have the concept of an outline, and therefore we can make the following re-formulation instead: .. code:: python a < b() > c < d def _comparison_chain(): # So called "outline" function tmp_a = a tmp_b = b() tmp = tmp_a < tmp_b if not tmp: return tmp del tmp_a tmp_c = c tmp = tmp_b > tmp_c if not tmp: return tmp del tmp_b return tmp_c < d _comparison_chain() This transformation is performed at tree building already. The temporary variables keep the value for the use of the same expression. Only the last expression needs no temporary variable to keep it. What we got from this, is making the checks of the comparison chain explicit and comparisons in Nuitka to be internally always about two operands only. The ``execfile`` built-in ------------------------- Handling is: .. code:: python execfile(filename) # Basically the same as: exec(compile(open(filename).read()), filename, "exec") .. note:: This allows optimizations to discover the file opening nature easily and apply file embedding or whatever we will have there one day. This transformation is performed when the ``execfile`` built-in is detected as such during optimization. Generator expressions with ``yield`` ------------------------------------ These are converted at tree building time into a generator function body that yields from the iterator given, which is the put into a for loop to iterate, created a lambda function of and then called with the first iterator. That eliminates the generator expression for this case. It's a bizarre construct and with this trick needs no special code generation. This is a complex example, demonstrating multiple cases of yield in unexpected cases: .. code:: python x = ((yield i) for i in (1, 2) if not (yield)) # Basically the same as: def x(): for i in (1, 2): if not (yield): yield (yield i) Function Decorators ------------------- When one learns about decorators, you see that: .. code:: python @decorator def function(): pass # Is basically the same as: def function(): pass function = decorator(function) The only difference is the assignment to function. In the ``@decorator`` case, if the decorator fails with an exception, the name ``function`` is not assigned yet, but kept in a temporary variable. Therefore in Nuitka this assignment is more similar to that of a lambda expression, where the assignment to the name is only at the end, which also has the extra benefit of not treating real function and lambda functions any different. This removes the need for optimization and code generation to support decorators at all. And it should make the two variants optimize equally well. Functions nested arguments -------------------------- Nested arguments are a Python2 only feature supported by Nuitka. Consider this example: .. code:: python def function(a, (b, c)): return a, b, c We solve this, by kind of wrapping the function with another function that does the unpacking and gives the errors that come from this: .. code:: python def function(a, _1): def _tmp(a, b, c): return a, b, c a, b = _1 return _tmp(a, b, c) The ``.1`` is the variable name used by CPython internally, and actually works if you use keyword arguments via star dictionary. So this is very compatible and actually the right kind of re-formulation, but it removes the need from the code that does parameter parsing to deal with these. Obviously, there is no frame for ``_tmp``, just one for ``function`` and we do not use local variables, but temporary functions. In-place Assignments -------------------- In-place assignments are re-formulated to an expression using temporary variables. These are not as much a reformulation of ``+=`` to ``+``, but instead one which makes it explicit that the assign target may change its value. .. code:: python a += b .. code:: python _tmp = a.__iadd__(b) if a is not _tmp: a = _tmp Using ``__iadd__`` here to express that for the ``+``, the in-place variant ``iadd`` is used instead. The ``is`` check may be optimized away depending on type and value knowledge later on. Complex Assignments ------------------- Complex assignments are defined as those with multiple targets to assign from a single source and are re-formulated to such using a temporary variable and multiple simple assignments instead. .. code:: python a = b = c .. code:: python _tmp = c a = _tmp b = _tmp del _tmp This is possible, because in Python, if one assignment fails, it can just be interrupted, so in fact, they are sequential, and all that is required is to not calculate ``c`` twice, which the temporary variable takes care of. Were ``b`` a more complex expression, e.g. ``b.some_attribute`` that might raise an exception, ``a`` would still be assigned. Unpacking Assignments --------------------- Unpacking assignments are re-formulated to use temporary variables as well. .. code:: python a, b.attr, c[ind] = d = e, f, g = h() Becomes this: .. code:: python _tmp = h() _iter1 = iter(_tmp) _tmp1 = unpack(_iter1, 3) _tmp2 = unpack(_iter1, 3) _tmp3 = unpack(_iter1, 3) unpack_check(_iter1) a = _tmp1 b.attr = _tmp2 c[ind] = _tmp3 d = _tmp _iter2 = iter(_tmp) _tmp4 = unpack(_iter2, 3) _tmp5 = unpack(_iter2, 3) _tmp6 = unpack(_iter2, 3) unpack_check(_iter1) e = _tmp4 f = _tmp5 g = _tmp6 That way, the unpacking is decomposed into multiple simple statements. It will be the job of optimizations to try and remove unnecessary unpacking, in case e.g. the source is a known tuple or list creation. .. note:: The ``unpack`` is a special node which is a form of ``next`` that will raise a ``ValueError`` when it cannot get the next value, rather than a ``StopIteration``. The message text contains the number of values to unpack, therefore the integer argument. .. note:: The ``unpack_check`` is a special node that raises a ``ValueError`` exception if the iterator is not finished, i.e. there are more values to unpack. Again the number of values to unpack is provided to construct the error message. With Statements --------------- The ``with`` statements are re-formulated to use temporary variables as well. The taking and calling of ``__enter__`` and ``__exit__`` with arguments, is presented with standard operations instead. The promise to call ``__exit__`` is fulfilled by ``try``/``except`` clause instead. .. code:: python with some_context as x: something(x) .. code:: python tmp_source = some_context # Actually it needs to be "special look-up" for Python2.7, so attribute # look-up won't be exactly what is there. tmp_exit = tmp_source.__exit__ # This one must be held for the whole with statement, it may be assigned # or not, in our example it is. If an exception occurs when calling # ``__enter__``, the ``__exit__`` should not be called. tmp_enter_result = tmp_source.__enter__() # Indicator variable to know if "tmp_exit" has been called. tmp_indicator = False try: # Now the assignment is to be done, if there is any name for the # manager given, this may become multiple assignment statements and # even unpacking ones. x = tmp_enter_result # Then the code of the "with" block. something(x) except Exception: # Note: This part of the code must not set line numbers, which we # indicate with special source code references, which we call "internal". # Otherwise the line of the frame would get corrupted. tmp_indicator = True if not tmp_exit(*sys.exc_info()): raise finally: if not tmp_indicator: # Call the exit if no exception occurred with all arguments # as "None". tmp_exit(None, None, None) .. note:: We don't refer really to ``sys.exc_info()`` at all, instead, we have fast references to the current exception type, value and trace, taken directly from the caught exception object on the C level. If we had the ability to optimize ``sys.exc_info()`` to do that, we could use the same transformation, but right now we don't have it. For Loops --------- The ``for`` loops use normal assignments and handle the iterator that is implicit in the code explicitly. .. code:: python for x, y in iterable: if something(x): break else: otherwise() This is roughly equivalent to the following code: .. code:: python _iter = iter(iterable) _no_break_indicator = False while 1: try: _tmp_value = next(_iter) except StopIteration: # Set the indicator that the else branch may be executed. _no_break_indicator = True # Optimization should be able to tell that the else branch is run # only once. break # Normal assignment re-formulation applies to this assignment of course. x, y = _tmp_value del _tmp_value if something(x): break if _no_break_indicator: otherwise() .. note:: The ``_iter`` temporary variable is of course also in a ``try/finally`` construct, to make sure it releases after its used. The ``x, y`` assignment is of course subject to unpacking re-formulation. The ``try``/``except`` is detected to allow to use a variant of ``next`` that does not raise an exception, but to be fast check about the ``NULL`` return from ``next`` built-in. So no actual exception handling is happening in this case. While Loops ----------- Quoting the ``nuitka.tree.ReformulationWhileLoopStatements`` documentation: Reformulation of while loop statements. Loops in Nuitka have no condition attached anymore, so while loops are re-formulated like this: .. code:: python while condition: something() .. code:: python while 1: if not condition: break something() This is to totally remove the specialization of loops, with the condition moved to the loop body in an initial conditional statement, which contains a ``break`` statement. That achieves, that only ``break`` statements exit the loop, and allow for optimization to remove always true loop conditions, without concerning code generation about it, and to detect such a situation, consider e.g. endless loops. .. note:: Loop analysis (not yet done) can then work on a reduced problem (which ``break`` statements are executed under what conditions) and is then automatically very general. The fact that the loop body may not be entered at all, is still optimized, but also in the general sense. Explicit breaks at the loop start and loop conditions are the same. End quoting the ``nuitka.tree.ReformulationWhileLoopStatements`` documentation: Exception Handlers ------------------ Exception handlers in Python may assign the caught exception value to a variable in the handler definition. And the different handlers are represented as conditional checks on the result of comparison operations. .. code:: python try: block() except A as e: handlerA(e) except B as e: handlerB(e) else: handlerElse() .. code:: python try: block() except: # These are special nodes that access the exception, and don't really # use the "sys" module. tmp_exc_type = sys.exc_info()[0] tmp_exc_value = sys.exc_info()[1] # exception_matches is a comparison operation, also a special node. if exception_matches(tmp_exc_type, (A,)): e = tmp_exc_value handlerA(e) elif exception_matches(tmp_exc_type, (B,)): e = tmp_exc_value handlerB(e) else: handlerElse() For Python3, the assigned ``e`` variables get deleted at the end of the handler block. Should that value be already deleted, that ``del`` does not raise, therefore it's tolerant. This has to be done in any case, so for Python3 it is even more complex. .. code:: python try: block() except: # These are special nodes that access the exception, and don't really # use the "sys" module. tmp_exc_type = sys.exc_info()[0] tmp_exc_value = sys.exc_info()[1] # exception_matches is a comparison operation, also a special node. if exception_matches(tmp_exc_type, (A,)): try: e = tmp_exc_value handlerA(e) finally: del e elif exception_matches(tmp_exc_type, (B,)): try: e = tmp_exc_value handlerB(e) finally: del e else: handlerElse() Should there be no ``else:`` branch, a default re-raise statement is used instead. And of course, the values of the current exception type and value, both use special references, that access the C++ and don't go via ``sys.exc_info`` at all, nodes called ``CaughtExceptionTypeRef`` and ``CaughtExceptionValueRef``. This means, that the different handlers and their catching run time behavior are all explicit and reduced the branches. Statement ``try``/``except`` with ``else`` ------------------------------------------ Much like ``else`` branches of loops, an indicator variable is used to indicate the entry into any of the exception handlers. Therefore, the ``else`` becomes a real conditional statement in the node tree, checking the indicator variable and guarding the execution of the ``else`` branch. Class Creation (Python2) ------------------------ Classes in Python2 have a body that only serves to build the class dictionary and is a normal function otherwise. This is expressed with the following re-formulation: .. code:: python # in module "SomeModule" # ... class SomeClass(SomeBase, AnotherBase): """ This is the class documentation. """ some_member = 3 .. code:: python def _makeSomeClass(): # The module name becomes a normal local variable too. __module__ = "SomeModule" # The doc string becomes a normal local variable. __doc__ = """ This is the class documentation. """ some_member = 3 return locals() # force locals to be a writable dictionary, will be optimized away, but # that property will stick. This is only to express, that locals(), where # used will be writable to. exec("") SomeClass = make_class("SomeClass", (SomeBase, AnotherBase), _makeSomeClass()) That is roughly the same, except that ``_makeSomeClass`` is *not* visible to its child functions when it comes to closure taking, which we cannot express in Python language at all. Therefore, class bodies are just special function bodies that create a dictionary for use in class creation. They don't really appear after the tree building stage anymore. The type inference will of course have to become able to understand ``make_class`` quite well, so it can recognize the created class again. Class Creation (Python3) ------------------------ In Python3, classes are a complicated way to write a function call, that can interact with its body. The body starts with a dictionary provided by the metaclass, so that is different, because it can ``__prepare__`` a non-empty locals for it, which is hidden away in "prepare_class_dict" below. What's noteworthy, is that this dictionary, could e.g. be an ``OrderDict``. I am not sure, what ``__prepare__`` is allowed to return. .. code:: python3 # in module "SomeModule" # ... class SomeClass(SomeBase, AnotherBase, metaclass = SomeMetaClass): """ This is the class documentation. """ some_member = 3 .. code:: python # Non-keyword arguments, need to be evaluated first. tmp_bases = (SomeBase, AnotherBase) # Keyword arguments go next, __metaclass__ is just one of them. In principle # we need to forward the others as well, but this is ignored for the sake of # brevity. tmp_metaclass = select_metaclass(tmp_bases, SomeMetaClass) tmp_prepared = tmp_metaclass.__prepare__("SomeClass", tmp_bases) # The function that creates the class dictionary. Receives temporary variables # to work with. def _makeSomeClass(): # This has effect, currently I don't know how to express that in Python3 # syntax, but we will have a node that does that. locals().replace(tmp_prepared) # The module name becomes a normal local variable too. __module__ = "SomeModule" # The doc string becomes a normal local variable. __doc__ = """ This is the class documentation. """ some_member = 3 # Create the class, share the potential closure variable "__class__" # with others. __class__ = tmp_metaclass("SomeClass", tmp_bases, locals()) return __class__ # Build and assign the class. SomeClass = _makeSomeClass() Generator Expressions --------------------- There are re-formulated as functions. Generally they are turned into calls of function bodies with (potentially nested) for loops: .. code:: python gen = (x * 2 for x in range(8) if cond()) .. code:: python def _gen_helper(__iterator): for x in __iterator: if cond(): yield x * 2 gen = _gen_helper(range(8)) List Contractions ----------------- The list contractions of Python2 are different from those of Python3, in that they don't actually do any closure variable taking, and that no function object ever exists. .. code:: python list_value = [x * 2 for x in range(8) if cond()] .. code:: python def _listcontr_helper(__iterator): result = [] for x in __iterator: if cond(): result.append(x * 2) return result list_value = _listcontr_helper(range(8)) The difference is that with Python3, the function "_listcontr_helper" is really there and named ```` (or ```` as of Python3.7 or higher), whereas with Python2 the function is only an outline, so it can readily access the containing name space. Set Contractions ---------------- The set contractions of Python2.7 are like list contractions in Python3, in that they produce an actual helper function: .. code:: python set_value = {x * 2 for x in range(8) if cond()} .. code:: python def _setcontr_helper(__iterator): result = set() for x in __iterator: if cond(): result.add(x * 2) return result set_value = _setcontr_helper(range(8)) Dictionary Contractions ----------------------- The dictionary contractions of are like list contractions in Python3, in that they produce an actual helper function: .. code:: python dict_value = {x: x * 2 for x in range(8) if cond()} .. code:: python def _dictcontr_helper(__iterator): result = {} for x in __iterator: if cond(): result[x] = x * 2 return result set_value = _dictcontr_helper(range(8)) Boolean expressions ``and`` and ``or`` -------------------------------------- The short circuit operators ``or`` and ``and`` tend to be only less general that the ``if``/``else`` expressions, but have dedicated nodes. We used to have a re-formulation towards those, but we now do these via dedicated nodes too. These new nodes, present the evaluation of the left value, checking for its truth value, and depending on it, to pick it, or use the right value. Simple Calls ------------ As seen below, even complex calls are simple calls. In simple calls of Python there is still some hidden semantic going on, that we expose. .. code:: python func(arg1, arg2, named1=arg3, named2=arg4) On the C-API level there is a tuple and dictionary built. This one is exposed: .. code:: python func(*(arg1, arg2), **{"named1": arg3, "named2": arg4}) A called function will access this tuple and the dictionary to parse the arguments, once that is also re-formulated (argument parsing), it can then lead to simple in-lining. This way calls only have 2 arguments with constant semantics, that fits perfectly with the C-API where it is the same, so it is actually easier for code generation. Although the above looks like a complex call, it actually is not. No checks are needed for the types of the star arguments and it's directly translated to ``PyObject_Call``. Complex Calls ------------- The call operator in Python allows to provide arguments in 4 forms. - Positional (or normal) arguments - Named (or keyword) arguments - Star list arguments - Star dictionary arguments The evaluation order is precisely that. An example would be: .. code:: python something(pos1, pos2, name1=named1, name2=named2, *star_list, **star_dict) The task here is that first all the arguments are evaluated, left to right, and then they are merged into only two, that is positional and named arguments only. for this, the star list argument and the star dictionary arguments, are merged with the positional and named arguments. What's peculiar, is that if both the star list and dictionary arguments are present, the merging is first done for star dictionary, and only after that for the star list argument. This makes a difference, because in case of an error, the star argument raises first. .. code:: python something(*1, **2) This raises "TypeError: something() argument after ** must be a mapping, not int" as opposed to a possibly more expected "TypeError: something() argument after * must be a sequence, not int." That doesn't matter much though, because the value is to be evaluated first anyway, and the check is only performed afterwards. If the star list argument calculation gives an error, this one is raised before checking the star dictionary argument. So, what we do, is we convert complex calls by the way of special functions, which handle the dirty work for us. The optimization is then tasked to do the difficult stuff. Our example becomes this: .. code:: python def _complex_call(called, pos, kw, star_list_arg, star_dict_arg): # Raises errors in case of duplicate arguments or tmp_star_dict not # being a mapping. tmp_merged_dict = merge_star_dict_arguments( called, tmp_named, mapping_check(called, tmp_star_dict) ) # Raises an error if tmp_star_list is not a sequence. tmp_pos_merged = merge_pos_arguments(called, tmp_pos, tmp_star_list) # On the C-API level, this is what it looks like. return called(*tmp_pos_merged, **tmp_merged_dict) returned = _complex_call( called=something, pos=(pos1, pos2), named={"name1": named1, "name2": named2}, star_list_arg=star_list, star_dict_arg=star_dict, ) The call to ``_complex_call`` is be a direct function call with no parameter parsing overhead. And the call in its end, is a special call operation, which relates to the ``PyObject_Call`` C-API. Match Statements ---------------- .. code:: python match something(): case [x] if x: z = 2 case _ as y if y == x and y: z = 1 case 0: z = 0 This is the same as .. code:: python tmp_match_subject = something() # Indicator variable, once true, all matching stops. tmp_handled = False # First branch x = tmp_match_subject if sequence_check(x) if x: z = 2 tmp_handled = True if tmp_handled is False: y = tmp_match_subject if x == y and y: z = 1 tmp_handled = True if tmp_handled is False: z = 0 Print Statements ---------------- The ``print`` statement exists only in Python2. It implicitly converts its arguments to strings before printing them. In order to make this accessible and compile time optimized, this is made visible in the node tree. .. code:: python print arg1, "1", 1 This is in Nuitka converted so that the code generation for ``print`` doesn't do any conversions itself anymore and relies on the string nature of its input. .. code:: python print str(arg1), "1", str(1) Only string objects are spared from the ``str`` built-in wrapper, because that would only cause noise in optimization stage. Later optization can then find it unnecessary for certain arguments. Additionally, each ``print`` may have a target, and multiple arguments, which we break down as well for dumber code generation. The target is evaluated first and should be a file, kept referenced throughout the whole print statement. .. code:: python print >> target_file, str(arg1), "1", str(1) This is being reformulated to: .. code:: python try: tmp_target = target_file print >>tmp_target, str(arg1), print >>tmp_target, "1", print >>tmp_target, str(1), print >>tmp_target finally: del tmp_target This allows code generation to not deal with arbitrary amount of arguments to ``print``. It also separates the newline indicator from the rest of things, which makes sense too, having it as a special node, as it's behavior with regards to soft-space is different of course. And finally, for ``print`` without a target, we still assume that a target was given, which would be ``sys.stdout`` in a rather hard-coded way (no variable look-ups involved). Reformulations during Optimization ================================== Builtin ``zip`` for Python2 --------------------------- .. code:: python def _zip(a, b, c): # Potentially more arguments. # First assign, to preserve the order of execution, the arguments might be # complex expressions with side effects. tmp_arg1 = a tmp_arg2 = b tmp_arg3 = c # could be more ... # Creation of iterators goes first. try: tmp_iter_1 = iter(tmp_arg1) except TypeError: raise TypeError("zip argument #1 must support iteration") try: tmp_iter_2 = iter(tmp_arg2) except TypeError: raise TypeError("zip argument #2 must support iteration") try: tmp_iter_3 = iter(tmp_arg3) except TypeError: raise TypeError("zip argument #3 must support iteration") # could be more ... tmp_result = [] try: while 1: tmp_result.append( ( next(tmp_iter_1), next(tmp_iter_2), next(tmp_iter_3), # more arguments here ... ) ) except StopIteration: pass return tmp_result Builtin ``zip`` for Python3 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python for x, y, z in zip(a, b, c): ... .. code:: python def _zip_gen_object(a, b, c, ...): ... # See Python2 ... # could be more ... while 1: yield ( next(tmp_iter_1), next(tmp_iter_2), next(tmp_iter_3), ... ) except StopIteration: break for x, y, z in _zip_gen_object(a, b, c): ... Builtin ``map`` for Python2 --------------------------- .. code:: python def _map(): # TODO: Not done yet. pass Builtin ``min`` --------------- .. code:: python # TODO: keyfunc (Python2/3), defaults (Python3) def _min(a, b, c): # Potentially more arguments. tmp_arg1 = a tmp_arg2 = b tmp_arg3 = c # more arguments here ... result = tmp_arg1 if keyfunc is None: # can be decided during re-formulation tmp_key_result = keyfunc(result) tmp_key_candidate = keyfunc(tmp_arg2) if tmp_key_candidate < tmp_key_result: result = tmp_arg2 tmp_key_result = tmp_key_candidate tmp_key_candidate = keyfunc(tmp_arg3) if tmp_key_candidate < tmp_key_result: result = tmp_arg3 tmp_key_result = tmp_key_candidate # more arguments here ... else: if tmp_arg2 < result: result = tmp_arg2 if tmp_arg3 < result: result = tmp_arg3 # more arguments here ... return result Builtin ``max`` --------------- See ``min`` just with ``>`` instead of ``<``. Call to ``dir`` without arguments --------------------------------- This expression is reformulated to ``locals().keys()`` for Python2, and ``list(locals.keys())`` for Python3. Calls to functions with known signatures ---------------------------------------- As a necessary step for inlining function calls, we need to change calls to variable references to function references. .. code:: python def f(arg1, arg2): return some_op(arg1, arg2) # ... other code x = f(a, b + c) In the optimization it is turned into .. code:: python # ... other code x = lambda arg1, arg2: some_op(arg1, arg2)(a, b + c) .. note:: The ``lambda`` stands here for a reference to the function, rather than a variable reference, this is the normal forward propagation of values, and does not imply duplicating or moving any code at all. At this point, we still have not resolved the actual call arguments to the variable names, still a Python level function is created, and called, and arguments are parsed to a tuple, and from a tuple. For simplicity sake, we have left out keyword arguments out of the equation for now, but they are even more costly. So now, what we want to do, is to re-formulate the call into what we call an outline body, which is a inline function, and that does the parameter parsing already and contains the function code too. In this inlining, there still is a function, but it's technically not a Python function anymore, just something that is an expression whose value is determined by control flow and the function call. .. code:: python # ... other code def _f(): tmp_arg1 = arg1 tmp_arg2 = b + c return tmp_arg1 + tmp_arg2 x = _f() With this, a function is considered inlined, because it becomes part of the abstract execution, and the actual code is duplicated. The point is, that matching the signature of the function to the actual arguments given, is pretty straight forward in many cases, but there are two forms of complications that can happen. One is default values, because they need to assigned or not, and the other is keyword arguments, because they allow to reorder arguments. Lets consider an example with default values first. .. code:: python def f(arg1, arg2=some_default()): return some_op(arg1, arg2) # ... other code x = f(a, b + c) Since the point, at which defaults are taken, we must execute them at that point and make them available. .. code:: python tmp_defaults = (some_default,) # that was f.__defaults__ # ... other code def _f(): tmp_arg1 = arg1 tmp_arg2 = tmp_defaults[0] return tmp_arg1 + tmp_arg2 x = _f() Now, one where keyword arguments are ordered the other way. .. code:: python def f(arg1, arg2): return some_op(arg1, arg2) # ... other code x = f(arg2=b + c, arg1=a) # "b+c" is evaluated before "a" The solution is an extra level of temporary variables. We remember the argument order by names and then assign parameters from it: .. code:: python # ... other code def _f(): tmp_given_value1 = b + c tmp_given_value2 = a tmp_arg1 = tmp_given_value2 tmp_arg2 = tmp_given_value1 return tmp_arg1 + tmp_arg2 x = _f() Obviously, optimization of Nuitka can decide, that e.g. should ``a`` or ``b+c`` not have side effects, to optimize these with standard variable tracing away. Nodes that serve special purposes ================================= Try statements -------------- In Python, there is ``try``/``except`` and ``try``/``finally``. In Nuitka there is only a ``try``, which then has blocks to handle exceptions, ``continue``, or ``break``, or ``return``. There is no ``else`` to this node type. This is more low level and universal. Code for the different handlers can be different. User provided ``finally`` blocks become copied into the different handlers. Releases -------- When a function exits, the local variables are to be released. The same applies to temporary variables used in re-formulations. These releases cause a reference to the object to the released, but no value change. They are typically the last use of the object in the function. The are similar to ``del``, but make no value change. For shared variables this effect is most visible. Side Effects ------------ When an exception is bound to occur, and this can be determined at compile time, Nuitka will not generate the code the leads to the exception, but directly just raise it. But not in all cases, this is the full thing. Consider this code: .. code:: python f(a(), 1 / 0) The second argument will create a ``ZeroDivisionError`` exception, but before that ``a()`` must be executed, but the call to ``f`` will never happen and no code is needed for that, but the name look-up must still succeed. This then leads to code that is internally like this: .. code:: python f(a(), raise_ZeroDivisionError()) which is then modeled as: .. code:: python side_effect(a(), f, raise_ZeroDivisionError()) where we can consider ``side_effect`` to be a function that returns the last expression. Of course, if this is not part of another expression, but close to statement level, side effects, can be converted to multiple statements simply. Another use case, is that the value of an expression can be predicted, but that the language still requires things to happen, consider this: .. code:: python a = len((f(), g())) We can tell that ``a`` will be 2, but the call to ``f`` and ``g`` must still be performed, so it becomes: .. code:: python a = side_effects(f(), g(), 2) Modelling side effects explicitly has the advantage of recognizing them easily and allowing to drop the call to the tuple building and checking its length, only to release it. Caught Exception Type/Value References -------------------------------------- When catching an exception, these are not directly put to ``sys.exc_info()``, but remain as mere C variables. From there, they can be accessed with these nodes, or if published then from the thread state. Hard Module Imports ------------------- These are module look-ups that don't depend on any local variable for the module to be looked up, but with hard-coded names. These may be the result of optimization gaining such level of certainty. Currently they are used to represent ``sys.stdout`` usage for ``print`` statements, but other usages will follow. Locals Dict Update Statement ---------------------------- For the ``exec`` re-formulation, we apply an explicit sync back to locals as an explicit node. It helps us to tell the affected local variable traces that they might be affected. It represents the bit of ``exec`` in Python2, that treats ``None`` as the locals argument as an indication to copy back. Optimizing Attribute Lookups into Method Calls for Built-ins types ================================================================== The attribute lookup node ``ExpressionAttributeLookup`` represents looking up an attribute name, that is known to be a string. That's already a bit more special, than say what ``ExpressionBuiltinGetattr`` does for ``getattr``, where it could be any object being looked up. From the Python syntax however, these are what gets created, as it's not allowed in any other way. So, this is where this starts. Then, when we are creating an attribute node with a *fixed* name, we dispatch it to generated node classes, e.g. ``ExpressionAttributeLookupFixedAppend``. This will be the same, except that the attribute name is hardcoded. There are generated, such that they can have code that is special for ``.append`` lookups. In their case, it makes sense to ask the source, if they are a ``list`` object exactly. It doesn't make sense to do this check for names that the ``list`` does not contain. So at that stage, we are saving both a bit of memory and time. Should this question succeed, i.e. the expression the attribute values is looked up upon, is known to be a ``list`` exactly, we persist this knowledge in the also generated nodes that represent ``list.append`` and just that. It is called ``ExpressionAttributeLookupListAppend`` and only represents the knowledge gained so far. We do not consider if ``ExpressionAttributeLookupFixedAppend`` is called, or not, passed as an argument, assigned somewhere, it doesn't matter yet, but for ``ExpressionAttributeLookupListAppend`` we know a hell of a lot more. We know its type, we know attributes for it, say ``__name__``, as it is a compile time constant, therefore much optimization can follow for them, and code generation can specialize them too (not yet done). Should these nodes then, and say this happens later after some inlining happens be seen as called, we can then turn them into method call nodes, checking the arguments and such, this is then ``ExpressionListOperationAppend`` and at this point, will raising errors with wrong argument counts. And then we have this ``ExpressionListOperationAppend`` which will influence the tracing of ``list`` contents, i.e. it will be able to tell the ``list`` in question is no more empty after this ``append``, and it will be able to at least predict the last element value, truth value of the list, etc. ****************************** Plan to add "ctypes" support ****************************** Add interfacing to C code, so Nuitka can turn a ``ctypes`` binding into an efficient binding as if it were written manually with Python C-API or better. Goals/Allowances to the task ============================ #. Goal: Must not directly use any pre-existing C/C++ language file headers, only generate declarations in generated C code ourselves. We would rather write or use tools that turn an existing a C header to some ``ctypes`` declarations if it needs to be, but not mix and use declarations from existing header code. .. note:: The "cffi" interface maybe won't have the issue, but it's not something we need to write or test the code for. #. Allowance: May use ``ctypes`` module at compile time to ask things about ``ctypes`` and its types. #. Goal: Should make use of ``ctypes``, to e.g. not hard code in Nuitka what ``ctypes.c_int()`` gives on the current platform, unless there is a specific benefit. #. Allowance: Not all ``ctypes`` usages must be supported immediately. #. Goal: Try and be as general as possible. For the compiler, ``ctypes`` support should be hidden behind a generic interface of some sort. Supporting ``math`` module should be the same thing. Type Inference - The Discussion =============================== Main initial goal is to forward value knowledge. When you have ``a = b``, that means that a and b now "alias". And if you know the value of ``b`` you can assume to know the value of ``a``. This is called "aliasing". When assigning ``a`` to something new, that won't change ``b`` at all. But when an attribute is set, a method called of it, that might impact the actual value, referenced by both. We need to understand mutable vs. immutable though, as some things are not affectable by aliasing in any way. .. code:: python a = 3 b = a b += 4 # a is not changed a = [3] b = a b += [4] # a is changed indeed If we cannot tell, we must assume that ``a`` might be changed. It's either ``b`` or what ``a`` was before. If the type is not mutable, we can assume the aliasing to be broken up, and if it is, we can assume both to be the same value still. When that value is a compile time constant, we will want to push it forward, and we do that with "(Constant) Value Propagation", which is implemented already. We avoid too large constants, and we properly trace value assignments, but not yet aliases. In order to fully benefit from type knowledge, the new type system must be able to be fully friends with existing built-in types, but for classes to also work with it, it should not be tied to them. The behavior of a type ``long``, ``str``, etc. ought to be implemented as far as possible with the built-in ``long``, ``str`` at compiled time as well. .. note:: This "use the real thing" concept extends beyond builtin types, e.g. ``ctypes.c_int()`` should also be used, but we must be aware of platform dependencies. The maximum size of ``ctypes.c_int`` values would be an example of that. Of course that may not be possible for everything. This approach has well proven itself with built-in functions already, where we use real built-ins where possible to make computations. We have the problem though that built-ins may have problems to execute everything with reasonable compile time cost. Another example, consider the following code: .. code:: python len("a" * 1000000000000) To predict this code, calculating it at compile time using constant operations, while feasible, puts an unacceptable burden on the compilation. Esp. we wouldn't want to produce such a huge constant and stream it, the C++ code would become too huge. So, we need to stop the ``*`` operator from being used at compile time and cope with reduced knowledge, already here: .. code:: python "a" * 10000000000000 Instead, we would probably say that for this expression: - The result is a ``str`` or a C level ``PyStringObject *``. - We know its length exactly, it's ``10000000000000``. - Can predict every of its elements when sub-scripted, sliced, etc., if need be, with a function we may create. Similar is true for this horrible (in Python2) thing: .. code:: python range(10000000000000) So it's a rather general problem, this time we know: - The result is a ``list`` or C level ``PyListObject *``. - We know its length exactly, ``10000000000000``. - Can predict every of its elements when index, sliced, etc., if need be, with a function. Again, we wouldn't want to create the list. Therefore Nuitka avoids executing these calculation, when they result in constants larger than a threshold of e.g. 256 elements. This concept has to be also applied to large integers and more CPU and memory traps. Now lets look at a more complete use case: .. code:: python for x in range(10000000000000): doSomething() Looking at this example, one traditional way to look at it, would be to turn ``range`` into ``xrange``, and to note that ``x`` is unused. That would already perform better. But really better is to notice that ``range()`` generated values are not used at all, but only the length of the expression matters. And even if ``x`` were used, only the ability to predict the value from a function would be interesting, so we would use that computation function instead of having an iteration source. Being able to predict from a function could mean to have Python code to do it, as well as C code to do it. Then code for the loop can be generated without any CPython library usage at all. .. note:: Of course, it would only make sense where such calculations are "O(1)" complexity, i.e. do not require recursion like "n!" does. The other thing is that CPython appears to at - run time - take length hints from objects for some operations, and there it would help too, to track length of objects, and provide it, to outside code. Back to the original example: .. code:: python len("a" * 1000000000000) The theme here, is that when we can't compute all intermediate expressions, and we sure can't do it in the general case. But we can still, predict some of properties of an expression result, more or less. Here we have ``len`` to look at an argument that we know the size of. Great. We need to ask if there are any side effects, and if there are, we need to maintain them of course. This is already done by existing optimization if an operation generates an exception. .. note:: The optimization of ``len`` has been implemented and works for all kinds of container creation and ranges. Applying this to "ctypes" ========================= The *not so specific* problem to be solved to understand ``ctypes`` declarations is maybe as follows: .. code:: python import ctypes This leads to Nuitka in its tree to have an assignment from a ``__import__`` expression to the variable ``ctypes``. It can be predicted by default to be a module object, and even better, it can be known as ``ctypes`` from standard library with more or less certainty. See the section about "Importing". So that part is "easy", and it's what will happen. During optimization, when the module ``__import__`` expression is examined, it should say: - ``ctypes`` is a module - ``ctypes`` is from standard library (if it is, might not be true) - ``ctypes`` then has code behind it, called ``ModuleFriend`` that knows things about it attributes, that should be asked. The later is the generic interface, and the optimization should connect the two, of course via package and module full names. It will need a ``ModuleFriendRegistry``, from which it can be pulled. It would be nice if we can avoid ``ctypes`` to be loaded into Nuitka unless necessary, so these need to be more like a plug-in, loaded only if necessary, i.e. the user code actually uses ``ctypes``. Coming back to the original expression, it also contains an assignment expression, because it re-formulated to be more like this: .. code:: python ctypes = __import__("ctypes") The assigned to object, simply gets the type inferred propagated as part of an SSA form. Ideally, we could be sure that nothing in the program changes the variable, and therefore have only one version of that variable. For module variables, when the execution leaves the module to unknown code, or unclear code, it might change the variable. Therefore, likely we will often only assume that it could still be ``ctypes``, but also something else. Depending on how well we control module variable assignment, we can decide this more of less quickly. With "compiled modules" types, the expectation is that it's merely a quick C ``==`` comparison check. The module friend should offer code to allow a check if it applies, for uncertain cases. Then when we come to uses of it: .. code:: python ctypes.c_int() At this point, using SSA, we are more of less sure, that ``ctypes`` is at that point the module, and that we know what it's ``c_int`` attribute is, at compile time, and what it's call result is. We will use the module friend to help with that. It will attach knowledge about the result of that expression during the SSA collection process. This is more like a value forward propagation than anything else. In fact, constant propagation should only be the special case of it, and one design goal of Nuitka was always to cover these two cases with the same code. Excursion to Functions ====================== In order to decide what this means to functions and their call boundaries, if we propagate forward, how to handle this: .. code:: python def my_append(a, b): a.append(b) return a We annotate that ``a`` is first a "unknown but defined parameter object", then later on something that definitely has an ``append`` attribute, when returned, as otherwise an exception occurs. The type of ``a`` changes to that after ``a.append`` look-up succeeds. It might be many kinds of an object, but e.g. it could have a higher probability of being a ``PyListObject``. And we would know it cannot be a ``PyStringObject``, as that one has no ``append`` method, and would have raised an exception therefore. .. note:: If classes, i.e. other types in the program, have an ``append`` attribute, it should play a role too, there needs to be a way to plug-in to this decisions. .. note:: On the other hand, types without ``append`` attribute can be eliminated. Therefore, functions through SSA provide an automatic analysis on their return state, or return value types, or a quick way to predict return value properties, based on input value knowledge. So this could work: .. code:: python b = my_append([], 3) assert b == [3] # Could be decided now Goal: The structure we use makes it easy to tell what ``my_append`` may be. So, there should be a means to ask it about call results with given type/value information. We need to be able to tell, if evaluating ``my_append`` makes sense with given parameters or not, if it does impact the return value. We should e.g. be able to make ``my_append`` tell, one or more of these: - Returns the first parameter value as return value (unless it raises an exception). - The return value has the same type as ``a`` (unless it raises an exception). - The return value has an ``append`` attribute. - The return value might be a ``list`` object. - The return value may not be a ``str`` object. - The function will raise if first argument has no ``append`` attribute. The exactness of statements may vary. But some things may be more interesting. If e.g. the aliasing of a parameter value to the return value is known exactly, then information about it need to all be given up, but some can survive. It would be nice, if ``my_append`` had sufficient information, so we could specialize with ``list`` and ``int`` from the parameters, and then e.g. know at least some things that it does in that case. Such specialization would have to be decided if it makes sense. In the alternative, it could be done for each variant anyway, as there won't be that many of them. Doing this "forward" analysis appears to be best suited for functions and therefore long term. We will try it that way. Excursion to Loops ================== .. code:: python a = 1 while 1: # think loop: here b = a + 1 a = b if cond(): break print(a) The handling of loops (both ``for`` and ``while`` are re-formulated to this kind of loops with ``break`` statements) has its own problem. The loop start and may have an assumption from before it started, that ``a`` is constant, but that is only true for the first iteration. So, we can't pass knowledge from outside loop forward directly into the for loop body. So the collection for loops needs to be two pass for loops. First, to collect assignments, and merge these into the start state, before entering the loop body. The need to make two passes is special to loops. For a start, it is done like this. At loop entry, all pre-existing, but written traces, are turned into loop merges. Knowledge is not completely removed about everything assigned or changed in the loop, but then it's not trusted anymore. From that basis, the ``break`` exits are analysed, and merged, building up the post loop state, and ``continue`` exits of the loop replacing the unknown part of the loop entry state. The loop end is considered a ``continue`` for this purpose. Excursion to Conditions ======================= .. code:: python if cond: x = 1 else: x = 2 b = x < 3 The above code contains a condition, and these have the problem, that when exiting the conditional block, a merge must be done, of the ``x`` versions. It could be either one. The merge may trace the condition under which a choice is taken. That way, we could decide pairs of traces under the same condition. These merges of SSA variable "versions", represent alternative values. They pose difficulties, and might have to be reduced to commonality. In the above example, the ``<`` operator will have to check for each version, and then to decide that both indeed give the same result. The trace collection tracks variable changes in conditional branches, and then merges the existing state at conditional statement exits. .. note:: A branch is considered "exiting" if it is not abortive. Should it end in a ``raise``, ``break``, ``continue``, or ``return``, there is no need to merge that branch, as execution of that branch is terminated. Should both branches be abortive, that makes things really simple, as there is no need to even continue. Should only one branch exist, but be abortive, then no merge is needed, and the collection can assume after the conditional statement, that the branch was not taken, and continue. When exiting both the branches, these branches must both be merged, with their new information. In the above case: - The "yes" branch knows variable ``x`` is an ``int`` of constant value ``1`` - The "no" branch knows variable ``x`` is an ``int`` of constant value ``2`` That might be collapsed to: - The variable ``x`` is an integer of value in ``(1,2)`` Given this, we then should be able to precompute the value of this: .. code:: python b = x < 3 The comparison operator can therefore decide and tell: - The variable ``b`` is a boolean of constant value ``True``. Were it unable to decide, it would still be able to say: - The variable ``b`` is a boolean. For conditional statements optimization, it's also noteworthy, that the condition is known to pass or not pass the truth check, inside branches, and in the case of non-exiting single branches, after the statement it's not true. We may want to take advantage of it. Consider e.g. .. code:: python if type(a) is list: a.append(x) else: a += (x,) In this case, the knowledge that ``a`` is a list, could be used to generate better code and with the definite knowledge that ``a`` is of type list. With that knowledge the ``append`` attribute call will become the ``list`` built-in type operation. Excursion to ``return`` statements ================================== The ``return`` statement (like ``break``, ``continue``, ``raise``) is "aborting" to control flow. It is always the last statement of inspected block. When there statements to follow it, optimization will remove it as "dead code". If all branches of a conditional statement are "aborting", the statement is decided "aborting" too. If a loop doesn't abort with a break, it should be considered "aborting" too. Excursion to ``yield`` expressions ================================== The ``yield`` expression can be treated like a normal function call, and as such invalidates some known constraints just as much as they do. It executes outside code for an unknown amount of time, and then returns, with little about the outside world known anymore, if it's accessible from there. Mixed Types =========== Consider the following inside a function or module: .. code:: python if cond is not None: a = [x for x in something() if cond(x)] else: a = () A programmer will often not make a difference between ``list`` and ``tuple``. In fact, using a ``tuple`` is a good way to express that something won't be changed later, as these are mutable. .. note:: Better programming style, would be to use this: .. code:: python if cond is not None: a = tuple(x for x in something() if cond(x)) else: a = () People don't do it, because they dislike the performance hit encountered by the generator expression being used to initialize the tuple. But it would be more consistent, and so Nuitka is using it, and of course one day Nuitka ought to be able to make no difference in performance for it. To Nuitka though this means, that if ``cond`` is not predictable, after the conditional statement we may either have a ``tuple`` or a ``list`` type object in ``a``. In order to represent that without resorting to "I know nothing about it", we need a kind of ``min``/``max`` operating mechanism that is capable of say what is common with multiple alternative values. .. note:: At this time, we don't really have that mechanism to find the commonality between values. Back to "ctypes" ================ .. code:: python v = ctypes.c_int() Coming back to this example, we needed to propagate ``ctypes``, then we can propagate "something" from ``ctypes.int`` and then known what this gives with a call and no arguments, so the walk of the nodes, and diverse operations should be addressed by a module friend. In case a module friend doesn't know what to do, it needs to say so by default. This should be enforced by a base class and give a warning or note. Now to the interface ==================== The following is the intended interface: - Iteration with node methods ``computeStatement`` and ``computeExpression``. These traverse modules and functions (i.e. scopes) and visit everything in the order that Python executes it. The visiting object is ``TraceCollection`` and pass forward. Some node types, e.g. ``StatementConditional`` new create branch trace collections and handle the SSA merging at exit. - Replacing nodes during the visit. Both ``computeStatement`` and ``computeExpression`` are tasked to return potential replacements of themselves, together with "tags" (meaningless now), and a "message", used for verbose tracing. The replacement node of ``+`` operator, may e.g. be the pre-computed constant result, wrapped in side effects of the node, or the expression raised, again wrapped in side effects. - Assignments and references affect SSA. The SSA tree is initialized every time a scope is visited. Then during traversal, traces are built up. Every assignment and merge starts a new trace for that matter. References to a given variable version are traced that way. - Value escapes are traced too. When an operation hands over a value to outside code, it indicates so to the trace collection. This is for it to know, when e.g. a constant value, might be mutated meanwhile. - Nodes can be queried about their properties. There is a type shape and a value shape that each node can be asked about. The type shape offers methods that allow to check if certain operations are at all supported or not. These can always return ``True`` (yes), ``False`` (no), and ``None`` (cannot decide). In the case of the later, optimizations may not be able do much about it. Lets call these values "tri-state". There is also the value shape of a node. This can go deeper, and be more specific to a given node. The default implementation will be very pessimistic. Specific node types and shapes may then declare, that they e.g. have no side effects, will not raise for certain operations, have a known truth value, have a known iteration length, can predict their iteration values, etc. - Nodes are linked to certain states. During the collect, a variable reference, is linked to a certain trace state, and that can be used by parent operations. .. code:: python a = 1 b = a + a In this example, the references to ``a``, can look-up the ``1`` in the trace, and base value shape response to ``+`` on it. For compile time evaluation, it may also ask ``isCompileTimeConstant()`` and if both nodes will respond ``True``, then "getCompileTimeConstant()" will return ``1``, which will be be used in computation. Then ``extractSideEffects()`` for the ``a`` reference will return ``()`` and therefore, the result ``2`` will not be wrapped. An alternative approach would be ``hasTypeSlotAdd()`` on the both nodes, and they both do, to see if the selection mechanism used by CPython can be used to find which types ``+`` should be used. - Class for module import expression ``ExpressionImportModule``. This one just knows that something is imported, but not how or what it is assigned to. It will be able in a recursive compile, to provide the module as an assignment source, or the module variables or submodules as an attribute source when referenced from a variable trace or in an expression. - Base class for module friend ``ModuleFriendBase``. This is intended to provide something to overload, which e.g. can handle ``math`` in a better way. - Module ``ModuleFriendRegistry`` Provides a register function with ``name`` and instances of ``ValueFriendModuleBase`` to be registered. Recursed to modules should integrate with that too. The registry could well be done with a metaclass approach. - The module friends should each live in a module of their own. With a naming policy to be determined. These modules should add themselves via above mechanism to ``ModuleFriendRegistry`` and all shall be imported and register. Importing of e.g. ``ctypes`` should be delayed to when the friend is actually used. A meta class should aid this task. The delay will avoid unnecessary blot of the compiler at run time, if no such module is used. For "qt" and other complex stuff, this will be a must. - The walk should initially be single pass, and not maintain history. Instead optimization that needs to look at multiple things, e.g. "unused assignment", will look at the whole SSA collection afterwards. Discussing with examples ======================== The following examples: .. code:: python # Assignment, the source decides the type of the assigned expression a = b # Operator "attribute look-up", the looked up expression "ctypes" decides # via its trace. ctypes.c_int # Call operator, the called expressions decides with help of arguments, # which have been walked, before the call itself. called_expression_of_any_complexity() # import gives a module any case, and the "ModuleRegistry" may say more. import ctypes # From import need not give module, "x" decides what it is. from x import y # Operations are decided by arguments, and CPython operator rules between # argument states. a + b The optimization is mostly performed by walking of the tree and performing trace collection. When it encounters assignments and references to them, it considers current state of traces and uses it for ``computeExpression``. .. note:: Assignments to attributes, indexes, slices, etc. will also need to follow the flow of ``append``, so it cannot escape attention that a list may be modified. Usages of ``append`` that we cannot be sure about, must be traced to exist, and disallow the list to be considered known value again. Code Generation Impact ====================== Right now, code generation assumes that everything is a ``PyObject *``, i.e. a Python object, and does not take knowledge of ``int`` or other types into consideration at all, and it should remain like that for some time to come. Instead, ``ctypes`` value friend will be asked give ``Identifiers``, like other codes do too. And these need to be able to convert themselves to objects to work with the other things. But Code Generation should no longer require that operations must be performed on that level. Imagine e.g. the following calls: .. code:: python c_call(other_c_call()) Value returned by "other_c_call()" of say ``c_int`` type, should be possible to be fed directly into another call. That should be easy by having a ``asIntC()`` in the identifier classes, which the ``ctypes`` Identifiers handle without conversions. Code Generation should one day also become able to tell that all uses of a variable have only ``c_int`` value, and use ``int`` instead of ``PyObjectLocalVariable`` more or less directly. We could consider ``PyIntLocalVariable`` of similar complexity as ``int`` after the C++ compiler performed its in-lining. Such decisions would be prepared by finalization, which then would track the history of values throughout a function or part of it. Initial Implementation ====================== The basic interface will be added to *all* expressions and a node may override it, potentially using trace collection state, as attached during ``computeExpression``. Goal 1 (Reached) ---------------- Initially most things will only be able to give up on about anything. And it will be little more than a tool to do simple look-ups in a general form. It will then be the first goal to turn the following code into better performing one: .. code:: python a = 3 b = 7 c = a / b print(c) to: .. code:: python a = 3 b = 7 c = 3 / 7 print(c) and then: .. code:: python a = 3 b = 7 c = 0 print(c) and then: .. code:: python a = 3 b = 7 c = 0 print(0) This depends on SSA form to be able to tell us the values of ``a``, ``b``, and ``c`` to be written to by constants, which can be forward propagated at no cost. Goal 2 (Reached) ---------------- The assignments to ``a``, ``b``, and ``c`` shall all become prey to "unused" assignment analysis in the next step. They are all only assigned to, and the assignment source has no effect, so they can be simply dropped. .. code:: python print(0) In the SSA form, these are then assignments without references. These assignments, can be removed if the assignment source has no side effect. Or at least they could be made "anonymous", i.e. use a temporary variable instead of the named one. That would have to take into account though, that the old version still needs a release. The most general form would first merely remove assignments that have no impact, and leave the value as a side effect, so we arrive at this first: .. code:: python 3 7 0 print(0) When applying the removal of expression only statements without effect, this gives us: .. code:: python print(0) which is the perfect result. Doing it in one step would only be an optimization at the cost of generalization. In order to be able to manipulate nodes related to a variable trace, we need to attach the nodes that did it. Consider this: .. code:: python if cond(): x = 1 elif other(): x = 3 # Not using "x". print(0) In the above case, the merge of the value traces, should say that ``x`` may be undefined, or one of ``1`` or ``3``, but since ``x`` is not used, apply the "dead value" trick to each branch. The removal of the "merge" of the 3 ``x`` versions, should exhibit that the other versions are also only assigned to, and can be removed. These merges of course appear as usages of the ``x`` versions. Goal 3 ------ Then third goal is to understand all of this: .. code:: python def f(): a = [] print(a) for i in range(1000): print(a) a.append(i) return len(a) .. note:: There are many operations in this, and all of them should be properly handled, or at least ignored in safe way. The first goal code gave us that the ``list`` has an annotation from the assignment of ``[]`` and that it will be copied to ``a`` until the for loop in encountered. Then it must be removed, because the ``for`` loop somehow says so. The ``a`` may change its value, due to the unknown attribute look-up of it already, not even the call. The for loop must be able to say "may change value" due to that, of course also due to the call of that attribute too. The code should therefore become equivalent to: .. code:: python def f(): a = [] print([]) for i in range(1000): print(a) a.append(i) return len(a) But no other changes must occur, especially not to the ``return`` statement, it must not assume ``a`` to be constant "[]" but an unknown ``a`` instead. With that, we would handle this code correctly and have some form constant value propagation in place, handle loops at least correctly, and while it is not much, it is important demonstration of the concept. Goal 4 ------ The fourth goal is to understand the following: .. code:: python def f(cond): y = 3 if cond: x = 1 else: x = 2 return x < y In this we have a branch, and we will be required to keep track of both the branches separately, and then to merge with the original knowledge. After the conditional statement we will know that "x" is an "int" with possible values in ``(1,2)``, which can be used to predict that the return value is always ``True``. The forth goal will therefore be that the "ValueFriendConstantList" knows that append changes ``a`` value, but it remains a list, and that the size increases by one. It should provide an other value friend "ValueFriendList" for "a" due to that. In order to do that, such code must be considered: .. code:: python a = [] a.append(1) a.append(2) print(len(a)) It will be good, if ``len`` still knows that ``a`` is a list object, but not the constant list anymore. From here, work should be done to demonstrate the correctness of it with the basic tests applied to discover undetected issues. Fifth and optional goal: Extra bonus points for being able to track and predict ``append`` to update the constant list in a known way. Using ``list.append`` that should be done and lead to a constant result of ``len`` being used. The sixth and challenging goal will be to make the code generation be impacted by the value friends types. It should have a knowledge that ``PyList_Append`` does the job of append and use ``PyList_Size`` for ``len``. The "ValueFriends" should aid the code generation too. Last and right now optional goal will be to make ``range`` have a value friend, that can interact with iteration of the for loop, and ``append`` of the ``list`` value friend, so it knows it's possible to iterate 5000 times, and that "a" has then after the "loop" this size, so ``len(a)`` could be predicted. For during the loop, about a the range of its length should be known to be less than 5000. That would make the code of goal 2 completely analyzed at compile time. Limitations for now =================== - Aim only for limited examples. For ``ctypes`` that means to compile time evaluate: .. code:: python print(ctypes.c_int(17) + ctypes.c_long(19)) Later then call to "libc" or something else universally available, e.g. "strlen()" or "strcmp()" from full blown declarations of the callable. - We won't have the ability to test that optimization are actually performed, we will check the generated code by hand. With time, we will add XML based checks with "xpath" queries, expressed as hints, but that is some work that will be based on this work here. The "hints" fits into the "ValueFriends" concept nicely or so the hope is. - No inter-function optimization functions yet Of course, once in place, it will make the ``ctypes`` annotation even more usable. Using ``ctypes`` objects inside functions, while creating them on the module level, is therefore not immediately going to work. - No loops yet Loops break value propagation. For the ``ctypes`` use case, this won't be much of a difficulty. Due to the strangeness of the task, it should be tackled later on at a higher priority. - Not too much. Try and get simple things to work now. We shall see, what kinds of constraints really make the most sense. Understanding ``list`` subscript/slice values e.g. is not strictly useful for much code and should not block us. .. note:: This design is not likely to be the final one. *********************************** How to make Features Experimental *********************************** Every experimental feature needs a name. We have a rule to pick a name with lower case and ``_`` as separators. An example of with would be the name ``jinja_generated_add`` that has been used in the past. Command Line ============ Experimental features are enabled with the command line argument .. code:: bash nuitka --experimental=jinja_generated_add ... In C code ========= In Scons, all experimental features automatically are converted into C defines, and can be used like this: .. code:: C #ifdef _NUITKA_EXPERIMENTAL_JINJA_GENERATED_ADD #include "HelpersOperationGeneratedBinaryAdd.c" #else #include "HelpersOperationBinaryAdd.c" #endif The C pre-processor is the only thing that makes an experimental feature usable. In Python ========= You can query experimental features using ``Options.isExperimental()`` with e.g. code like this: .. code:: python if Options.isExperimental("use_feature"): experimental_code() else: standard_code() When to use it ============== Often we need to keep feature in parallel because they are not finished, or need to be tested after merge and should not break. Then we can do code changes that will not make a difference except when the experimental flag is given on the command line to Nuitka. The testing of Nuitka is very heavy weight when e.g. all Python code is compiled, and very often, it is interesting to compare behavior with and without a change. When to remove it ================= When a feature becomes default, we might choose to keep the old variant around, but normally we do not. Then we remove the ``if`` and ``#if`` checks and drop the old code. At this time, large scale testing will have demonstrated the viability of the code. ******************************* Adding dependencies to Nuitka ******************************* First of all, there is an important distinction to make, runtime or development time. The first kind of dependency is used when Nuitka is executing. Adding a Runtime Dependency =========================== This is the kind of dependency that is the most scrutinized. As we want Nuitka to run on latest greatest Python as well as relatively old ones, we have to be very careful with these ones. There is also a distinction of optional dependencies. Right now e.g. the ``lxml`` package is relatively optional, and Nuitka can work without it being installed, because e.g. on some platforms it will not be easy to do so. That bar has lifted somewhat, but it means e.g. that XML based optimization tests are not run with all Python versions. The list of runtime dependencies is in ``requirements.txt`` and it is for those the case, that they are not really required to be installed by the user, consider this snippet: .. code:: python # Folders to use for cache files. appdirs # Scons is the backend building tool to turn C files to binaries. scons For both these dependencies, there is either an inline copy (Scons) that we handle to use in case, if Scons is not available (in fact we have a version that works with Python 2.6 and 2.7 still), and also the same for appdirs and every dependency. But since inline copies are against the rules on some platforms that still do not contain the package, we often even have our own wrapper which provides a minimal fallback or exposes a sane interface for the subset of functionality that we use. .. note:: Therefore, please if you consider adding one of these, get in touch with ``@Nuitka-pushers`` first and get a green light. Adding a Development Dependency =============================== A typical example of a development dependency is ``black`` which is used by our autoformat tool, and then in turn by the git pre-commit hook. It is used to format source code, and doesn't have a role at run time of the actual compiler code of Nuitka. Much less strict rules apply to these in comparison to runtime dependencies. Generally please take care that the tool must be well maintained an available on newer Pythons. Then we can use it, no problem normally. But if it's really big, say all of SciPy, we might want to justify it a bit better. The list of development dependencies is in ``requirements-devel.txt`` and it is for example like this: .. code:: python # Autoformat needs this rstfmt == 0.0.10 ; python_version >= '3.7' We always add the version, so that when tests run on as old versions as Python 2.6, the installation would fail with that version, so we need to make a version requirement. Sometimes we use older versions for Python2 than for Python3, ``Jinaj2`` being a notable candidate, but generally we ought to avoid that. For many tools only being available for currently 3.7 or higher is good enough, esp. if they are run as development tools, like ``autoformat-nuitka-source`` is. ********** Idea Bin ********** This an area where to drop random ideas on our minds, to later sort it out, and out it into action, which could be code changes, plan changes, issues created, etc. - Make "SELECT_METACLASS" meta class selection transparent. Looking at the "SELECT_METACLASS" it should become an anonymous helper function. In that way, the optimization process can remove choices at compile time, and e.g. in-line the effect of a meta class, if it is known. This of course makes most sense, if we have the optimizations in place that will allow this to actually happen. - Keeping track of iterations The trace collection trace should become the place, where variables or values track their use state. The iterator should keep track of the "next()" calls made to it, so it can tell which value to given in that case. That would solve the "iteration of constants" as a side effect and it would allow to tell that they can be removed. That would mean to go back in the tree and modify it long after. .. code:: python a = iter((2, 3)) b = next(a) c = next(a) del a It would be sweet if we could recognize that as: .. code:: python a = iter((2, 3)) b = side_effect(next(a), 2) c = side_effect(next(a), 3) del a That trivially becomes: .. code:: python a = iter((2, 3)) next(a) b = 2 next(a) c = 3 del a When the ``del a`` is examined at the end of scope, or due to another assignment to the same variable, ending the trace, we would have to consider of the ``next`` uses, and retrofit the information that they had no effect. .. code:: python a = iter((2, 3)) b = 2 b = 3 del a - Aliasing Each time an assignment is made, an alias is created. A value may have different names. .. code:: python a = iter(range(9)) b = a c = next(b) d = next(a) If we fail to detect the aliasing nature, we will calculate ``d`` wrongly. We may incref and decref values to trace it. Aliasing is automatically traced already in SSA form. The ``b`` is assigned to version of ``a``. So, that should allow to replace it with this: .. code:: python a = iter(range(9)) c = next(a) d = next(a) Which then will be properly handled. - Tail recursion optimization. Functions that return the results of calls, can be optimized. The Stackless Python does it already. - Integrate with "upx" compression. Calling "upx" on the created binaries, would be easy. - In-lining constant "exec" and "eval". It should be possible to re-formulate at least cases without "locals" or "globals" given. .. code:: python def f(): a = 1 b = 2 exec("""a+=b;c=1""") return a, c Should become this here: .. code:: python def f(): a = 1 b = 2 a += b # c = 1 # MaybeLocalVariables for everything except known local ones. return a, c If this holds up, inlining ``exec`` should be relatively easy. - Original and overloaded built-ins This is about making things visible in the node tree. In Nuitka things that are not visible in the node tree tend to be wrong. We already pushed around information to the node tree a lot. Later versions, Nuitka will become able to determine it has to be the original built-in at compile time, then a condition that checks will be optimized away, together with the slow path. Or the other path, if it won't be. Then it will be optimized away, or if doubt exists, it will be correct. That is the goal. Right now, the change would mean to effectively disable all built-in call optimization, which is why we don't immediately do it. Making the compatible version, will also require a full listing of all built-ins, which is typing work merely, but not needed now. And a way to stop built-in optimization from optimizing built-in calls that it used in a wrap. Probably just some flag to indicate it when it visits it to skip it. That's for later. But should we have that both, I figure, we could not raise a ``RuntimeError`` error, but just do the correct thing, in all cases. An earlier step may raise ``RuntimeError`` error, when built-in module values are written to, that we don't support. ****************** Prongs of Action ****************** In this chapter, we keep track of prongs of action currently ongoing. This can get detailed and shows things we strive for. Builtin optimization ==================== Definitely want to get built-in names under full control, so that variable references to module variables do not have a twofold role. Currently they reference the module variable and also the potential built-in as a fallback. In terms of generated code size and complexity for modules with many variables and uses of them that is horrible. But ``some_var`` (normally) cannot be a built-in and therefore needs no code to check for that each time. This is also critical to getting to whole program optimization. Being certain what is what there on module level, will enable more definitely knowledge about data flows and module interfaces. Class Creation Overhead Reduction ================================= This is more of a meta goal. Some work for the metaclass has already been done, but that is Python2 only currently. Being able to to decide built-ins and to distinguish between global only variables, and built-ins more clearly will help this a lot. In the end, empty classes should be able to be statically converted to calls to ``type`` with static dictionaries. The inlining of class creation function is also needed for this, but on Python3 cannot happen yet. Memory Usage at Compile Time ============================ We will need to store more and more information in the future. Getting the tree to be tight shaped is therefore an effort, where we will be spending time too. The mix-ins prevent slots usage, so lets try and get rid of those. The "children having" should become more simple and faster code. I am even thinking of even generating code in the meta class, so it's both optimal and doesn't need that mix-in any more. This is going to be ugly then. Coverage Testing ================ And then there is coverage, it should be taken and merged from all Python versions and OSes, but I never managed to merge between Windows and Linux for unknown reasons. Python3 Performance =================== The Python3 lock for thread state is making it slower by a lot. I have only experimental code that just ignores the lock, but it likely only works on Linux, and I wonder why there is that lock in the first place. Ignoring the locks cannot be good. But what updates that thread state pointer ever without a thread change, and is this what abiflags are about in this context, are there some that allow us to ignore the locks. An important bit would be to use a thread state once acquired for as much as possible, currently exception helpers do not accept it as an argument, but that ought to become an option, that way saving and restoring an exception will be much faster, not to mention checking and dropping non interesting, or rewriting exceptions. Onefile compression on Windows ============================== We need to add compression on that platform too. This should use zstd and probably just needs integration into our build. The Python side already is capable of producing compressed payload. Caching of Python level compilation =================================== While the C compilation result is already cached with ccache and friends now, we need to also cover our bases and save the resulting node tree of potential expensive optimization on the module level. ************************* Updates for this Manual ************************* This document is written in REST. That is an ASCII format which is readable to human, but easily used to generate PDF or HTML documents. You will find the current source under: https://github.com/Nuitka/Nuitka/blob/develop/Developer_Manual.rst And the current PDF under: https://nuitka.net/doc/Developer_Manual.pdf Nuitka-0.6.19.1/setup.py0000600000372100037210000003253014166627112022004 0ustar nuitka-buildslavenuitka-buildslave00000000000000# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Setup file for Nuitka. This applies a few tricks. First, the Nuitka version is read from the source code. Second, the packages are scanned from the filesystem, and third, the byte code compilation is avoided for inline copies of scons with mismatching Python major versions. """ import os import sys os.chdir(os.path.dirname(__file__) or ".") sys.path.insert(0, os.path.abspath(os.getcwd())) # isort:start import re from setuptools import setup from setuptools.command import easy_install # TODO: We need a better solution for this, probably # error exit, once sys.exit is optimized for. This is # to avoid descending into Nuitka through distutils. if __name__ == "__main__": from nuitka.PythonFlavors import isMSYS2MingwPython scripts = [] # For Windows, there are batch files to launch Nuitka. if os.name == "nt" and not isMSYS2MingwPython(): scripts += ["misc/nuitka.bat", "misc/nuitka-run.bat"] # Detect the version of Nuitka from its source directly. Without calling it, we # don't mean to pollute with ".pyc" files and similar effects. def detectVersion(): # Encoding is not needed, pylint: disable=unspecified-encoding with open("nuitka/Version.py") as version_file: (version_line,) = [line for line in version_file if line.startswith("Nuitka V")] return version_line.split("V")[1].strip() version = detectVersion() # The MSI installer enforces a 3 digit version number, which is stupid, but no # way around it, so we map our number to it, in some way. if os.name == "nt" and "bdist_msi" in sys.argv: # Pre-releases are always smaller, official releases get the "1". middle = 1 if "rc" not in version else 0 version = version.replace("rc", "") parts = version.split(".") major, first, last = parts[:3] hotfix = parts[3] if len(parts) > 3 else 0 version = ".".join( "%s" % value for value in ( int(major) * 10 + int(first), middle, int(last) * 10 + int(hotfix), ) ) def findNuitkaPackages(): result = [] for root, dirnames, filenames in os.walk("nuitka"): # Packages must contain "__init__.py" or they are merely directories # in Nuitka as we are Python2 compatible. if "__init__.py" not in filenames: continue # The "release" namespace is code used to release, but not itself for # release, same goes for "quality". if "release" in dirnames: dirnames.remove("release") if "quality" in dirnames: dirnames.remove("quality") # Handled separatedly. if "inline_copy" in dirnames: dirnames.remove("inline_copy") result.append(root.replace(os.path.sep, ".")) return result inline_copy_files = [] def addInlineCopy(name): inline_copy_files.extend( ( "inline_copy/%s/*.py" % name, "inline_copy/%s/*/*.py" % name, "inline_copy/%s/*/*/*.py" % name, "inline_copy/%s/*/*/*/*.py" % name, "inline_copy/%s/*/*/*/*/*.py" % name, "inline_copy/%s/LICENSE*", "inline_copy/%s/*/LICENSE*", "inline_copy/%s/READ*", ) ) addInlineCopy("appdirs") addInlineCopy("glob2") addInlineCopy("markupsafe") addInlineCopy("tqdm") sdist_mode = "sdist" in sys.argv if os.name == "nt" or sdist_mode: addInlineCopy("atomicwrites") addInlineCopy("clcache") addInlineCopy("colorama") if sys.version_info < (3,) or sdist_mode: addInlineCopy("yaml_27") if (3,) < sys.version_info < (3, 6) or sdist_mode: addInlineCopy("yaml_35") if sys.version_info >= (3, 6) or sdist_mode: addInlineCopy("yaml") if sys.version_info < (3, 6) or sdist_mode: addInlineCopy("jinja2_35") if sys.version_info >= (3, 6) or sdist_mode: addInlineCopy("jinja2") # Scons really only, with historic naming and positioning. Needs to match the # "scons.py" in bin with respect to versions selection. addInlineCopy("bin") if os.name == "nt" or sdist_mode: addInlineCopy("lib/scons-4.3.0") if (os.name != "nt" and sys.version_info < (2, 7)) or sdist_mode: addInlineCopy("lib/scons-2.3.2") if (os.name != "nt" and sys.version_info >= (2, 7)) or sdist_mode: addInlineCopy("lib/scons-3.1.2") # Have different project names for MSI installers, so 32 and 64 bit versions do # not conflict. if "bdist_msi" in sys.argv: project_name = "Nuitka%s" % (64 if "AMD64" in sys.version else 32) else: project_name = "Nuitka" import distutils.util orig_byte_compile = distutils.util.byte_compile def byte_compile(py_files, *args, **kw): # Disable bytecode compilation output, too annoying. kw["verbose"] = 0 orig_byte_compile(py_files, *args, **kw) distutils.util.byte_compile = byte_compile # We monkey patch easy install script generation to not load pkg_resources, # which is very slow to launch. This can save one second or more per launch # of Nuitka. runner_script_template = """\ # -*- coding: utf-8 -*- # Launcher for Nuitka import nuitka.__main__ nuitka.__main__.main() """ # This is for newer setuptools: @classmethod def get_args(cls, dist, header=None): """ Yield write_script() argument tuples for a distribution's console_scripts and gui_scripts entry points. """ if header is None: header = cls.get_header() for type_ in "console", "gui": group = type_ + "_scripts" for name, _ep in dist.get_entry_map(group).items(): script_text = runner_script_template args = cls._get_script_args( # pylint: disable=protected-access type_, name, header, script_text ) for res in args: yield res try: easy_install.ScriptWriter.get_args = get_args except AttributeError: pass # This is for older setuptools: def get_script_args(dist, executable=os.path.normpath(sys.executable), wininst=False): """Yield write_script() argument tuples for a distribution's entrypoints""" header = easy_install.get_script_header("", executable, wininst) for group in "console_scripts", "gui_scripts": for name, _ep in dist.get_entry_map(group).items(): script_text = runner_script_template if sys.platform == "win32" or wininst: # On Windows/wininst, add a .py extension and an .exe launcher if group == "gui_scripts": launcher_type = "gui" ext = "-script.pyw" old = [".pyw"] new_header = re.sub("(?i)python.exe", "pythonw.exe", header) else: launcher_type = "cli" ext = "-script.py" old = [".py", ".pyc", ".pyo"] new_header = re.sub("(?i)pythonw.exe", "python.exe", header) if ( os.path.exists(new_header[2:-1].strip('"')) or sys.platform != "win32" ): hdr = new_header else: hdr = header yield (name + ext, hdr + script_text, "t", [name + x for x in old]) yield ( name + ".exe", easy_install.get_win_launcher(launcher_type), "b", # write in binary mode ) if not easy_install.is_64bit(): # install a manifest for the launcher to prevent Windows # from detecting it as an installer (which it will for # launchers like easy_install.exe). Consider only # adding a manifest for launchers detected as installers. # See Distribute #143 for details. m_name = name + ".exe.manifest" yield (m_name, easy_install.load_launcher_manifest(name), "t") else: # On other platforms, we assume the right thing to do is to # just write the stub with no extension. yield (name, header + script_text) try: easy_install.get_script_args except AttributeError: pass else: easy_install.get_script_args = get_script_args binary_suffix = "%d" % sys.version_info[0] if os.name == "nt" and not isMSYS2MingwPython(): console_scripts = [] else: console_scripts = [ "nuitka%s = nuitka.__main__:main" % binary_suffix, "nuitka%s-run = nuitka.__main__:main" % binary_suffix, ] with open("README.rst", "rb") as input_file: long_description = input_file.read().decode("utf8") # Need to remove the ..contents etc from the rest, or else PyPI will not render # it. long_description = long_description.replace(".. contents::\n", "") long_description = long_description.replace( ".. image:: doc/images/Nuitka-Logo-Symbol.png\n", "" ) setup( name=project_name, license="Apache License, Version 2.0", version=version, long_description=long_description, long_description_content_type="text/x-rst", classifiers=[ # Nuitka is mature even "Development Status :: 5 - Production/Stable", # Indicate who Nuitka is for "Intended Audience :: Developers", "Intended Audience :: Science/Research", # Nuitka is a compiler and a build tool as such. "Topic :: Software Development :: Compilers", "Topic :: Software Development :: Build Tools", # Is has a weak subset of PyLint, but aims for more long term "Topic :: Software Development :: Quality Assurance", # Nuitka standalone mode aims at distribution "Topic :: System :: Software Distribution", # Python2 supported versions. "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", # Python3 supported versions. "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", # We depend on CPython. "Programming Language :: Python :: Implementation :: CPython", # We generate C intermediate code and implement part of the # run time environment in C. Actually C11. "Programming Language :: C", # Supported OSes are many "Operating System :: POSIX :: Linux", "Operating System :: POSIX :: BSD :: FreeBSD", "Operating System :: POSIX :: BSD :: NetBSD", "Operating System :: POSIX :: BSD :: OpenBSD", "Operating System :: Microsoft :: Windows", # License "License :: OSI Approved :: Apache Software License", ], packages=findNuitkaPackages(), package_data={ # Include extra files "": ["*.txt", "*.rst", "*.c", "*.h", "*.yml"], "nuitka.build": [ "Backend.scons", "Onefile.scons", "static_src/*.c", "static_src/*.cpp", "static_src/*/*.c", "static_src/*/*.h", "inline_copy/zstd/*.h", "inline_copy/zstd/*/*.h", "inline_copy/zstd/*/*.c", "static_src/*/*.asm", "static_src/*/*.S", "include/*.h", "include/*/*.h", "include/*/*/*.h", ] + inline_copy_files, "nuitka.codegen": ["templates_c/*.j2"], }, # metadata for upload to PyPI author="Kay Hayen", author_email="Kay.Hayen@gmail.com", url="https://nuitka.net", description="""\ Python compiler with full language support and CPython compatibility""", keywords="compiler,python,nuitka", project_urls={ "Commercial": "https://nuitka.net/doc/commercial.html", "Support": "https://nuitka.net/pages/support.html", "Documentation": "https://nuitka.net/doc/user-manual.html", "Donations": "https://nuitka.net/pages/donations.html", "Twitter": "https://twitter.com/KayHayen", "Source": "https://github.com/Nuitka/Nuitka", }, zip_safe=False, scripts=scripts, entry_points={ "distutils.commands": [ "bdist_nuitka = \ nuitka.distutils.DistutilCommands:bdist_nuitka", "build_nuitka = \ nuitka.distutils.DistutilCommands:build", "install_nuitka = \ nuitka.distutils.DistutilCommands:install", ], "distutils.setup_keywords": [ "build_with_nuitka = nuitka.distutils.DistutilCommands:setupNuitkaDistutilsCommands" ], "console_scripts": console_scripts, }, ) Nuitka-0.6.19.1/bin/0000700000372100037210000000000014167275622021043 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/bin/compare_with_cpython0000700000372100037210000000217514166627112025215 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for output comparison tool. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start from nuitka.tools.testing.compare_with_cpython.__main__ import main main() Nuitka-0.6.19.1/bin/nuitka0000700000372100037210000000322414166627112022257 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for Nuitka the compiler itself. """ # Import as little as possible initially, because we might be re-executing # soon. import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start import nuitka.__main__ # false alarm, pylint: disable=I0021,no-name-in-module # Remove the nuitka package directory again, it might contain other stuff that we # do not want added automatically. del sys.path[0] # The bin folder of the runner can't be that helpful, but got added automatically, # so attempt to remove it. sys.path = [ path_element for path_element in sys.path if os.path.dirname(os.path.abspath(__file__)) != path_element ] # Now execute Nuitka in a clean environment. nuitka.__main__.main() Nuitka-0.6.19.1/bin/autoformat-nuitka-source0000700000372100037210000000215514166627112025736 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python3 # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for autoformat tool. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start from nuitka.tools.quality.autoformat.__main__ import main main() Nuitka-0.6.19.1/bin/compare_with_xml0000700000372100037210000000605514166627112024332 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Tool to compare XML outputs of two Nuitka versions. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start import difflib from nuitka.tools.testing.Common import my_print from nuitka.utils.Execution import executeProcess nuitka1 = sys.argv[1] nuitka2 = sys.argv[2] filename = sys.argv[3] my_print( """\ Comparing output of '{filename}' using '{nuitka1}' <-> '{nuitka2}' ...""".format( filename=filename, nuitka1=nuitka1, nuitka2=nuitka2 ) ) extra_options = os.environ.get("NUITKA_EXTRA_OPTIONS", "") nuitka1_cmd = "{nuitka1} --xml {filename}".format(nuitka1=nuitka1, filename=filename) nuitka2_cmd = "{nuitka2} --xml {filename}".format(nuitka2=nuitka2, filename=filename) stdout_nuitka1, stderr_nuitka1, exit_nuitka1 = executeProcess(nuitka1_cmd, shell=True) stdout_nuitka2, stderr_nuitka2, exit_nuitka2 = executeProcess(nuitka2_cmd, shell=True) def makeDiffable(output): result = [] for line in output.split(b"\n"): line = str(line) result.append(line) return result fromdate = None todate = None def compareOutput(kind, out1, out2): diff = difflib.unified_diff( makeDiffable(out1), makeDiffable(out2), "{program} ({detail})".format(program="nuitka1 " + filename, detail=kind), "{program} ({detail})".format(program="nuitka2 " + filename, detail=kind), fromdate, todate, n=3, ) result = list(diff) if result: for line in result: my_print(line, end="\n" if not line.startswith("---") else "") return 1 else: return 0 exit_code_stdout = compareOutput("stdout", stdout_nuitka1, stdout_nuitka2) exit_code_return = exit_nuitka1 != exit_nuitka2 if exit_code_return: my_print( """\ Exit codes {exit_nuitka1:d} ({nuitka1}) != {exit_nuitka2:d} ({nuitka2})""".format( exit_nuitka1=exit_nuitka1, nuitka1=nuitka1, exit_nuitka2=exit_nuitka2, nuitka2=nuitka2, ) ) exit_code = exit_code_stdout or exit_code_return if exit_code: sys.exit("Error, outputs differed.") my_print("OK, same outputs.") Nuitka-0.6.19.1/bin/check-nuitka-with-pylint0000700000372100037210000000215714166627112025624 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python3.9 # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for pylint checker tool. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start from nuitka.tools.quality.pylint.__main__ import main main() Nuitka-0.6.19.1/bin/nuitka-run0000700000372100037210000000322414166627112023061 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for Nuitka the compiler itself. """ # Import as little as possible initially, because we might be re-executing # soon. import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start import nuitka.__main__ # false alarm, pylint: disable=I0021,no-name-in-module # Remove the nuitka package directory again, it might contain other stuff that we # do not want added automatically. del sys.path[0] # The bin folder of the runner can't be that helpful, but got added automatically, # so attempt to remove it. sys.path = [ path_element for path_element in sys.path if os.path.dirname(os.path.abspath(__file__)) != path_element ] # Now execute Nuitka in a clean environment. nuitka.__main__.main() Nuitka-0.6.19.1/bin/measure-construct-performance0000700000372100037210000000221214166627112026742 0ustar nuitka-buildslavenuitka-buildslave00000000000000#!/usr/bin/env python # Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com # # Part of "Nuitka", an optimizing Python compiler that is compatible and # integrates with CPython, but also works on its own. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Launcher for construct performance tool. """ import os import sys # Unchanged, running from checkout, use the parent directory, the nuitka # package ought to be there. sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) # isort:start from nuitka.tools.testing.measure_construct_performance.__main__ import main main() Nuitka-0.6.19.1/LICENSE.txt0000600000372100037210000002612414166627112022117 0ustar nuitka-buildslavenuitka-buildslave00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright © 2010-2019 Kay Hayen Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Nuitka-0.6.19.1/misc/0000700000372100037210000000000014167275622021226 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/misc/nuitka.bat0000600000372100037210000000172214166627112023207 0ustar nuitka-buildslavenuitka-buildslave00000000000000@echo off rem Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com rem rem Part of "Nuitka", an optimizing Python compiler that is compatible and rem integrates with CPython, but also works on its own. rem rem Licensed under the Apache License, Version 2.0 (the "License"); rem you may not use this file except in compliance with the License. rem You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem setlocal if exist "%~dp0..\python.exe" ( "%~dp0..\python" -m nuitka %* ) else ( "%~dp0python" -m nuitka %* ) endlocal Nuitka-0.6.19.1/misc/nuitka-run.bat0000600000372100037210000000160414166627112024010 0ustar nuitka-buildslavenuitka-buildslave00000000000000@echo off rem Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com rem rem Part of "Nuitka", an optimizing Python compiler that is compatible and rem integrates with CPython, but also works on its own. rem rem Licensed under the Apache License, Version 2.0 (the "License"); rem you may not use this file except in compliance with the License. rem You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem setlocal "%~dp0nuitka.bat --run %* endlocal Nuitka-0.6.19.1/PKG-INFO0000600000372100037210000021252214167275622021376 0ustar nuitka-buildslavenuitka-buildslave00000000000000Metadata-Version: 2.1 Name: Nuitka Version: 0.6.19.1 Summary: Python compiler with full language support and CPython compatibility Home-page: https://nuitka.net Author: Kay Hayen Author-email: Kay.Hayen@gmail.com License: Apache License, Version 2.0 Project-URL: Support, https://nuitka.net/pages/support.html Project-URL: Documentation, https://nuitka.net/doc/user-manual.html Project-URL: Commercial, https://nuitka.net/doc/commercial.html Project-URL: Source, https://github.com/Nuitka/Nuitka Project-URL: Donations, https://nuitka.net/pages/donations.html Project-URL: Twitter, https://twitter.com/KayHayen Description: #################### Nuitka User Manual #################### ********** Overview ********** This document is the recommended first read if you are interested in using Nuitka, understand its use cases, check what you can expect, license, requirements, credits, etc. Nuitka is **the** Python compiler. It is written in Python. It is a seamless replacement or extension to the Python interpreter and compiles **every** construct that CPython 2.6, 2.7, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 have, when itself run with that Python version. It then executes uncompiled code and compiled code together in an extremely compatible manner. You can use all Python library modules and all extension modules freely. Nuitka translates the Python modules into a C level program that then uses ``libpython`` and static C files of its own to execute in the same way as CPython does. All optimization is aimed at avoiding overhead, where it's unnecessary. None is aimed at removing compatibility, although slight improvements will occasionally be done, where not every bug of standard Python is emulated, e.g. more complete error messages are given, but there is a full compatibility mode to disable even that. ******* Usage ******* Requirements ============ - C Compiler: You need a compiler with support for C11 or alternatively for C++03 [#]_ Currently this means, you need to use one of these compilers: - The MinGW64 C11 compiler on Windows, must be based on gcc 11.2 or higher. It will be *automatically* downloaded if no usable C compiler is found, which is the recommended way of installing it, as Nuitka will also upgrade it for you. - Visual Studio 2022 or higher on Windows [#]_, older versions will work but only supported for commercial users. Configure to use the English language pack for best results (Nuitka filters away garbage outputs, but only for English language). It will be used by default if installed. - On all other platforms, the ``gcc`` compiler of at least version 5.1, and below that the ``g++`` compiler of at least version 4.4 as an alternative. - The ``clang`` compiler on macOS X and most FreeBSD architectures. - On Windows the ``clang-cl`` compiler on Windows can be used if provided by the Visual Studio installer. - Python: Version 2.6, 2.7 or 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 .. admonition:: For Python 3.3/3.4 and *only* those, we need other Python version as a *compile time* dependency. Nuitka itself is fully compatible with all listed versions, but Scons as an internally used tool is not. For these versions, you *need* a Python2 or Python 3.5 or higher installed as well, but only during the compile time only. That is for use with Scons (which orchestrates the C compilation), which does not support the same Python versions as Nuitka. In addition, on Windows, Python2 cannot be used because ``clcache`` does not work with it, there a Python 3.5 or higher needs to be installed. Nuitka finds these needed Python versions (on Windows via registry) and you shouldn't notice it as long as they are installed. .. admonition:: Moving binaries to other machines The created binaries can be made executable independent of the Python installation, with ``--standalone`` and ``--onefile`` options. .. admonition:: Binary filename suffix The created binaries have an ``.exe`` suffix on Windows. On other platforms they have no suffix for standalone mode, or ``.bin`` suffix, that you are free to remove or change, or specify with the ``-o`` option. The suffix for acceleration mode is added just to be sure that the original script name and the binary name do not ever collide, so we can safely do an overwrite without destroying the original source file. .. admonition:: It **has to** be CPython, Anaconda Python. You need the standard Python implementation, called "CPython", to execute Nuitka, because it is closely tied to implementation details of it. .. admonition:: It **cannot be** from Windows app store It is known that Windows app store Python definitely does not work, it's checked against. And on macOS "pyenv" likely does **not** work. - Operating System: Linux, FreeBSD, NetBSD, macOS X, and Windows (32/64 bits). Others may work as well. The portability is expected to be generally good, but the e.g. Scons usage may have to be adapted. Make sure to match Windows Python and C compiler architecture, or else you will get cryptic error messages. - Architectures: x86, x86_64 (amd64), and arm, likely many more Other architectures are expected to also work, out of the box, as Nuitka is generally not using any hardware specifics. These are just the ones tested and known to be good. Feedback is welcome. Generally, the architectures that Debian supports can be considered good and tested too. .. [#] Support for this C11 is a given with gcc 5.x or higher or any clang version. The MSVC compiler doesn't do it yet. But as a workaround, as the C++03 language standard is very overlapping with C11, it is then used instead where the C compiler is too old. Nuitka used to require a C++ compiler in the past, but it changed. .. [#] Download for free from https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx (the community editions work just fine). The latest version is recommended but not required. On the other hand, there is no need to except pre-Windows 10 support, and they might work for you, but support of these configurations is only available to commercial users. Command Line ============ The recommended way of executing Nuitka is `` -m nuitka`` to be absolutely certain which Python interpreter you are using, so it is easier to match with what Nuitka has. The next best way of executing Nuitka bare that is from a source checkout or archive, with no environment variable changes, most noteworthy, you do not have to mess with ``PYTHONPATH`` at all for Nuitka. You just execute the ``nuitka`` and ``nuitka-run`` scripts directly without any changes to the environment. You may want to add the ``bin`` directory to your ``PATH`` for your convenience, but that step is optional. Moreover, if you want to execute with the right interpreter, in that case, be sure to execute `` bin/nuitka`` and be good. .. admonition:: Pick the right Interpreter If you encounter a ``SyntaxError`` you absolutely most certainly have picked the wrong interpreter for the program you are compiling. Nuitka has a ``--help`` option to output what it can do: .. code:: bash nuitka --help The ``nuitka-run`` command is the same as ``nuitka``, but with a different default. It tries to compile *and* directly execute a Python script: .. code:: bash nuitka-run --help This option that is different is ``--run``, and passing on arguments after the first non-option to the created binary, so it is somewhat more similar to what plain ``python`` will do. Installation ============ For most systems, there will be packages on the `download page `__ of Nuitka. But you can also install it from source code as described above, but also like any other Python program it can be installed via the normal ``python setup.py install`` routine. License ======= Nuitka is licensed under the Apache License, Version 2.0; you may not use it except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ************************************* Tutorial Setup and build on Windows ************************************* This is basic steps if you have nothing installed, of course if you have any of the parts, just skip it. Setup ===== Install Python -------------- - Download and install from https://www.python.org/downloads/windows - Select one of ``Windows x86-64 web-based installer`` (64 bits Python, recommended) or ``x86 executable`` (32 bits Python) installer. - Verify using command ``python --version``. Install Nuitka -------------- - ``python -m pip install nuitka`` - Verify using command ``python -m nuitka --version`` Write some code and test ======================== Create a folder for the Python code ----------------------------------- - mkdir HelloWorld - make a python file named **hello.py** .. code:: python def talk(message): return "Talk " + message def main(): print(talk("Hello World")) if __name__ == "__main__": main() Test your program ----------------- Do as you normally would. Running Nuitka on code that works incorrectly is not easier to debug. .. code:: bash python hello.py ---- Build it using -------------- .. code:: bash python -m nuitka hello.py .. note:: This will prompt you to download a C caching tool (to speed up repeated compilation of generated C code) and a MinGW64 based C compiler unless you have a suitable MSVC installed. Say ``yes`` to both those questions. Run it ------ Execute the ``hello.exe`` created near ``hello.py``. Distribute ---------- To distribute, build with ``--standalone`` option, which will not output a single executable, but a whole folder. Copy the resulting ``hello.dist`` folder to the other machine and run it. You may also try ``--onefile`` which does create a single file, but make sure that the mere standalone is working, before turning to it, as it will make the debugging only harder, e.g. in case of missing data files. *********** Use Cases *********** Use Case 1 - Program compilation with all modules embedded ========================================================== If you want to compile a whole program recursively, and not only the single file that is the main program, do it like this: .. code:: bash python -m nuitka --follow-imports program.py .. note:: There are more fine grained controls than ``--follow-imports`` available. Consider the output of ``nuitka --help``. Including less modules into the compilation, but instead using normal Python for it will make it faster to compile. In case you have a source directory with dynamically loaded files, i.e. one which cannot be found by recursing after normal import statements via the ``PYTHONPATH`` (which would be the recommended way), you can always require that a given directory shall also be included in the executable: .. code:: bash python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py .. note:: If you don't do any dynamic imports, simply setting your ``PYTHONPATH`` at compilation time is what you should do. Use ``--include-plugin-directory`` only if you make ``__import__()`` calls that Nuitka cannot predict, because they e.g. depend on command line parameters. Nuitka also warns about these, and point to the option. .. note:: The resulting filename will be ``program.exe`` on Windows, ``program.bin`` on other platforms. .. note:: The resulting binary still depend on CPython and used C extension modules being installed. If you want to be able to copy it to another machine, use ``--standalone`` and copy the created ``program.dist`` directory and execute the ``program.exe`` (Windows) or ``program`` (other platforms) put inside. Use Case 2 - Extension Module compilation ========================================= If you want to compile a single extension module, all you have to do is this: .. code:: bash python -m nuitka --module some_module.py The resulting file ``some_module.so`` can then be used instead of ``some_module.py``. .. note:: It's left as an exercise to the reader, to find out what happens if both are present. .. note:: The option ``--follow-imports`` and other variants work as well, but the included modules will only become importable *after* you imported the ``some_module`` name. .. note:: The resulting extension module can only be loaded into a CPython of the same version and doesn't include other extension modules. Use Case 3 - Package compilation ================================ If you need to compile a whole package and embed all modules, that is also feasible, use Nuitka like this: .. code:: bash python -m nuitka --module some_package --include-package=some_package .. note:: The inclusion of the package contents needs to be provided manually, otherwise, the package is empty. You can be more specific if you want, and only include part of it. Data files located inside the package will not be embedded by this process, you need to copy them yourself with this approach. Use Case 4 - Program Distribution ================================= For distribution to other systems, there is the standalone mode which produces a folder for which you can specify ``--standalone``. .. code:: bash python -m nuitka --standalone program.py Follow all imports is default in this mode. You can selectively exclude modules by specifically saying ``--nofollow-import-to``, but then an ``ImportError`` will be raised when import of it is attempted at program runtime. For data files to be included, use the option ``--include-data-file==`` where the source is a file system path, but target has to be specified relative. For standalone you can also copy them manually, but this can do extra checks, and for onefile mode, there is no manual copying possible. To copy some or all file in a directory, use the option ``--include-data-file=/etc/*.txt=etc/`` where you get to specify shell patterns for the files, and a subdirectory where to put them, indicated by the trailing slash. To copy a whole folder with all files, you can use ``--include-data-dir=/path/to/images=images`` which will copy all files including a potential subdirectory structure. You cannot filter here, i.e. if you want only a partial copy, remove the files beforehand. For package data, there is a better way, using ``--include-package-data`` which detects data files of packages automatically and copies them over. It even accepts patterns in shell style. With data files, you are largely on your own. Nuitka keeps track of ones that are needed by popular packages, but it might be incomplete. Raise issues if you encounter something in these. When that is working, you can use the onefile mode if you so desire. .. code:: bash python -m nuitka --onefile program.py This will create a single binary, which on Linux will not even unpack itself, but instead loop back mount its contents as a filesystem and use that. .. code:: bash # Create a binary that unpacks into a temporary folder python -m nuitka --onefile program.py .. note:: There are more platform specific options, e.g. related to icons, splash screen, and version information, consider the ``--help`` output for the details of these and check the section "Good Looks". Again, on Windows, for the temporary file directory, by default the user one is used, however this is overridable with a path specification given in ``--windows-onefile-tempdir-spec=%TEMP%\\onefile_%PID%_%TIME%`` which is the default and asserts that the temporary directories created cannot collide. Currently these expanded tokens are available: +-----------+--------------------------------------+-----------------------------------+ | Token | What this Expands to | Example | +===========+======================================+===================================+ | %TEMP% | User temporary file directory | C:\Users\...\AppData\Locals\Temp | +-----------+--------------------------------------+-----------------------------------+ | %PID% | Process ID | 2772 | +-----------+--------------------------------------+-----------------------------------+ | %TIME% | Time in seconds since the epoch. | 1299852985 | +-----------+--------------------------------------+-----------------------------------+ | %PROGRAM% | Full program filename of executable. | C:\SomeWhere\YourOnefile.exe | +-----------+--------------------------------------+-----------------------------------+ .. note:: It is your responsibility to make the path provided unique, on Windows a running program will be locked, and while using a fixed folder name is possible, it can cause locking issues in that case, where the program gets restarted. Usually you need to use ``%TIME%`` or at least ``%PID%`` to make a path unique, and this is mainly intended for use cases, where e.g. you want things to reside in a place you choose or abide your naming conventions. Use Case 5 - Setuptools Wheels ============================== If you have a ``setup.py``, ``setup.cfg`` or ``pyproject.toml`` driven creation of wheels for your software in place, putting Nuitka to use is extremely easy. Lets start with the most common ``setuptools`` approach, you can - having Nuitka installed of course, simply execute the target ``bdist_nuitka`` rather than the ``bdist_wheel``. It takes all the options and allows you to specify some more, that are specific to Nuitka. .. code:: python # For setup.py if not you't use other build systems: setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': True, # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': 'anti-bloat', # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ["*.tests", "*.distutils"], } }, ) # For setup.py with other build systems: # The tuple nature of the arguments is required by the dark nature of # "setuptools" and plugins to it, that insist on full compatibility, # e.g. "setuptools_rust" setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': ("setup.py", True), # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': ("setup.py", 'anti-bloat'), # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ("setup.py", ["*.tests", "*.distutils"]), } }, ) If for some reason, you cannot or do not what to change the target, you can add this to your ``setup.py``. .. code:: python # For setup.py setup( ..., build_with_nuitka=True ) .. note:: To temporarily disable the compilation, you could remove above line, or edit the value to ``False`` by or take its value from an environment variable if you so choose, e.g. ``bool(os.environ.get("USE_NUITKA", "True"))``. This is up to you. Or you could put it in your ``setup.cfg`` .. code:: toml [metadata] build_with_nuitka = True And last, but not least, Nuitka also supports the new ``build`` meta, so when you have a ``pyproject.toml`` already, simple replace or add this value: .. code:: toml [build-system] requires = ["setuptools>=42", "wheel", "nuitka"] build-backend = "nuitka.distutils.Build" ******** Tweaks ******** Icons ===== For good looks, you may specify icons. On Windows, you can provide an icon file, a template executable, or a PNG file. All of these will work and may even be combined: .. code:: bash # These create binaries with icons: python -m nuitka --onefile --windows-icon-from-ico=your-icon.png program.py python -m nuitka --onefile --windows-icon-from-ico=your-icon.ico program.py python -m nuitka --onefile --windows-icon-template-exe=your-icon.ico program.py Splash screen ============= Splash screens are useful when program startup is slow. Onefile startup itself is not slow, but your program may be, and you cannot really know how fast the computer used will be, so it might be a good idea to have them. Luckily with Nuitka, they are easy to add for Windows. For splash screen, you need to specify it as an PNG file, and then make sure to disable the splash screen when your program is ready, e.g. has complete the imports, prepared the window, connected to the database, and wants the splash screen to go away. Here we are using the project syntax to combine the code with the creation, compile this: .. code:: python # nuitka-project: --onefile # nuitka-project: --onefile-windows-splash-screen-image={MAIN_DIRECTORY}/Splash-Screen.png # Whatever this is obviously print("Delaying startup by 10s...") import time time.sleep(10) # Use this code to signal the splash screen removal. if "NUITKA_ONEFILE_PARENT" in os.environ: splash_filename = os.path.join( tempfile.gettempdir(), "onefile_%d_splash_feedback.tmp" % int(os.environ["NUITKA_ONEFILE_PARENT"]), ) if os.path.exists(splash_filename): os.unlink(splash_filename) print("Done... splash should be gone.") ... # Rest of your program goes here. ****************** Typical Problems ****************** Memory issues and compiler bugs =============================== Sometimes the C compilers will crash saying they cannot allocate memory or that some input was truncated, or similar error messages, clearly from it. There are several options you can explore here: Ask Nuitka to use less memory ----------------------------- There is a dedicated option ``--low-memory`` which influces decisions of Nuitka, such that it avoids high usage of memory during compilation at the cost of increased compile time. Avoid 32 bit C compiler/assembler memory limits ----------------------------------------------- Do not use a 32 bits compiler, but a 64 bit one. If you are using Python with 32 bits on Windows, you most definitely ought to use MSVC as the C compiler, and not MinGW64. The MSVC is a cross compiler, and can use more memory than gcc on that platform. If you are not on Windows, that is not an option of course. Also using the 64 bits Python will work. Use LTO compilation or not -------------------------- With ``--lto=yes`` or ``--lto=no`` you can switch the C compilation to only produce bytecode, and not assembler code and machine code directly, but make a whole program optimization at the end. This will change the memory usage pretty dramatically, and if you error is coming from the assembler, using LTO will most definitely avoid that. Switch the C compiler to clang ------------------------------ People have reported that programs that fail to compile with gcc due to its bugs or memory usage work fine with clang on Linux. On Windows, this could still be an option, but it needs to be implemented first for the automatic downloaded gcc, that would contain it. Since MSVC is known to be more memory effective anyway, you should go there, and if you want to use Clang, there is support for the one contained in MSVC. Add a larger swap file to your embedded Linux --------------------------------------------- On systems with not enough RAM, you need to use swap space. Running out of it is possibly a cause, and adding more swap space, or one at all, might solve the issue, but beware that it will make things extremely slow when the compilers swap back and forth, so consider the next tip first or on top of it. Limit the amount of compilation jobs ------------------------------------ With the ``--jobs`` option of Nuitka, it will not start many C compiler instances at once, each competing for the scarce resource of RAM. By picking a value of one, only one C compiler instance will be running, and on a 8 core system, that reduces the amount of memory by factor 8, so that's a natural choice right there. Dynamic ``sys.path`` ==================== If your script modifies ``sys.path`` to e.g. insert directories with source code relative to it, Nuitka will currently not be able to see those. However, if you set the ``PYTHONPATH`` to the resulting value, you will be able to compile it. Missing data files in standalone ================================ If your program fails to file data, it can cause all kinds of different behaviours, e.g. a package might complain it is not the right version, because a ``VERSION`` file check defaulted to unknown. The absence of icon files or help texts, may raise strange errors. Often the error paths for files not being present are even buggy and will reveal programming errors like unbound local variables. Please look carefully at these exceptions keeping in mind that this can be the cause. If you program works without standalone, chances are data files might be cause. Missing DLLs in standalone ========================== Nuitka has plugins that deal with copying DLLs. For NumPy, SciPy, Tkinter, etc. These need special treatment to be able to run on other systems. Manually copying them is not enough and will given strange errors. Sometimes newer version of packages, esp. NumPy can be unsupported. In this case you will have to raise an issue, and use the older one. Dependency creep in standalone ============================== Some packages are a single import, but to Nuitka mean that more than a thousand packages (literally) are to be included. The prime example of Pandas, which does want to plug and use just about everything you can imagine. Multiple frameworks for syntax highlighting everything imaginable take time. Nuitka will have to learn effective caching to deal with this in the future. Right now, you will have to deal with huge compilation times for these. For now, a major weapon in fighting dependency creap should be applied, namely the ``anti-bloat`` plugin, which offers interesting abilities, that can be put to use and block unneeded imports, giving an error for where they occur. Use it e.g. like this ``--enable-plugin=anti-bloat --noinclude-pytest-mode=nofollow --noinclude-setuptools-mode=nofollow`` and check its help output. It can take for each module of your choice, e.g. forcing also that PyQt5 is considered uninstalled for standalone mode. Onefile: Finding files ====================== There is a difference between ``sys.argv[0]`` and ``__file__`` of the main module for onefile more, that is caused by using a bootstrap to a temporary location. The first one will be the original executable path, where as the second one will be the temporary or permanent path the bootstrap executable unpacks to. Data files will be in the later location, your original environment files will be in the former location. Given 2 files, one which you expect to be near your executable, and one which you expect to be inside the onefile binary, access them like this. .. code:: python # This will find a file near your onefile.exe open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt")) # This will find a file inside your onefile.exe open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt")) Windows Programs without console give no errors =============================================== For debugging purposes, remove ``--windows-disable-console`` or use the options ``--windows-force-stdout-spec`` and ``--windows-force-stderr-spec`` with paths as documented for ``--windows-onefile-tempdir-spec`` above. ****** Tips ****** Nuitka Options in the code ========================== There is support for conditional options, and options using pre-defined variables, this is an example: .. code:: python # Compilation mode, support OS specific. # nuitka-project-if: {OS} in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --onefile # nuitka-project-if: {OS} not in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --standalone # The PySide2 plugin covers qt-plugins # nuitka-project: --enable-plugin=pyside2 # nuitka-project: --include-qt-plugins=sensible,qml The comments must be a start of line, and indentation is to be used, to end a conditional block, much like in Python. There are currently no other keywords than the used ones demonstrated above. You can put abitrary Python expressions there, and if you wanted to e.g. access a version information of a package, you could simply use ``__import__("module_name").__version__`` if that would be required to e.g. enable or disable certain Nuitka settings. The only thing Nuitka does that makes this not Python expressions, is expanding ``{variable}`` for a pre-defined set of variables: Table with supported variables: +------------------+--------------------------------+------------------------------------------+ | Variable | What this Expands to | Example | +==================+================================+==========================================+ | {OS} | Name of the OS used | Linux, Windows, Darwin, FreeBSD, OpenBSD | +------------------+--------------------------------+------------------------------------------+ | {Version} | Version of Nuitka | e.g. (0, 6, 16) | +------------------+--------------------------------+------------------------------------------+ | {Commercial} | Version of Nuitka Commercial | e.g. (0, 9, 4) | +------------------+--------------------------------+------------------------------------------+ | {Arch} | Architecture used | x86_64, arm64, etc. | +------------------+--------------------------------+------------------------------------------+ | {MAIN_DIRECTORY} | Directory of the compiled file | some_dir/maybe_relative | +------------------+--------------------------------+------------------------------------------+ | {Flavor} | Variant of Python | e.g. Debian Python, Anaconda Python | +------------------+--------------------------------+------------------------------------------+ Python command line flags ========================= For passing things like ``-O`` or ``-S`` to Python, to your compiled program, there is a command line option name ``--python-flag=`` which makes Nuitka emulate these options. The most important ones are supported, more can certainly be added. Caching compilation results =========================== The C compiler, when invoked with the same input files, will take a long time and much CPU to compile over and over. Make sure you are having ``ccache`` installed and configured when using gcc (even on Windows). It will make repeated compilations much faster, even if things are not yet not perfect, i.e. changes to the program can cause many C files to change, requiring a new compilation instead of using the cached result. On Windows, with gcc Nuitka supports using ``ccache.exe`` which it will offer to download from an official source and it automatically. This is the recommended way of using it on Windows, as other versions can e.g. hang. Nuitka will pick up ``ccache`` if it's in found in system ``PATH``, and it will also be possible to provide if by setting ``NUITKA_CCACHE_BINARY`` to the full path of the binary, this is for use in CI systems. For the MSVC compilers and ClangCL setups, using the ``clcache`` is automatic and included in Nuitka. Control where Caches live ========================= The storage for cache results of all kinds, downloads, cached compilation results from C and Nuitka, is done in a platform dependent directory as determined by the ``appdirs`` package. However, you can override it with setting the environment variable ``NUITKA_CACHE_DIR`` to a base directory. This is for use in environments where the home directory is not persisted, but other paths are. Runners ======= Avoid running the ``nuitka`` binary, doing ``python -m nuitka`` will make a 100% sure you are using what you think you are. Using the wrong Python will make it give you ``SyntaxError`` for good code or ``ImportError`` for installed modules. That is happening, when you run Nuitka with Python2 on Python3 code and vice versa. By explicitly calling the same Python interpreter binary, you avoid that issue entirely. Fastest C Compilers =================== The fastest binaries of ``pystone.exe`` on Windows with 64 bits Python proved to be significantly faster with MinGW64, roughly 20% better score. So it is recommended for use over MSVC. Using ``clang-cl.exe`` of Clang7 was faster than MSVC, but still significantly slower than MinGW64, and it will be harder to use, so it is not recommended. On Linux for ``pystone.bin`` the binary produced by ``clang6`` was faster than ``gcc-6.3``, but not by a significant margin. Since gcc is more often already installed, that is recommended to use for now. Differences in C compilation times have not yet been examined. Unexpected Slowdowns ==================== Using the Python DLL, like standard CPython does can lead to unexpected slowdowns, e.g. in uncompiled code that works with Unicode strings. This is because calling to the DLL rather than residing in the DLL causes overhead, and this even happens to the DLL with itself, being slower, than a Python all contained in one binary. So if feasible, aim at static linking, which is currently only possible with Anaconda Python on non-Windows, Debian Python2, self compiled Pythons (do not activate ``--enable-shared``, not needed), and installs created with ``pyenv``. .. note:: On Anaconda, you may need to execute ``conda install -c conda-forge libpython-static`` Standalone executables and dependencies ======================================= The process of making standalone executables for Windows traditionally involves using an external dependency walker in order to copy necessary libraries along with the compiled executables to the distribution folder. There is plenty of ways to find that something is missing. Do not manually copy things into the folder, esp. not DLLs, as that's not going to work. Instead make bug reports to get these handled by Nuitka properly. Windows errors with resources ============================= On Windows, the Windows Defender tool and the Windows Indexing Service both scan the freshly created binaries, while Nuitka wants to work with it, e.g. adding more resources, and then preventing operations randomly due to holding locks. Make sure to exclude your compilation stage from these services. Windows standalone program redistribuation ========================================== Whether compiling with MingW or MSVC, the standalone programs have external dependencies to Visual C Runtime libraries. Nuitka tries to ship those dependent DLLs by copying them from your system. Beginning with Microsoft Windows 10, Microsoft ships ``ucrt.dll`` (Universal C Runtime libraries) which rehook calls to ``api-ms-crt-*.dll``. With earlier Windows platforms (and wine/ReactOS), you should consider installing Visual C Runtime libraries before executing a Nuitka standalone compiled program. Depending on the used C compiler, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | Visual C version | Redist Year | CPython | +==================+=============+===============================+ | 14.2 | 2019 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ | 14.1 | 2017 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 14.0 | 2015 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 10.0 | 2010 | 3.3, 3.4 | +------------------+-------------+-------------------------------+ | 9.0 | 2008 | 2.6, 2.7 | +------------------+-------------+-------------------------------+ When using MingGW64, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | MingGW64 version | Redist Year | CPython | +==================+=============+===============================+ | 8.1.0 | 2015 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ Once the corresponding runtime libraries are installed on the target system, you may remove all ``api-ms-crt-*.dll`` files from your Nuitka compiled dist folder. Detecting Nuitka at run time ============================ It doesn't set ``sys.frozen`` unlike other tools. For Nuitka, we have the module attribute ``__compiled__`` to test if a specific module was compiled. ************* Performance ************* This chapter gives an overview, of what to currently expect in terms of performance from Nuitka. It's a work in progress and is updated as we go. The current focus for performance measurements is Python 2.7, but 3.x is going to follow later. pystone results =============== The results are the top value from this kind of output, running pystone 1000 times and taking the minimal value. The idea is that the fastest run is most meanigful, and eliminates usage spikes. .. code:: bash echo "Uncompiled Python2" for i in {1..100}; do BENCH=1 python2 tests/benchmarks/pystone.py ; done | sort -n -r | head -n 1 python2 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone.py echo "Compiled Python2" for i in {1..100}; do BENCH=1 ./pystone.bin ; done | sort -n -r | head -n 1 echo "Uncompiled Python3" for i in {1..100}; do BENCH=1 python3 tests/benchmarks/pystone3.py ; done | sort -n -r | head -n 1 python3 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone3.py echo "Compiled Python3" for i in {1..100}; do BENCH=1 ./pystone3.bin ; done | sort -n -r | head -n 1 +-------------------+-------------------+----------------------+---------------------+ | Python | Uncompiled | Compiled LTO | Compiled PGO | +===================+===================+======================+=====================+ | Debian Python 2.7 | 137497.87 (1.000) | 460995.20 (3.353) | 503681.91 (3.663) | +-------------------+-------------------+----------------------+---------------------+ | Nuitka Python 2.7 | 144074.78 (1.048) | 479271.51 (3.486) | 511247.44 (3.718) | +-------------------+-------------------+----------------------+---------------------+ ****************** Where to go next ****************** Remember, this project is not completed yet. Although the CPython test suite works near perfect, there is still more work needed, esp. to make it do more optimization. Try it out. Follow me on Twitter ==================== Nuitka announcements and interesting stuff is pointed to on the Twitter account, but obviously with not too many details. `@KayHayen `_. Report issues or bugs ===================== Should you encounter any issues, bugs, or ideas, please visit the `Nuitka bug tracker `__ and report them. Best practices for reporting bugs: - Please always include the following information in your report, for the underlying Python version. You can easily copy&paste this into your report. .. code:: bash python -m nuitka --version - Try to make your example minimal. That is, try to remove code that does not contribute to the issue as much as possible. Ideally come up with a small reproducing program that illustrates the issue, using ``print`` with different results when that programs runs compiled or native. - If the problem occurs spuriously (i.e. not each time), try to set the environment variable ``PYTHONHASHSEED`` to ``0``, disabling hash randomization. If that makes the problem go away, try increasing in steps of 1 to a hash seed value that makes it happen every time, include it in your report. - Do not include the created code in your report. Given proper input, it's redundant, and it's not likely that I will look at it without the ability to change the Python or Nuitka source and re-run it. - Do not send screenshots of text, that is bad and lazy. Instead, capture text outputs from the console. Word of Warning =============== Consider using this software with caution. Even though many tests are applied before releases, things are potentially breaking. Your feedback and patches to Nuitka are very welcome. ************* Join Nuitka ************* You are more than welcome to join Nuitka development and help to complete the project in all minor and major ways. The development of Nuitka occurs in git. We currently have these 3 branches: - ``main`` This branch contains the stable release to which only hotfixes for bugs will be done. It is supposed to work at all times and is supported. - ``develop`` This branch contains the ongoing development. It may at times contain little regressions, but also new features. On this branch, the integration work is done, whereas new features might be developed on feature branches. - ``factory`` This branch contains unfinished and incomplete work. It is very frequently subject to ``git rebase`` and the public staging ground, where my work for develop branch lives first. It is intended for testing only and recommended to base any of your own development on. When updating it, you very often will get merge conflicts. Simply resolve those by doing ``git reset --hard origin/factory`` and switch to the latest version. .. note:: The `Developer Manual `__ explains the coding rules, branching model used, with feature branches and hotfix releases, the Nuitka design and much more. Consider reading it to become a contributor. This document is intended for Nuitka users. *********** Donations *********** Should you feel that you cannot help Nuitka directly, but still want to support, please consider `making a donation `__ and help this way. *************************** Unsupported functionality *************************** The ``co_code`` attribute of code objects ========================================= The code objects are empty for native compiled functions. There is no bytecode with Nuitka's compiled function objects, so there is no way to provide it. PDB === There is no tracing of compiled functions to attach a debugger to. ************** Optimization ************** Constant Folding ================ The most important form of optimization is the constant folding. This is when an operation can be fully predicted at compile time. Currently, Nuitka does these for some built-ins (but not all yet, somebody to look at this more closely will be very welcome!), and it does it e.g. for binary/unary operations and comparisons. Constants currently recognized: .. code:: python 5 + 6 # binary operations not 7 # unary operations 5 < 6 # comparisons range(3) # built-ins Literals are the one obvious source of constants, but also most likely other optimization steps like constant propagation or function inlining will be. So this one should not be underestimated and a very important step of successful optimizations. Every option to produce a constant may impact the generated code quality a lot. .. admonition:: Status The folding of constants is considered implemented, but it might be incomplete in that not all possible cases are caught. Please report it as a bug when you find an operation in Nuitka that has only constants as input and is not folded. Constant Propagation ==================== At the core of optimizations, there is an attempt to determine the values of variables at run time and predictions of assignments. It determines if their inputs are constants or of similar values. An expression, e.g. a module variable access, an expensive operation, may be constant across the module of the function scope and then there needs to be none or no repeated module variable look-up. Consider e.g. the module attribute ``__name__`` which likely is only ever read, so its value could be predicted to a constant string known at compile time. This can then be used as input to the constant folding. .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() .. admonition:: Status From modules attributes, only ``__name__`` is currently actually optimized. Also possible would be at least ``__doc__``. In the future, this may improve as SSA is expanded to module variables. Built-in Name Lookups ===================== Also, built-in exception name references are optimized if they are used as a module level read-only variables: .. code:: python try: something() except ValueError: # The ValueError is a slow global name lookup normally. pass .. admonition:: Status This works for all built-in names. When an assignment is done to such a name, or it's even local, then, of course, it is not done. Built-in Call Prediction ======================== For built-in calls like ``type``, ``len``, or ``range`` it is often possible to predict the result at compile time, esp. for constant inputs the resulting value often can be precomputed by Nuitka. It can simply determine the result or the raised exception and replace the built-in call with that value, allowing for more constant folding or code path reduction. .. code:: python type("string") # predictable result, builtin type str. len([1, 2]) # predictable result range(3, 9, 2) # predictable result range(3, 9, 0) # predictable exception, range raises due to 0. .. admonition:: Status The built-in call prediction is considered implemented. We can simply during compile time emulate the call and use its result or raised exception. But we may not cover all the built-ins there are yet. Sometimes the result of a built-in should not be predicted when the result is big. A ``range()`` call e.g. may give too big values to include the result in the binary. Then it is not done. .. code:: python range(100000) # We do not want this one to be expanded .. admonition:: Status This is considered mostly implemented. Please file bugs for built-ins that are pre-computed, but should not be computed by Nuitka at compile time with specific values. Conditional Statement Prediction ================================ For conditional statements, some branches may not ever be taken, because of the conditions being possible to predict. In these cases, the branch not taken and the condition check is removed. This can typically predict code like this: .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() or .. code:: python if False: # Your deactivated code might be here use_something_not_use_by_program() It will also benefit from constant propagations, or enable them because once some branches have been removed, other things may become more predictable, so this can trigger other optimization to become possible. Every branch removed makes optimization more likely. With some code branches removed, access patterns may be more friendly. Imagine e.g. that a function is only called in a removed branch. It may be possible to remove it entirely, and that may have other consequences too. .. admonition:: Status This is considered implemented, but for the maximum benefit, more constants need to be determined at compile time. Exception Propagation ===================== For exceptions that are determined at compile time, there is an expression that will simply do raise the exception. These can be propagated upwards, collecting potentially "side effects", i.e. parts of expressions that were executed before it occurred, and still have to be executed. Consider the following code: .. code:: python print(side_effect_having() + (1 / 0)) print(something_else()) The ``(1 / 0)`` can be predicted to raise a ``ZeroDivisionError`` exception, which will be propagated through the ``+`` operation. That part is just Constant Propagation as normal. The call ``side_effect_having()`` will have to be retained though, but the ``print`` does not and can be turned into an explicit raise. The statement sequence can then be aborted and as such the ``something_else`` call needs no code generation or consideration anymore. To that end, Nuitka works with a special node that raises an exception and is wrapped with a so-called "side_effects" expression, but yet can be used in the code as an expression having a value. .. admonition:: Status The propagation of exceptions is mostly implemented but needs handling in every kind of operations, and not all of them might do it already. As work progresses or examples arise, the coverage will be extended. Feel free to generate bug reports with non-working examples. Exception Scope Reduction ========================= Consider the following code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) The ``try`` block is bigger than it needs to be. The statement ``b = 8`` cannot cause a ``ValueError`` to be raised. As such it can be moved to outside the try without any risk. .. code:: python b = 8 try: print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) .. admonition:: Status This is considered done. For every kind of operation, we trace if it may raise an exception. We do however *not* track properly yet, what can do a ``ValueError`` and what cannot. Exception Block Inlining ======================== With the exception propagation, it then becomes possible to transform this code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed!") except ValueError as e: print(e) .. code:: python try: raise ValueError("range() step argument must not be zero") except ValueError as e: print(e) Which then can be lowered in complexity by avoiding the raise and catch of the exception, making it: .. code:: python e = ValueError("range() step argument must not be zero") print(e) .. admonition:: Status This is not implemented yet. Empty Branch Removal ==================== For loops and conditional statements that contain only code without effect, it should be possible to remove the whole construct: .. code:: python for i in range(1000): pass The loop could be removed, at maximum, it should be considered an assignment of variable ``i`` to ``999`` and no more. .. admonition:: Status This is not implemented yet, as it requires us to track iterators, and their side effects, as well as loop values, and exit conditions. Too much yet, but we will get there. Another example: .. code:: python if side_effect_free: pass The condition check should be removed in this case, as its evaluation is not needed. It may be difficult to predict that ``side_effect_free`` has no side effects, but many times this might be possible. .. admonition:: Status This is considered implemented. The conditional statement nature is removed if both branches are empty, only the condition is evaluated and checked for truth (in cases that could raise an exception). Unpacking Prediction ==================== When the length of the right-hand side of an assignment to a sequence can be predicted, the unpacking can be replaced with multiple assignments. .. code:: python a, b, c = 1, side_effect_free(), 3 .. code:: python a = 1 b = side_effect_free() c = 3 This is of course only really safe if the left-hand side cannot raise an exception while building the assignment targets. We do this now, but only for constants, because we currently have no ability to predict if an expression can raise an exception or not. .. admonition:: Status Not implemented yet. Will need us to see through the unpacking of what is an iteration over a tuple, we created ourselves. We are not there yet, but we will get there. Built-in Type Inference ======================= When a construct like ``in xrange()`` or ``in range()`` is used, it is possible to know what the iteration does and represent that so that iterator users can use that instead. I consider that: .. code:: python for i in xrange(1000): something(i) could translate ``xrange(1000)`` into an object of a special class that does the integer looping more efficiently. In case ``i`` is only assigned from there, this could be a nice case for a dedicated class. .. admonition:: Status Future work, not even started. Quicker Function Calls ====================== Functions are structured so that their parameter parsing and ``tp_call`` interface is separate from the actual function code. This way the call can be optimized away. One problem is that the evaluation order can differ. .. code:: python def f(a, b, c): return a, b, c f(c=get1(), b=get2(), a=get3()) This will have to evaluate first ``get1()``, then ``get2()`` and only then ``get3()`` and then make the function call with these values. Therefore it will be necessary to have a staging of the parameters before making the actual call, to avoid a re-ordering of the calls to ``get1()``, ``get2()``, and ``get3()``. .. admonition:: Status Not even started. A re-formulation that avoids the dictionary to call the function, and instead uses temporary variables appears to be relatively straight forward once we do that kind of parameter analysis. Lowering of iterated Container Types ==================================== In some cases, accesses to ``list`` constants can become ``tuple`` constants instead. Consider that: .. code:: python for x in [a, b, c]: something(x) Can be optimized into this: .. code:: python for x in (a, b, c): something(x) This allows for simpler, faster code to be generated, and fewer checks needed, because e.g. the ``tuple`` is clearly immutable, whereas the ``list`` needs a check to assert that. This is also possible for sets. .. admonition:: Status Implemented, even works for non-constants. Needs other optimization to become generally useful, and will itself help other optimization to become possible. This allows us to e.g. only treat iteration over tuples, and not care about sets. In theory, something similar is also possible for ``dict``. For the later, it will be non-trivial though to maintain the order of execution without temporary values introduced. The same thing is done for pure constants of these types, they change to ``tuple`` values when iterated. ************************* Updates for this Manual ************************* This document is written in REST. That is an ASCII format which is readable to human, but easily used to generate PDF or HTML documents. You will find the current version at: https://nuitka.net/doc/user-manual.html And the current PDF under: https://nuitka.net/doc/README.pdf Keywords: compiler,python,nuitka Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Topic :: Software Development :: Compilers Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: System :: Software Distribution Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: C Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: POSIX :: BSD :: FreeBSD Classifier: Operating System :: POSIX :: BSD :: NetBSD Classifier: Operating System :: POSIX :: BSD :: OpenBSD Classifier: Operating System :: Microsoft :: Windows Classifier: License :: OSI Approved :: Apache Software License Description-Content-Type: text/x-rst Nuitka-0.6.19.1/README.rst0000600000372100037210000015564214166627112021773 0ustar nuitka-buildslavenuitka-buildslave00000000000000#################### Nuitka User Manual #################### ********** Overview ********** This document is the recommended first read if you are interested in using Nuitka, understand its use cases, check what you can expect, license, requirements, credits, etc. Nuitka is **the** Python compiler. It is written in Python. It is a seamless replacement or extension to the Python interpreter and compiles **every** construct that CPython 2.6, 2.7, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 have, when itself run with that Python version. It then executes uncompiled code and compiled code together in an extremely compatible manner. You can use all Python library modules and all extension modules freely. Nuitka translates the Python modules into a C level program that then uses ``libpython`` and static C files of its own to execute in the same way as CPython does. All optimization is aimed at avoiding overhead, where it's unnecessary. None is aimed at removing compatibility, although slight improvements will occasionally be done, where not every bug of standard Python is emulated, e.g. more complete error messages are given, but there is a full compatibility mode to disable even that. ******* Usage ******* Requirements ============ - C Compiler: You need a compiler with support for C11 or alternatively for C++03 [#]_ Currently this means, you need to use one of these compilers: - The MinGW64 C11 compiler on Windows, must be based on gcc 11.2 or higher. It will be *automatically* downloaded if no usable C compiler is found, which is the recommended way of installing it, as Nuitka will also upgrade it for you. - Visual Studio 2022 or higher on Windows [#]_, older versions will work but only supported for commercial users. Configure to use the English language pack for best results (Nuitka filters away garbage outputs, but only for English language). It will be used by default if installed. - On all other platforms, the ``gcc`` compiler of at least version 5.1, and below that the ``g++`` compiler of at least version 4.4 as an alternative. - The ``clang`` compiler on macOS X and most FreeBSD architectures. - On Windows the ``clang-cl`` compiler on Windows can be used if provided by the Visual Studio installer. - Python: Version 2.6, 2.7 or 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 .. admonition:: For Python 3.3/3.4 and *only* those, we need other Python version as a *compile time* dependency. Nuitka itself is fully compatible with all listed versions, but Scons as an internally used tool is not. For these versions, you *need* a Python2 or Python 3.5 or higher installed as well, but only during the compile time only. That is for use with Scons (which orchestrates the C compilation), which does not support the same Python versions as Nuitka. In addition, on Windows, Python2 cannot be used because ``clcache`` does not work with it, there a Python 3.5 or higher needs to be installed. Nuitka finds these needed Python versions (on Windows via registry) and you shouldn't notice it as long as they are installed. .. admonition:: Moving binaries to other machines The created binaries can be made executable independent of the Python installation, with ``--standalone`` and ``--onefile`` options. .. admonition:: Binary filename suffix The created binaries have an ``.exe`` suffix on Windows. On other platforms they have no suffix for standalone mode, or ``.bin`` suffix, that you are free to remove or change, or specify with the ``-o`` option. The suffix for acceleration mode is added just to be sure that the original script name and the binary name do not ever collide, so we can safely do an overwrite without destroying the original source file. .. admonition:: It **has to** be CPython, Anaconda Python. You need the standard Python implementation, called "CPython", to execute Nuitka, because it is closely tied to implementation details of it. .. admonition:: It **cannot be** from Windows app store It is known that Windows app store Python definitely does not work, it's checked against. And on macOS "pyenv" likely does **not** work. - Operating System: Linux, FreeBSD, NetBSD, macOS X, and Windows (32/64 bits). Others may work as well. The portability is expected to be generally good, but the e.g. Scons usage may have to be adapted. Make sure to match Windows Python and C compiler architecture, or else you will get cryptic error messages. - Architectures: x86, x86_64 (amd64), and arm, likely many more Other architectures are expected to also work, out of the box, as Nuitka is generally not using any hardware specifics. These are just the ones tested and known to be good. Feedback is welcome. Generally, the architectures that Debian supports can be considered good and tested too. .. [#] Support for this C11 is a given with gcc 5.x or higher or any clang version. The MSVC compiler doesn't do it yet. But as a workaround, as the C++03 language standard is very overlapping with C11, it is then used instead where the C compiler is too old. Nuitka used to require a C++ compiler in the past, but it changed. .. [#] Download for free from https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx (the community editions work just fine). The latest version is recommended but not required. On the other hand, there is no need to except pre-Windows 10 support, and they might work for you, but support of these configurations is only available to commercial users. Command Line ============ The recommended way of executing Nuitka is `` -m nuitka`` to be absolutely certain which Python interpreter you are using, so it is easier to match with what Nuitka has. The next best way of executing Nuitka bare that is from a source checkout or archive, with no environment variable changes, most noteworthy, you do not have to mess with ``PYTHONPATH`` at all for Nuitka. You just execute the ``nuitka`` and ``nuitka-run`` scripts directly without any changes to the environment. You may want to add the ``bin`` directory to your ``PATH`` for your convenience, but that step is optional. Moreover, if you want to execute with the right interpreter, in that case, be sure to execute `` bin/nuitka`` and be good. .. admonition:: Pick the right Interpreter If you encounter a ``SyntaxError`` you absolutely most certainly have picked the wrong interpreter for the program you are compiling. Nuitka has a ``--help`` option to output what it can do: .. code:: bash nuitka --help The ``nuitka-run`` command is the same as ``nuitka``, but with a different default. It tries to compile *and* directly execute a Python script: .. code:: bash nuitka-run --help This option that is different is ``--run``, and passing on arguments after the first non-option to the created binary, so it is somewhat more similar to what plain ``python`` will do. Installation ============ For most systems, there will be packages on the `download page `__ of Nuitka. But you can also install it from source code as described above, but also like any other Python program it can be installed via the normal ``python setup.py install`` routine. License ======= Nuitka is licensed under the Apache License, Version 2.0; you may not use it except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ************************************* Tutorial Setup and build on Windows ************************************* This is basic steps if you have nothing installed, of course if you have any of the parts, just skip it. Setup ===== Install Python -------------- - Download and install from https://www.python.org/downloads/windows - Select one of ``Windows x86-64 web-based installer`` (64 bits Python, recommended) or ``x86 executable`` (32 bits Python) installer. - Verify using command ``python --version``. Install Nuitka -------------- - ``python -m pip install nuitka`` - Verify using command ``python -m nuitka --version`` Write some code and test ======================== Create a folder for the Python code ----------------------------------- - mkdir HelloWorld - make a python file named **hello.py** .. code:: python def talk(message): return "Talk " + message def main(): print(talk("Hello World")) if __name__ == "__main__": main() Test your program ----------------- Do as you normally would. Running Nuitka on code that works incorrectly is not easier to debug. .. code:: bash python hello.py ---- Build it using -------------- .. code:: bash python -m nuitka hello.py .. note:: This will prompt you to download a C caching tool (to speed up repeated compilation of generated C code) and a MinGW64 based C compiler unless you have a suitable MSVC installed. Say ``yes`` to both those questions. Run it ------ Execute the ``hello.exe`` created near ``hello.py``. Distribute ---------- To distribute, build with ``--standalone`` option, which will not output a single executable, but a whole folder. Copy the resulting ``hello.dist`` folder to the other machine and run it. You may also try ``--onefile`` which does create a single file, but make sure that the mere standalone is working, before turning to it, as it will make the debugging only harder, e.g. in case of missing data files. *********** Use Cases *********** Use Case 1 - Program compilation with all modules embedded ========================================================== If you want to compile a whole program recursively, and not only the single file that is the main program, do it like this: .. code:: bash python -m nuitka --follow-imports program.py .. note:: There are more fine grained controls than ``--follow-imports`` available. Consider the output of ``nuitka --help``. Including less modules into the compilation, but instead using normal Python for it will make it faster to compile. In case you have a source directory with dynamically loaded files, i.e. one which cannot be found by recursing after normal import statements via the ``PYTHONPATH`` (which would be the recommended way), you can always require that a given directory shall also be included in the executable: .. code:: bash python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py .. note:: If you don't do any dynamic imports, simply setting your ``PYTHONPATH`` at compilation time is what you should do. Use ``--include-plugin-directory`` only if you make ``__import__()`` calls that Nuitka cannot predict, because they e.g. depend on command line parameters. Nuitka also warns about these, and point to the option. .. note:: The resulting filename will be ``program.exe`` on Windows, ``program.bin`` on other platforms. .. note:: The resulting binary still depend on CPython and used C extension modules being installed. If you want to be able to copy it to another machine, use ``--standalone`` and copy the created ``program.dist`` directory and execute the ``program.exe`` (Windows) or ``program`` (other platforms) put inside. Use Case 2 - Extension Module compilation ========================================= If you want to compile a single extension module, all you have to do is this: .. code:: bash python -m nuitka --module some_module.py The resulting file ``some_module.so`` can then be used instead of ``some_module.py``. .. note:: It's left as an exercise to the reader, to find out what happens if both are present. .. note:: The option ``--follow-imports`` and other variants work as well, but the included modules will only become importable *after* you imported the ``some_module`` name. .. note:: The resulting extension module can only be loaded into a CPython of the same version and doesn't include other extension modules. Use Case 3 - Package compilation ================================ If you need to compile a whole package and embed all modules, that is also feasible, use Nuitka like this: .. code:: bash python -m nuitka --module some_package --include-package=some_package .. note:: The inclusion of the package contents needs to be provided manually, otherwise, the package is empty. You can be more specific if you want, and only include part of it. Data files located inside the package will not be embedded by this process, you need to copy them yourself with this approach. Use Case 4 - Program Distribution ================================= For distribution to other systems, there is the standalone mode which produces a folder for which you can specify ``--standalone``. .. code:: bash python -m nuitka --standalone program.py Follow all imports is default in this mode. You can selectively exclude modules by specifically saying ``--nofollow-import-to``, but then an ``ImportError`` will be raised when import of it is attempted at program runtime. For data files to be included, use the option ``--include-data-file==`` where the source is a file system path, but target has to be specified relative. For standalone you can also copy them manually, but this can do extra checks, and for onefile mode, there is no manual copying possible. To copy some or all file in a directory, use the option ``--include-data-file=/etc/*.txt=etc/`` where you get to specify shell patterns for the files, and a subdirectory where to put them, indicated by the trailing slash. To copy a whole folder with all files, you can use ``--include-data-dir=/path/to/images=images`` which will copy all files including a potential subdirectory structure. You cannot filter here, i.e. if you want only a partial copy, remove the files beforehand. For package data, there is a better way, using ``--include-package-data`` which detects data files of packages automatically and copies them over. It even accepts patterns in shell style. With data files, you are largely on your own. Nuitka keeps track of ones that are needed by popular packages, but it might be incomplete. Raise issues if you encounter something in these. When that is working, you can use the onefile mode if you so desire. .. code:: bash python -m nuitka --onefile program.py This will create a single binary, which on Linux will not even unpack itself, but instead loop back mount its contents as a filesystem and use that. .. code:: bash # Create a binary that unpacks into a temporary folder python -m nuitka --onefile program.py .. note:: There are more platform specific options, e.g. related to icons, splash screen, and version information, consider the ``--help`` output for the details of these and check the section "Good Looks". Again, on Windows, for the temporary file directory, by default the user one is used, however this is overridable with a path specification given in ``--windows-onefile-tempdir-spec=%TEMP%\\onefile_%PID%_%TIME%`` which is the default and asserts that the temporary directories created cannot collide. Currently these expanded tokens are available: +-----------+--------------------------------------+-----------------------------------+ | Token | What this Expands to | Example | +===========+======================================+===================================+ | %TEMP% | User temporary file directory | C:\Users\...\AppData\Locals\Temp | +-----------+--------------------------------------+-----------------------------------+ | %PID% | Process ID | 2772 | +-----------+--------------------------------------+-----------------------------------+ | %TIME% | Time in seconds since the epoch. | 1299852985 | +-----------+--------------------------------------+-----------------------------------+ | %PROGRAM% | Full program filename of executable. | C:\SomeWhere\YourOnefile.exe | +-----------+--------------------------------------+-----------------------------------+ .. note:: It is your responsibility to make the path provided unique, on Windows a running program will be locked, and while using a fixed folder name is possible, it can cause locking issues in that case, where the program gets restarted. Usually you need to use ``%TIME%`` or at least ``%PID%`` to make a path unique, and this is mainly intended for use cases, where e.g. you want things to reside in a place you choose or abide your naming conventions. Use Case 5 - Setuptools Wheels ============================== If you have a ``setup.py``, ``setup.cfg`` or ``pyproject.toml`` driven creation of wheels for your software in place, putting Nuitka to use is extremely easy. Lets start with the most common ``setuptools`` approach, you can - having Nuitka installed of course, simply execute the target ``bdist_nuitka`` rather than the ``bdist_wheel``. It takes all the options and allows you to specify some more, that are specific to Nuitka. .. code:: python # For setup.py if not you't use other build systems: setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': True, # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': 'anti-bloat', # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ["*.tests", "*.distutils"], } }, ) # For setup.py with other build systems: # The tuple nature of the arguments is required by the dark nature of # "setuptools" and plugins to it, that insist on full compatibility, # e.g. "setuptools_rust" setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': ("setup.py", True), # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': ("setup.py", 'anti-bloat'), # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ("setup.py", ["*.tests", "*.distutils"]), } }, ) If for some reason, you cannot or do not what to change the target, you can add this to your ``setup.py``. .. code:: python # For setup.py setup( ..., build_with_nuitka=True ) .. note:: To temporarily disable the compilation, you could remove above line, or edit the value to ``False`` by or take its value from an environment variable if you so choose, e.g. ``bool(os.environ.get("USE_NUITKA", "True"))``. This is up to you. Or you could put it in your ``setup.cfg`` .. code:: toml [metadata] build_with_nuitka = True And last, but not least, Nuitka also supports the new ``build`` meta, so when you have a ``pyproject.toml`` already, simple replace or add this value: .. code:: toml [build-system] requires = ["setuptools>=42", "wheel", "nuitka"] build-backend = "nuitka.distutils.Build" ******** Tweaks ******** Icons ===== For good looks, you may specify icons. On Windows, you can provide an icon file, a template executable, or a PNG file. All of these will work and may even be combined: .. code:: bash # These create binaries with icons: python -m nuitka --onefile --windows-icon-from-ico=your-icon.png program.py python -m nuitka --onefile --windows-icon-from-ico=your-icon.ico program.py python -m nuitka --onefile --windows-icon-template-exe=your-icon.ico program.py Splash screen ============= Splash screens are useful when program startup is slow. Onefile startup itself is not slow, but your program may be, and you cannot really know how fast the computer used will be, so it might be a good idea to have them. Luckily with Nuitka, they are easy to add for Windows. For splash screen, you need to specify it as an PNG file, and then make sure to disable the splash screen when your program is ready, e.g. has complete the imports, prepared the window, connected to the database, and wants the splash screen to go away. Here we are using the project syntax to combine the code with the creation, compile this: .. code:: python # nuitka-project: --onefile # nuitka-project: --onefile-windows-splash-screen-image={MAIN_DIRECTORY}/Splash-Screen.png # Whatever this is obviously print("Delaying startup by 10s...") import time time.sleep(10) # Use this code to signal the splash screen removal. if "NUITKA_ONEFILE_PARENT" in os.environ: splash_filename = os.path.join( tempfile.gettempdir(), "onefile_%d_splash_feedback.tmp" % int(os.environ["NUITKA_ONEFILE_PARENT"]), ) if os.path.exists(splash_filename): os.unlink(splash_filename) print("Done... splash should be gone.") ... # Rest of your program goes here. ****************** Typical Problems ****************** Memory issues and compiler bugs =============================== Sometimes the C compilers will crash saying they cannot allocate memory or that some input was truncated, or similar error messages, clearly from it. There are several options you can explore here: Ask Nuitka to use less memory ----------------------------- There is a dedicated option ``--low-memory`` which influces decisions of Nuitka, such that it avoids high usage of memory during compilation at the cost of increased compile time. Avoid 32 bit C compiler/assembler memory limits ----------------------------------------------- Do not use a 32 bits compiler, but a 64 bit one. If you are using Python with 32 bits on Windows, you most definitely ought to use MSVC as the C compiler, and not MinGW64. The MSVC is a cross compiler, and can use more memory than gcc on that platform. If you are not on Windows, that is not an option of course. Also using the 64 bits Python will work. Use LTO compilation or not -------------------------- With ``--lto=yes`` or ``--lto=no`` you can switch the C compilation to only produce bytecode, and not assembler code and machine code directly, but make a whole program optimization at the end. This will change the memory usage pretty dramatically, and if you error is coming from the assembler, using LTO will most definitely avoid that. Switch the C compiler to clang ------------------------------ People have reported that programs that fail to compile with gcc due to its bugs or memory usage work fine with clang on Linux. On Windows, this could still be an option, but it needs to be implemented first for the automatic downloaded gcc, that would contain it. Since MSVC is known to be more memory effective anyway, you should go there, and if you want to use Clang, there is support for the one contained in MSVC. Add a larger swap file to your embedded Linux --------------------------------------------- On systems with not enough RAM, you need to use swap space. Running out of it is possibly a cause, and adding more swap space, or one at all, might solve the issue, but beware that it will make things extremely slow when the compilers swap back and forth, so consider the next tip first or on top of it. Limit the amount of compilation jobs ------------------------------------ With the ``--jobs`` option of Nuitka, it will not start many C compiler instances at once, each competing for the scarce resource of RAM. By picking a value of one, only one C compiler instance will be running, and on a 8 core system, that reduces the amount of memory by factor 8, so that's a natural choice right there. Dynamic ``sys.path`` ==================== If your script modifies ``sys.path`` to e.g. insert directories with source code relative to it, Nuitka will currently not be able to see those. However, if you set the ``PYTHONPATH`` to the resulting value, you will be able to compile it. Missing data files in standalone ================================ If your program fails to file data, it can cause all kinds of different behaviours, e.g. a package might complain it is not the right version, because a ``VERSION`` file check defaulted to unknown. The absence of icon files or help texts, may raise strange errors. Often the error paths for files not being present are even buggy and will reveal programming errors like unbound local variables. Please look carefully at these exceptions keeping in mind that this can be the cause. If you program works without standalone, chances are data files might be cause. Missing DLLs in standalone ========================== Nuitka has plugins that deal with copying DLLs. For NumPy, SciPy, Tkinter, etc. These need special treatment to be able to run on other systems. Manually copying them is not enough and will given strange errors. Sometimes newer version of packages, esp. NumPy can be unsupported. In this case you will have to raise an issue, and use the older one. Dependency creep in standalone ============================== Some packages are a single import, but to Nuitka mean that more than a thousand packages (literally) are to be included. The prime example of Pandas, which does want to plug and use just about everything you can imagine. Multiple frameworks for syntax highlighting everything imaginable take time. Nuitka will have to learn effective caching to deal with this in the future. Right now, you will have to deal with huge compilation times for these. For now, a major weapon in fighting dependency creap should be applied, namely the ``anti-bloat`` plugin, which offers interesting abilities, that can be put to use and block unneeded imports, giving an error for where they occur. Use it e.g. like this ``--enable-plugin=anti-bloat --noinclude-pytest-mode=nofollow --noinclude-setuptools-mode=nofollow`` and check its help output. It can take for each module of your choice, e.g. forcing also that PyQt5 is considered uninstalled for standalone mode. Onefile: Finding files ====================== There is a difference between ``sys.argv[0]`` and ``__file__`` of the main module for onefile more, that is caused by using a bootstrap to a temporary location. The first one will be the original executable path, where as the second one will be the temporary or permanent path the bootstrap executable unpacks to. Data files will be in the later location, your original environment files will be in the former location. Given 2 files, one which you expect to be near your executable, and one which you expect to be inside the onefile binary, access them like this. .. code:: python # This will find a file near your onefile.exe open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt")) # This will find a file inside your onefile.exe open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt")) Windows Programs without console give no errors =============================================== For debugging purposes, remove ``--windows-disable-console`` or use the options ``--windows-force-stdout-spec`` and ``--windows-force-stderr-spec`` with paths as documented for ``--windows-onefile-tempdir-spec`` above. ****** Tips ****** Nuitka Options in the code ========================== There is support for conditional options, and options using pre-defined variables, this is an example: .. code:: python # Compilation mode, support OS specific. # nuitka-project-if: {OS} in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --onefile # nuitka-project-if: {OS} not in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --standalone # The PySide2 plugin covers qt-plugins # nuitka-project: --enable-plugin=pyside2 # nuitka-project: --include-qt-plugins=sensible,qml The comments must be a start of line, and indentation is to be used, to end a conditional block, much like in Python. There are currently no other keywords than the used ones demonstrated above. You can put abitrary Python expressions there, and if you wanted to e.g. access a version information of a package, you could simply use ``__import__("module_name").__version__`` if that would be required to e.g. enable or disable certain Nuitka settings. The only thing Nuitka does that makes this not Python expressions, is expanding ``{variable}`` for a pre-defined set of variables: Table with supported variables: +------------------+--------------------------------+------------------------------------------+ | Variable | What this Expands to | Example | +==================+================================+==========================================+ | {OS} | Name of the OS used | Linux, Windows, Darwin, FreeBSD, OpenBSD | +------------------+--------------------------------+------------------------------------------+ | {Version} | Version of Nuitka | e.g. (0, 6, 16) | +------------------+--------------------------------+------------------------------------------+ | {Commercial} | Version of Nuitka Commercial | e.g. (0, 9, 4) | +------------------+--------------------------------+------------------------------------------+ | {Arch} | Architecture used | x86_64, arm64, etc. | +------------------+--------------------------------+------------------------------------------+ | {MAIN_DIRECTORY} | Directory of the compiled file | some_dir/maybe_relative | +------------------+--------------------------------+------------------------------------------+ | {Flavor} | Variant of Python | e.g. Debian Python, Anaconda Python | +------------------+--------------------------------+------------------------------------------+ Python command line flags ========================= For passing things like ``-O`` or ``-S`` to Python, to your compiled program, there is a command line option name ``--python-flag=`` which makes Nuitka emulate these options. The most important ones are supported, more can certainly be added. Caching compilation results =========================== The C compiler, when invoked with the same input files, will take a long time and much CPU to compile over and over. Make sure you are having ``ccache`` installed and configured when using gcc (even on Windows). It will make repeated compilations much faster, even if things are not yet not perfect, i.e. changes to the program can cause many C files to change, requiring a new compilation instead of using the cached result. On Windows, with gcc Nuitka supports using ``ccache.exe`` which it will offer to download from an official source and it automatically. This is the recommended way of using it on Windows, as other versions can e.g. hang. Nuitka will pick up ``ccache`` if it's in found in system ``PATH``, and it will also be possible to provide if by setting ``NUITKA_CCACHE_BINARY`` to the full path of the binary, this is for use in CI systems. For the MSVC compilers and ClangCL setups, using the ``clcache`` is automatic and included in Nuitka. Control where Caches live ========================= The storage for cache results of all kinds, downloads, cached compilation results from C and Nuitka, is done in a platform dependent directory as determined by the ``appdirs`` package. However, you can override it with setting the environment variable ``NUITKA_CACHE_DIR`` to a base directory. This is for use in environments where the home directory is not persisted, but other paths are. Runners ======= Avoid running the ``nuitka`` binary, doing ``python -m nuitka`` will make a 100% sure you are using what you think you are. Using the wrong Python will make it give you ``SyntaxError`` for good code or ``ImportError`` for installed modules. That is happening, when you run Nuitka with Python2 on Python3 code and vice versa. By explicitly calling the same Python interpreter binary, you avoid that issue entirely. Fastest C Compilers =================== The fastest binaries of ``pystone.exe`` on Windows with 64 bits Python proved to be significantly faster with MinGW64, roughly 20% better score. So it is recommended for use over MSVC. Using ``clang-cl.exe`` of Clang7 was faster than MSVC, but still significantly slower than MinGW64, and it will be harder to use, so it is not recommended. On Linux for ``pystone.bin`` the binary produced by ``clang6`` was faster than ``gcc-6.3``, but not by a significant margin. Since gcc is more often already installed, that is recommended to use for now. Differences in C compilation times have not yet been examined. Unexpected Slowdowns ==================== Using the Python DLL, like standard CPython does can lead to unexpected slowdowns, e.g. in uncompiled code that works with Unicode strings. This is because calling to the DLL rather than residing in the DLL causes overhead, and this even happens to the DLL with itself, being slower, than a Python all contained in one binary. So if feasible, aim at static linking, which is currently only possible with Anaconda Python on non-Windows, Debian Python2, self compiled Pythons (do not activate ``--enable-shared``, not needed), and installs created with ``pyenv``. .. note:: On Anaconda, you may need to execute ``conda install -c conda-forge libpython-static`` Standalone executables and dependencies ======================================= The process of making standalone executables for Windows traditionally involves using an external dependency walker in order to copy necessary libraries along with the compiled executables to the distribution folder. There is plenty of ways to find that something is missing. Do not manually copy things into the folder, esp. not DLLs, as that's not going to work. Instead make bug reports to get these handled by Nuitka properly. Windows errors with resources ============================= On Windows, the Windows Defender tool and the Windows Indexing Service both scan the freshly created binaries, while Nuitka wants to work with it, e.g. adding more resources, and then preventing operations randomly due to holding locks. Make sure to exclude your compilation stage from these services. Windows standalone program redistribuation ========================================== Whether compiling with MingW or MSVC, the standalone programs have external dependencies to Visual C Runtime libraries. Nuitka tries to ship those dependent DLLs by copying them from your system. Beginning with Microsoft Windows 10, Microsoft ships ``ucrt.dll`` (Universal C Runtime libraries) which rehook calls to ``api-ms-crt-*.dll``. With earlier Windows platforms (and wine/ReactOS), you should consider installing Visual C Runtime libraries before executing a Nuitka standalone compiled program. Depending on the used C compiler, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | Visual C version | Redist Year | CPython | +==================+=============+===============================+ | 14.2 | 2019 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ | 14.1 | 2017 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 14.0 | 2015 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 10.0 | 2010 | 3.3, 3.4 | +------------------+-------------+-------------------------------+ | 9.0 | 2008 | 2.6, 2.7 | +------------------+-------------+-------------------------------+ When using MingGW64, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | MingGW64 version | Redist Year | CPython | +==================+=============+===============================+ | 8.1.0 | 2015 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ Once the corresponding runtime libraries are installed on the target system, you may remove all ``api-ms-crt-*.dll`` files from your Nuitka compiled dist folder. Detecting Nuitka at run time ============================ It doesn't set ``sys.frozen`` unlike other tools. For Nuitka, we have the module attribute ``__compiled__`` to test if a specific module was compiled. ************* Performance ************* This chapter gives an overview, of what to currently expect in terms of performance from Nuitka. It's a work in progress and is updated as we go. The current focus for performance measurements is Python 2.7, but 3.x is going to follow later. pystone results =============== The results are the top value from this kind of output, running pystone 1000 times and taking the minimal value. The idea is that the fastest run is most meanigful, and eliminates usage spikes. .. code:: bash echo "Uncompiled Python2" for i in {1..100}; do BENCH=1 python2 tests/benchmarks/pystone.py ; done | sort -n -r | head -n 1 python2 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone.py echo "Compiled Python2" for i in {1..100}; do BENCH=1 ./pystone.bin ; done | sort -n -r | head -n 1 echo "Uncompiled Python3" for i in {1..100}; do BENCH=1 python3 tests/benchmarks/pystone3.py ; done | sort -n -r | head -n 1 python3 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone3.py echo "Compiled Python3" for i in {1..100}; do BENCH=1 ./pystone3.bin ; done | sort -n -r | head -n 1 +-------------------+-------------------+----------------------+---------------------+ | Python | Uncompiled | Compiled LTO | Compiled PGO | +===================+===================+======================+=====================+ | Debian Python 2.7 | 137497.87 (1.000) | 460995.20 (3.353) | 503681.91 (3.663) | +-------------------+-------------------+----------------------+---------------------+ | Nuitka Python 2.7 | 144074.78 (1.048) | 479271.51 (3.486) | 511247.44 (3.718) | +-------------------+-------------------+----------------------+---------------------+ ****************** Where to go next ****************** Remember, this project is not completed yet. Although the CPython test suite works near perfect, there is still more work needed, esp. to make it do more optimization. Try it out. Follow me on Twitter ==================== Nuitka announcements and interesting stuff is pointed to on the Twitter account, but obviously with not too many details. `@KayHayen `_. Report issues or bugs ===================== Should you encounter any issues, bugs, or ideas, please visit the `Nuitka bug tracker `__ and report them. Best practices for reporting bugs: - Please always include the following information in your report, for the underlying Python version. You can easily copy&paste this into your report. .. code:: bash python -m nuitka --version - Try to make your example minimal. That is, try to remove code that does not contribute to the issue as much as possible. Ideally come up with a small reproducing program that illustrates the issue, using ``print`` with different results when that programs runs compiled or native. - If the problem occurs spuriously (i.e. not each time), try to set the environment variable ``PYTHONHASHSEED`` to ``0``, disabling hash randomization. If that makes the problem go away, try increasing in steps of 1 to a hash seed value that makes it happen every time, include it in your report. - Do not include the created code in your report. Given proper input, it's redundant, and it's not likely that I will look at it without the ability to change the Python or Nuitka source and re-run it. - Do not send screenshots of text, that is bad and lazy. Instead, capture text outputs from the console. Word of Warning =============== Consider using this software with caution. Even though many tests are applied before releases, things are potentially breaking. Your feedback and patches to Nuitka are very welcome. ************* Join Nuitka ************* You are more than welcome to join Nuitka development and help to complete the project in all minor and major ways. The development of Nuitka occurs in git. We currently have these 3 branches: - ``main`` This branch contains the stable release to which only hotfixes for bugs will be done. It is supposed to work at all times and is supported. - ``develop`` This branch contains the ongoing development. It may at times contain little regressions, but also new features. On this branch, the integration work is done, whereas new features might be developed on feature branches. - ``factory`` This branch contains unfinished and incomplete work. It is very frequently subject to ``git rebase`` and the public staging ground, where my work for develop branch lives first. It is intended for testing only and recommended to base any of your own development on. When updating it, you very often will get merge conflicts. Simply resolve those by doing ``git reset --hard origin/factory`` and switch to the latest version. .. note:: The `Developer Manual `__ explains the coding rules, branching model used, with feature branches and hotfix releases, the Nuitka design and much more. Consider reading it to become a contributor. This document is intended for Nuitka users. *********** Donations *********** Should you feel that you cannot help Nuitka directly, but still want to support, please consider `making a donation `__ and help this way. *************************** Unsupported functionality *************************** The ``co_code`` attribute of code objects ========================================= The code objects are empty for native compiled functions. There is no bytecode with Nuitka's compiled function objects, so there is no way to provide it. PDB === There is no tracing of compiled functions to attach a debugger to. ************** Optimization ************** Constant Folding ================ The most important form of optimization is the constant folding. This is when an operation can be fully predicted at compile time. Currently, Nuitka does these for some built-ins (but not all yet, somebody to look at this more closely will be very welcome!), and it does it e.g. for binary/unary operations and comparisons. Constants currently recognized: .. code:: python 5 + 6 # binary operations not 7 # unary operations 5 < 6 # comparisons range(3) # built-ins Literals are the one obvious source of constants, but also most likely other optimization steps like constant propagation or function inlining will be. So this one should not be underestimated and a very important step of successful optimizations. Every option to produce a constant may impact the generated code quality a lot. .. admonition:: Status The folding of constants is considered implemented, but it might be incomplete in that not all possible cases are caught. Please report it as a bug when you find an operation in Nuitka that has only constants as input and is not folded. Constant Propagation ==================== At the core of optimizations, there is an attempt to determine the values of variables at run time and predictions of assignments. It determines if their inputs are constants or of similar values. An expression, e.g. a module variable access, an expensive operation, may be constant across the module of the function scope and then there needs to be none or no repeated module variable look-up. Consider e.g. the module attribute ``__name__`` which likely is only ever read, so its value could be predicted to a constant string known at compile time. This can then be used as input to the constant folding. .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() .. admonition:: Status From modules attributes, only ``__name__`` is currently actually optimized. Also possible would be at least ``__doc__``. In the future, this may improve as SSA is expanded to module variables. Built-in Name Lookups ===================== Also, built-in exception name references are optimized if they are used as a module level read-only variables: .. code:: python try: something() except ValueError: # The ValueError is a slow global name lookup normally. pass .. admonition:: Status This works for all built-in names. When an assignment is done to such a name, or it's even local, then, of course, it is not done. Built-in Call Prediction ======================== For built-in calls like ``type``, ``len``, or ``range`` it is often possible to predict the result at compile time, esp. for constant inputs the resulting value often can be precomputed by Nuitka. It can simply determine the result or the raised exception and replace the built-in call with that value, allowing for more constant folding or code path reduction. .. code:: python type("string") # predictable result, builtin type str. len([1, 2]) # predictable result range(3, 9, 2) # predictable result range(3, 9, 0) # predictable exception, range raises due to 0. .. admonition:: Status The built-in call prediction is considered implemented. We can simply during compile time emulate the call and use its result or raised exception. But we may not cover all the built-ins there are yet. Sometimes the result of a built-in should not be predicted when the result is big. A ``range()`` call e.g. may give too big values to include the result in the binary. Then it is not done. .. code:: python range(100000) # We do not want this one to be expanded .. admonition:: Status This is considered mostly implemented. Please file bugs for built-ins that are pre-computed, but should not be computed by Nuitka at compile time with specific values. Conditional Statement Prediction ================================ For conditional statements, some branches may not ever be taken, because of the conditions being possible to predict. In these cases, the branch not taken and the condition check is removed. This can typically predict code like this: .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() or .. code:: python if False: # Your deactivated code might be here use_something_not_use_by_program() It will also benefit from constant propagations, or enable them because once some branches have been removed, other things may become more predictable, so this can trigger other optimization to become possible. Every branch removed makes optimization more likely. With some code branches removed, access patterns may be more friendly. Imagine e.g. that a function is only called in a removed branch. It may be possible to remove it entirely, and that may have other consequences too. .. admonition:: Status This is considered implemented, but for the maximum benefit, more constants need to be determined at compile time. Exception Propagation ===================== For exceptions that are determined at compile time, there is an expression that will simply do raise the exception. These can be propagated upwards, collecting potentially "side effects", i.e. parts of expressions that were executed before it occurred, and still have to be executed. Consider the following code: .. code:: python print(side_effect_having() + (1 / 0)) print(something_else()) The ``(1 / 0)`` can be predicted to raise a ``ZeroDivisionError`` exception, which will be propagated through the ``+`` operation. That part is just Constant Propagation as normal. The call ``side_effect_having()`` will have to be retained though, but the ``print`` does not and can be turned into an explicit raise. The statement sequence can then be aborted and as such the ``something_else`` call needs no code generation or consideration anymore. To that end, Nuitka works with a special node that raises an exception and is wrapped with a so-called "side_effects" expression, but yet can be used in the code as an expression having a value. .. admonition:: Status The propagation of exceptions is mostly implemented but needs handling in every kind of operations, and not all of them might do it already. As work progresses or examples arise, the coverage will be extended. Feel free to generate bug reports with non-working examples. Exception Scope Reduction ========================= Consider the following code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) The ``try`` block is bigger than it needs to be. The statement ``b = 8`` cannot cause a ``ValueError`` to be raised. As such it can be moved to outside the try without any risk. .. code:: python b = 8 try: print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) .. admonition:: Status This is considered done. For every kind of operation, we trace if it may raise an exception. We do however *not* track properly yet, what can do a ``ValueError`` and what cannot. Exception Block Inlining ======================== With the exception propagation, it then becomes possible to transform this code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed!") except ValueError as e: print(e) .. code:: python try: raise ValueError("range() step argument must not be zero") except ValueError as e: print(e) Which then can be lowered in complexity by avoiding the raise and catch of the exception, making it: .. code:: python e = ValueError("range() step argument must not be zero") print(e) .. admonition:: Status This is not implemented yet. Empty Branch Removal ==================== For loops and conditional statements that contain only code without effect, it should be possible to remove the whole construct: .. code:: python for i in range(1000): pass The loop could be removed, at maximum, it should be considered an assignment of variable ``i`` to ``999`` and no more. .. admonition:: Status This is not implemented yet, as it requires us to track iterators, and their side effects, as well as loop values, and exit conditions. Too much yet, but we will get there. Another example: .. code:: python if side_effect_free: pass The condition check should be removed in this case, as its evaluation is not needed. It may be difficult to predict that ``side_effect_free`` has no side effects, but many times this might be possible. .. admonition:: Status This is considered implemented. The conditional statement nature is removed if both branches are empty, only the condition is evaluated and checked for truth (in cases that could raise an exception). Unpacking Prediction ==================== When the length of the right-hand side of an assignment to a sequence can be predicted, the unpacking can be replaced with multiple assignments. .. code:: python a, b, c = 1, side_effect_free(), 3 .. code:: python a = 1 b = side_effect_free() c = 3 This is of course only really safe if the left-hand side cannot raise an exception while building the assignment targets. We do this now, but only for constants, because we currently have no ability to predict if an expression can raise an exception or not. .. admonition:: Status Not implemented yet. Will need us to see through the unpacking of what is an iteration over a tuple, we created ourselves. We are not there yet, but we will get there. Built-in Type Inference ======================= When a construct like ``in xrange()`` or ``in range()`` is used, it is possible to know what the iteration does and represent that so that iterator users can use that instead. I consider that: .. code:: python for i in xrange(1000): something(i) could translate ``xrange(1000)`` into an object of a special class that does the integer looping more efficiently. In case ``i`` is only assigned from there, this could be a nice case for a dedicated class. .. admonition:: Status Future work, not even started. Quicker Function Calls ====================== Functions are structured so that their parameter parsing and ``tp_call`` interface is separate from the actual function code. This way the call can be optimized away. One problem is that the evaluation order can differ. .. code:: python def f(a, b, c): return a, b, c f(c=get1(), b=get2(), a=get3()) This will have to evaluate first ``get1()``, then ``get2()`` and only then ``get3()`` and then make the function call with these values. Therefore it will be necessary to have a staging of the parameters before making the actual call, to avoid a re-ordering of the calls to ``get1()``, ``get2()``, and ``get3()``. .. admonition:: Status Not even started. A re-formulation that avoids the dictionary to call the function, and instead uses temporary variables appears to be relatively straight forward once we do that kind of parameter analysis. Lowering of iterated Container Types ==================================== In some cases, accesses to ``list`` constants can become ``tuple`` constants instead. Consider that: .. code:: python for x in [a, b, c]: something(x) Can be optimized into this: .. code:: python for x in (a, b, c): something(x) This allows for simpler, faster code to be generated, and fewer checks needed, because e.g. the ``tuple`` is clearly immutable, whereas the ``list`` needs a check to assert that. This is also possible for sets. .. admonition:: Status Implemented, even works for non-constants. Needs other optimization to become generally useful, and will itself help other optimization to become possible. This allows us to e.g. only treat iteration over tuples, and not care about sets. In theory, something similar is also possible for ``dict``. For the later, it will be non-trivial though to maintain the order of execution without temporary values introduced. The same thing is done for pure constants of these types, they change to ``tuple`` values when iterated. ************************* Updates for this Manual ************************* This document is written in REST. That is an ASCII format which is readable to human, but easily used to generate PDF or HTML documents. You will find the current version at: https://nuitka.net/doc/user-manual.html And the current PDF under: https://nuitka.net/doc/README.pdf Nuitka-0.6.19.1/Nuitka.egg-info/0000700000372100037210000000000014167275622023220 5ustar nuitka-buildslavenuitka-buildslave00000000000000Nuitka-0.6.19.1/Nuitka.egg-info/top_level.txt0000600000372100037210000000000714167275622025751 0ustar nuitka-buildslavenuitka-buildslave00000000000000nuitka Nuitka-0.6.19.1/Nuitka.egg-info/dependency_links.txt0000600000372100037210000000000114167275622027270 0ustar nuitka-buildslavenuitka-buildslave00000000000000 Nuitka-0.6.19.1/Nuitka.egg-info/not-zip-safe0000600000372100037210000000000114167275622025450 0ustar nuitka-buildslavenuitka-buildslave00000000000000 Nuitka-0.6.19.1/Nuitka.egg-info/entry_points.txt0000600000372100037210000000061214167275622026517 0ustar nuitka-buildslavenuitka-buildslave00000000000000[console_scripts] nuitka2 = nuitka.__main__:main nuitka2-run = nuitka.__main__:main [distutils.commands] bdist_nuitka = nuitka.distutils.DistutilCommands:bdist_nuitka build_nuitka = nuitka.distutils.DistutilCommands:build install_nuitka = nuitka.distutils.DistutilCommands:install [distutils.setup_keywords] build_with_nuitka = nuitka.distutils.DistutilCommands:setupNuitkaDistutilsCommands Nuitka-0.6.19.1/Nuitka.egg-info/SOURCES.txt0000600000372100037210000021045714167275622025117 0ustar nuitka-buildslavenuitka-buildslave00000000000000Changelog.pdf Changelog.rst Developer_Manual.pdf Developer_Manual.rst LICENSE.txt MANIFEST.in README.pdf README.rst setup.py Nuitka.egg-info/PKG-INFO Nuitka.egg-info/SOURCES.txt Nuitka.egg-info/dependency_links.txt Nuitka.egg-info/entry_points.txt Nuitka.egg-info/not-zip-safe Nuitka.egg-info/top_level.txt bin/autoformat-nuitka-source bin/check-nuitka-with-pylint bin/compare_with_cpython bin/compare_with_xml bin/measure-construct-performance bin/nuitka bin/nuitka-run doc/nuitka2-run.1 doc/nuitka2.1 doc/nuitka3-run.1 doc/nuitka3.1 doc/Logo/Nuitka-Logo-Horizontal.svg doc/Logo/Nuitka-Logo-Symbol.svg doc/Logo/Nuitka-Logo-Vertical.svg doc/images/Nuitka-Logo-Horizontal.png doc/images/Nuitka-Logo-Symbol.png doc/images/Nuitka-Logo-Vertical.png lib/hints.py misc/nuitka-run.bat misc/nuitka.bat nuitka/Builtins.py nuitka/Bytecodes.py nuitka/Caching.py nuitka/Constants.py nuitka/Errors.py nuitka/MainControl.py nuitka/ModuleRegistry.py nuitka/OptionParsing.py nuitka/Options.py nuitka/OutputDirectories.py nuitka/PostProcessing.py nuitka/Progress.py nuitka/PythonFlavors.py nuitka/PythonOperators.py nuitka/PythonVersions.py nuitka/Reports.py nuitka/SourceCodeReferences.py nuitka/Tracing.py nuitka/TreeXML.py nuitka/Variables.py nuitka/Version.py nuitka/__init__.py nuitka/__main__.py nuitka/__past__.py nuitka/build/Backend.scons nuitka/build/DataComposerInterface.py nuitka/build/Onefile.scons nuitka/build/SconsCaching.py nuitka/build/SconsCompilerSettings.py nuitka/build/SconsHacks.py nuitka/build/SconsInterface.py nuitka/build/SconsProgress.py nuitka/build/SconsSpawn.py nuitka/build/SconsUtils.py nuitka/build/__init__.py nuitka/build/include/nuitka/allocator.h nuitka/build/include/nuitka/builtins.h nuitka/build/include/nuitka/calling.h nuitka/build/include/nuitka/compiled_asyncgen.h nuitka/build/include/nuitka/compiled_cell.h nuitka/build/include/nuitka/compiled_coroutine.h nuitka/build/include/nuitka/compiled_frame.h nuitka/build/include/nuitka/compiled_function.h nuitka/build/include/nuitka/compiled_generator.h nuitka/build/include/nuitka/compiled_method.h nuitka/build/include/nuitka/constants_blob.h nuitka/build/include/nuitka/exceptions.h nuitka/build/include/nuitka/freelists.h nuitka/build/include/nuitka/hedley.h nuitka/build/include/nuitka/helpers.h nuitka/build/include/nuitka/importing.h nuitka/build/include/nuitka/incbin.h nuitka/build/include/nuitka/prelude.h nuitka/build/include/nuitka/python_pgo.h nuitka/build/include/nuitka/safe_string_ops.h nuitka/build/include/nuitka/threading.h nuitka/build/include/nuitka/tracing.h nuitka/build/include/nuitka/unfreezing.h nuitka/build/include/nuitka/helper/attributes.h nuitka/build/include/nuitka/helper/boolean.h nuitka/build/include/nuitka/helper/bytearrays.h nuitka/build/include/nuitka/helper/calling2.h nuitka/build/include/nuitka/helper/comparisons_eq.h nuitka/build/include/nuitka/helper/comparisons_ge.h nuitka/build/include/nuitka/helper/comparisons_gt.h nuitka/build/include/nuitka/helper/comparisons_le.h nuitka/build/include/nuitka/helper/comparisons_lt.h nuitka/build/include/nuitka/helper/comparisons_ne.h nuitka/build/include/nuitka/helper/complex.h nuitka/build/include/nuitka/helper/dictionaries.h nuitka/build/include/nuitka/helper/import_hard.h nuitka/build/include/nuitka/helper/ints.h nuitka/build/include/nuitka/helper/iterators.h nuitka/build/include/nuitka/helper/lists.h nuitka/build/include/nuitka/helper/mappings.h nuitka/build/include/nuitka/helper/operations.h nuitka/build/include/nuitka/helper/operations_binary_add.h nuitka/build/include/nuitka/helper/operations_binary_bitand.h nuitka/build/include/nuitka/helper/operations_binary_bitor.h nuitka/build/include/nuitka/helper/operations_binary_bitxor.h nuitka/build/include/nuitka/helper/operations_binary_divmod.h nuitka/build/include/nuitka/helper/operations_binary_floordiv.h nuitka/build/include/nuitka/helper/operations_binary_lshift.h nuitka/build/include/nuitka/helper/operations_binary_matmult.h nuitka/build/include/nuitka/helper/operations_binary_mod.h nuitka/build/include/nuitka/helper/operations_binary_mult.h nuitka/build/include/nuitka/helper/operations_binary_olddiv.h nuitka/build/include/nuitka/helper/operations_binary_pow.h nuitka/build/include/nuitka/helper/operations_binary_rshift.h nuitka/build/include/nuitka/helper/operations_binary_sub.h nuitka/build/include/nuitka/helper/operations_binary_truediv.h nuitka/build/include/nuitka/helper/operations_builtin_types.h nuitka/build/include/nuitka/helper/operations_inplace_add.h nuitka/build/include/nuitka/helper/operations_inplace_bitand.h nuitka/build/include/nuitka/helper/operations_inplace_bitor.h nuitka/build/include/nuitka/helper/operations_inplace_bitxor.h nuitka/build/include/nuitka/helper/operations_inplace_floordiv.h nuitka/build/include/nuitka/helper/operations_inplace_lshift.h nuitka/build/include/nuitka/helper/operations_inplace_matmult.h nuitka/build/include/nuitka/helper/operations_inplace_mod.h nuitka/build/include/nuitka/helper/operations_inplace_mult.h nuitka/build/include/nuitka/helper/operations_inplace_olddiv.h nuitka/build/include/nuitka/helper/operations_inplace_pow.h nuitka/build/include/nuitka/helper/operations_inplace_rshift.h nuitka/build/include/nuitka/helper/operations_inplace_sub.h nuitka/build/include/nuitka/helper/operations_inplace_truediv.h nuitka/build/include/nuitka/helper/printing.h nuitka/build/include/nuitka/helper/raising.h nuitka/build/include/nuitka/helper/rangeobjects.h nuitka/build/include/nuitka/helper/richcomparisons.h nuitka/build/include/nuitka/helper/sequences.h nuitka/build/include/nuitka/helper/sets.h nuitka/build/include/nuitka/helper/slices.h nuitka/build/include/nuitka/helper/strings.h nuitka/build/include/nuitka/helper/subscripts.h nuitka/build/include/nuitka/helper/tuples.h nuitka/build/inline_copy/appdirs/appdirs.py nuitka/build/inline_copy/atomicwrites/atomicwrites.py nuitka/build/inline_copy/bin/scons.py nuitka/build/inline_copy/clcache/clcache/__init__.py nuitka/build/inline_copy/clcache/clcache/caching.py nuitka/build/inline_copy/colorama/colorama/__init__.py nuitka/build/inline_copy/colorama/colorama/ansi.py nuitka/build/inline_copy/colorama/colorama/ansitowin32.py nuitka/build/inline_copy/colorama/colorama/initialise.py nuitka/build/inline_copy/colorama/colorama/win32.py nuitka/build/inline_copy/colorama/colorama/winterm.py nuitka/build/inline_copy/glob2/glob2/__init__.py nuitka/build/inline_copy/glob2/glob2/compat.py nuitka/build/inline_copy/glob2/glob2/fnmatch.py nuitka/build/inline_copy/glob2/glob2/impl.py nuitka/build/inline_copy/jinja2/jinja2/__init__.py nuitka/build/inline_copy/jinja2/jinja2/_compat.py nuitka/build/inline_copy/jinja2/jinja2/_identifier.py nuitka/build/inline_copy/jinja2/jinja2/asyncfilters.py nuitka/build/inline_copy/jinja2/jinja2/asyncsupport.py nuitka/build/inline_copy/jinja2/jinja2/bccache.py nuitka/build/inline_copy/jinja2/jinja2/compiler.py nuitka/build/inline_copy/jinja2/jinja2/constants.py nuitka/build/inline_copy/jinja2/jinja2/debug.py nuitka/build/inline_copy/jinja2/jinja2/defaults.py nuitka/build/inline_copy/jinja2/jinja2/environment.py nuitka/build/inline_copy/jinja2/jinja2/exceptions.py nuitka/build/inline_copy/jinja2/jinja2/ext.py nuitka/build/inline_copy/jinja2/jinja2/filters.py nuitka/build/inline_copy/jinja2/jinja2/idtracking.py nuitka/build/inline_copy/jinja2/jinja2/lexer.py nuitka/build/inline_copy/jinja2/jinja2/loaders.py nuitka/build/inline_copy/jinja2/jinja2/meta.py nuitka/build/inline_copy/jinja2/jinja2/nativetypes.py nuitka/build/inline_copy/jinja2/jinja2/nodes.py nuitka/build/inline_copy/jinja2/jinja2/optimizer.py nuitka/build/inline_copy/jinja2/jinja2/parser.py nuitka/build/inline_copy/jinja2/jinja2/runtime.py nuitka/build/inline_copy/jinja2/jinja2/sandbox.py nuitka/build/inline_copy/jinja2/jinja2/tests.py nuitka/build/inline_copy/jinja2/jinja2/utils.py nuitka/build/inline_copy/jinja2/jinja2/visitor.py nuitka/build/inline_copy/jinja2_35/jinja2/__init__.py nuitka/build/inline_copy/jinja2_35/jinja2/_compat.py nuitka/build/inline_copy/jinja2_35/jinja2/_identifier.py nuitka/build/inline_copy/jinja2_35/jinja2/bccache.py nuitka/build/inline_copy/jinja2_35/jinja2/compiler.py nuitka/build/inline_copy/jinja2_35/jinja2/constants.py nuitka/build/inline_copy/jinja2_35/jinja2/debug.py nuitka/build/inline_copy/jinja2_35/jinja2/defaults.py nuitka/build/inline_copy/jinja2_35/jinja2/environment.py nuitka/build/inline_copy/jinja2_35/jinja2/exceptions.py nuitka/build/inline_copy/jinja2_35/jinja2/ext.py nuitka/build/inline_copy/jinja2_35/jinja2/filters.py nuitka/build/inline_copy/jinja2_35/jinja2/idtracking.py nuitka/build/inline_copy/jinja2_35/jinja2/lexer.py nuitka/build/inline_copy/jinja2_35/jinja2/loaders.py nuitka/build/inline_copy/jinja2_35/jinja2/meta.py nuitka/build/inline_copy/jinja2_35/jinja2/nativetypes.py nuitka/build/inline_copy/jinja2_35/jinja2/nodes.py nuitka/build/inline_copy/jinja2_35/jinja2/optimizer.py nuitka/build/inline_copy/jinja2_35/jinja2/parser.py nuitka/build/inline_copy/jinja2_35/jinja2/runtime.py nuitka/build/inline_copy/jinja2_35/jinja2/sandbox.py nuitka/build/inline_copy/jinja2_35/jinja2/tests.py nuitka/build/inline_copy/jinja2_35/jinja2/utils.py nuitka/build/inline_copy/jinja2_35/jinja2/visitor.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Action.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Builder.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/CacheDir.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Conftest.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Debug.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Defaults.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Environment.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Errors.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Executor.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Job.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Memoize.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/PathList.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/SConf.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/SConsign.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Sig.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Subst.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Taskmaster.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Util.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Warnings.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/cpp.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/dblite.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/exitfuncs.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Node/Alias.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Node/FS.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Node/Python.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Node/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/BoolOption.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/EnumOption.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/ListOption.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/PackageOption.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/PathOption.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Options/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/aix.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/cygwin.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/darwin.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/hpux.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/irix.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/os2.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/posix.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/sunos.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Platform/win32.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Scanner/C.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Scanner/Dir.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Scanner/Prog.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Scanner/RC.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Scanner/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Script/Interactive.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Script/Main.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Script/SConsOptions.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Script/SConscript.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Script/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/386asm.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/BitKeeper.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/CVS.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/GettextCommon.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/Perforce.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/PharLapCommon.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/RCS.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/SCCS.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/Subversion.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/aixc++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/aixcc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/aixf77.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/aixlink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/applelink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/ar.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/as.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/bcc32.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/c++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/cc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/cyglink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/default.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/dmd.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/filesystem.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/g++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/g77.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gas.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gcc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gdc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gettext.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gfortran.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/gnulink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/hpc++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/hpcc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/hplink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/icc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/icl.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/ilink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/ilink32.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/install.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/intelc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/lex.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/link.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/linkloc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/m4.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/masm.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mingw.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/msgfmt.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/msginit.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/msgmerge.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mslib.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mslink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mssdk.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/msvc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/msvs.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mwcc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/mwld.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/nasm.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/rmic.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/rpcgen.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sgiar.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sgic++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sgicc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sgilink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sunar.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sunc++.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/suncc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/sunlink.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/tar.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/textfile.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/tlib.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/wix.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/xgettext.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/zip.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/arch.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/common.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/netframework.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/sdk.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/vc.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/MSCommon/vs.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Tool/docbook/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/BoolVariable.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/EnumVariable.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/ListVariable.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/PackageVariable.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/PathVariable.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Variables/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/__init__.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_builtins.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_collections.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_dbm.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_hashlib.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_io.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_sets.py nuitka/build/inline_copy/lib/scons-2.3.2/SCons/compat/_scons_subprocess.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Action.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Builder.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/CacheDir.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Conftest.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Debug.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Defaults.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Environment.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Errors.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Executor.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Job.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Memoize.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/PathList.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/SConf.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/SConsign.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Subst.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Taskmaster.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Util.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Warnings.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/cpp.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/dblite.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/exitfuncs.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Node/Alias.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Node/FS.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Node/Python.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Node/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/aix.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/cygwin.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/darwin.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/hpux.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/irix.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/mingw.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/os2.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/posix.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/sunos.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/virtualenv.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Platform/win32.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Scanner/C.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Scanner/Dir.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Scanner/Prog.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Scanner/RC.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Scanner/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Script/Interactive.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Script/Main.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Script/SConsOptions.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Script/SConscript.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Script/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/386asm.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/GettextCommon.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/PharLapCommon.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/aixc++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/aixcc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/aixcxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/aixlink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/applelink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/ar.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/as.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/bcc32.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/c++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/cc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/clang.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/clangxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/cxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/cyglink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/default.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/filesystem.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/g++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/gas.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/gcc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/gettext_tool.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/gnulink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/gxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/hpc++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/hpcc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/hpcxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/hplink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/icc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/icl.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/ilink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/ilink32.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/install.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/intelc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/link.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/linkloc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/m4.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/masm.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mingw.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/msgfmt.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/msginit.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/msgmerge.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mslib.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mslink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mssdk.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/msvc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/msvs.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mwcc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/mwld.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/nasm.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/rmic.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/rpcgen.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sgiar.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sgic++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sgicc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sgicxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sgilink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sunar.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sunc++.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/suncc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/suncxx.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/sunlink.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/tar.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/textfile.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/tlib.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/wix.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/xgettext.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/zip.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/arch.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/common.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/netframework.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/sdk.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/vc.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/MSCommon/vs.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/clangCommon/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Tool/docbook/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/BoolVariable.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/EnumVariable.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/ListVariable.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/PackageVariable.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/PathVariable.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/Variables/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/compat/__init__.py nuitka/build/inline_copy/lib/scons-3.1.2/SCons/compat/_scons_dbm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Action.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Builder.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/CacheDir.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Conftest.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Debug.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Defaults.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Environment.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/EnvironmentValues.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Errors.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Executor.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Job.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Memoize.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/PathList.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/SConf.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/SConsign.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Subst.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Taskmaster.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Util.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Warnings.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/cpp.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/dblite.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/exitfuncs.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Node/Alias.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Node/FS.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Node/Python.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Node/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/aix.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/cygwin.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/darwin.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/hpux.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/irix.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/mingw.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/os2.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/posix.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/sunos.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/virtualenv.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Platform/win32.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Scanner/C.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Scanner/Dir.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Scanner/Prog.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Scanner/RC.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Scanner/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Script/Interactive.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Script/Main.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Script/SConsOptions.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Script/SConscript.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Script/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/386asm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/GettextCommon.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/PharLapCommon.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/aixc++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/aixcc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/aixcxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/aixlink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/applelink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/ar.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/as.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/asm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/bcc32.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/c++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/cc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/clang.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/clangxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/cxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/cyglink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/default.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/filesystem.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/g++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/gas.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/gcc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/gettext_tool.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/gnulink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/gxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/hpc++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/hpcc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/hpcxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/hplink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/icc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/icl.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/ilink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/ilink32.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/install.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/intelc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/link.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/linkloc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/m4.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/masm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mingw.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/msgfmt.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/msginit.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/msgmerge.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mslib.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mslink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mssdk.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/msvc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/msvs.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mwcc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/mwld.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/nasm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/rmic.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/rpcgen.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sgiar.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sgic++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sgicc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sgicxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sgilink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sunar.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sunc++.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/suncc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/suncxx.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/sunlink.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/tar.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/textfile.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/tlib.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/wix.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/xgettext.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/zip.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/arch.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/common.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/netframework.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/sdk.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/vc.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/MSCommon/vs.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/clangCommon/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/linkCommon/LoadableModule.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/linkCommon/SharedLibrary.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Tool/linkCommon/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Utilities/ConfigureCache.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Utilities/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Utilities/sconsign.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/BoolVariable.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/EnumVariable.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/ListVariable.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/PackageVariable.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/PathVariable.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/Variables/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/compat/__init__.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/compat/_scons_dbm.py nuitka/build/inline_copy/lib/scons-4.3.0/SCons/compat/win32.py nuitka/build/inline_copy/markupsafe/markupsafe/__init__.py nuitka/build/inline_copy/markupsafe/markupsafe/_compat.py nuitka/build/inline_copy/markupsafe/markupsafe/_constants.py nuitka/build/inline_copy/markupsafe/markupsafe/_native.py nuitka/build/inline_copy/tqdm/tqdm/__init__.py nuitka/build/inline_copy/tqdm/tqdm/__main__.py nuitka/build/inline_copy/tqdm/tqdm/_main.py nuitka/build/inline_copy/tqdm/tqdm/_monitor.py nuitka/build/inline_copy/tqdm/tqdm/_tqdm.py nuitka/build/inline_copy/tqdm/tqdm/_tqdm_gui.py nuitka/build/inline_copy/tqdm/tqdm/_tqdm_notebook.py nuitka/build/inline_copy/tqdm/tqdm/_tqdm_pandas.py nuitka/build/inline_copy/tqdm/tqdm/_utils.py nuitka/build/inline_copy/tqdm/tqdm/auto.py nuitka/build/inline_copy/tqdm/tqdm/autonotebook.py nuitka/build/inline_copy/tqdm/tqdm/dask.py nuitka/build/inline_copy/tqdm/tqdm/gui.py nuitka/build/inline_copy/tqdm/tqdm/keras.py nuitka/build/inline_copy/tqdm/tqdm/notebook.py nuitka/build/inline_copy/tqdm/tqdm/std.py nuitka/build/inline_copy/tqdm/tqdm/tk.py nuitka/build/inline_copy/tqdm/tqdm/utils.py nuitka/build/inline_copy/tqdm/tqdm/version.py nuitka/build/inline_copy/yaml/yaml/__init__.py nuitka/build/inline_copy/yaml/yaml/composer.py nuitka/build/inline_copy/yaml/yaml/constructor.py nuitka/build/inline_copy/yaml/yaml/cyaml.py nuitka/build/inline_copy/yaml/yaml/dumper.py nuitka/build/inline_copy/yaml/yaml/emitter.py nuitka/build/inline_copy/yaml/yaml/error.py nuitka/build/inline_copy/yaml/yaml/events.py nuitka/build/inline_copy/yaml/yaml/loader.py nuitka/build/inline_copy/yaml/yaml/nodes.py nuitka/build/inline_copy/yaml/yaml/parser.py nuitka/build/inline_copy/yaml/yaml/reader.py nuitka/build/inline_copy/yaml/yaml/representer.py nuitka/build/inline_copy/yaml/yaml/resolver.py nuitka/build/inline_copy/yaml/yaml/scanner.py nuitka/build/inline_copy/yaml/yaml/serializer.py nuitka/build/inline_copy/yaml/yaml/tokens.py nuitka/build/inline_copy/yaml_27/yaml/__init__.py nuitka/build/inline_copy/yaml_27/yaml/composer.py nuitka/build/inline_copy/yaml_27/yaml/constructor.py nuitka/build/inline_copy/yaml_27/yaml/cyaml.py nuitka/build/inline_copy/yaml_27/yaml/dumper.py nuitka/build/inline_copy/yaml_27/yaml/emitter.py nuitka/build/inline_copy/yaml_27/yaml/error.py nuitka/build/inline_copy/yaml_27/yaml/events.py nuitka/build/inline_copy/yaml_27/yaml/loader.py nuitka/build/inline_copy/yaml_27/yaml/nodes.py nuitka/build/inline_copy/yaml_27/yaml/parser.py nuitka/build/inline_copy/yaml_27/yaml/reader.py nuitka/build/inline_copy/yaml_27/yaml/representer.py nuitka/build/inline_copy/yaml_27/yaml/resolver.py nuitka/build/inline_copy/yaml_27/yaml/scanner.py nuitka/build/inline_copy/yaml_27/yaml/serializer.py nuitka/build/inline_copy/yaml_27/yaml/tokens.py nuitka/build/inline_copy/yaml_35/yaml/__init__.py nuitka/build/inline_copy/yaml_35/yaml/composer.py nuitka/build/inline_copy/yaml_35/yaml/constructor.py nuitka/build/inline_copy/yaml_35/yaml/cyaml.py nuitka/build/inline_copy/yaml_35/yaml/dumper.py nuitka/build/inline_copy/yaml_35/yaml/emitter.py nuitka/build/inline_copy/yaml_35/yaml/error.py nuitka/build/inline_copy/yaml_35/yaml/events.py nuitka/build/inline_copy/yaml_35/yaml/loader.py nuitka/build/inline_copy/yaml_35/yaml/nodes.py nuitka/build/inline_copy/yaml_35/yaml/parser.py nuitka/build/inline_copy/yaml_35/yaml/reader.py nuitka/build/inline_copy/yaml_35/yaml/representer.py nuitka/build/inline_copy/yaml_35/yaml/resolver.py nuitka/build/inline_copy/yaml_35/yaml/scanner.py nuitka/build/inline_copy/yaml_35/yaml/serializer.py nuitka/build/inline_copy/yaml_35/yaml/tokens.py nuitka/build/inline_copy/zstd/zstd.h nuitka/build/inline_copy/zstd/common/bitstream.h nuitka/build/inline_copy/zstd/common/compiler.h nuitka/build/inline_copy/zstd/common/cpu.h nuitka/build/inline_copy/zstd/common/debug.h nuitka/build/inline_copy/zstd/common/entropy_common.c nuitka/build/inline_copy/zstd/common/error_private.c nuitka/build/inline_copy/zstd/common/error_private.h nuitka/build/inline_copy/zstd/common/fse.h nuitka/build/inline_copy/zstd/common/fse_decompress.c nuitka/build/inline_copy/zstd/common/huf.h nuitka/build/inline_copy/zstd/common/mem.h nuitka/build/inline_copy/zstd/common/xxhash.c nuitka/build/inline_copy/zstd/common/xxhash.h nuitka/build/inline_copy/zstd/common/zstd_common.c nuitka/build/inline_copy/zstd/common/zstd_deps.h nuitka/build/inline_copy/zstd/common/zstd_errors.h nuitka/build/inline_copy/zstd/common/zstd_internal.h nuitka/build/inline_copy/zstd/decompress/huf_decompress.c nuitka/build/inline_copy/zstd/decompress/zstd_ddict.c nuitka/build/inline_copy/zstd/decompress/zstd_ddict.h nuitka/build/inline_copy/zstd/decompress/zstd_decompress.c nuitka/build/inline_copy/zstd/decompress/zstd_decompress_block.c nuitka/build/inline_copy/zstd/decompress/zstd_decompress_block.h nuitka/build/inline_copy/zstd/decompress/zstd_decompress_internal.h nuitka/build/static_src/CompiledAsyncgenType.c nuitka/build/static_src/CompiledCellType.c nuitka/build/static_src/CompiledCodeHelpers.c nuitka/build/static_src/CompiledCoroutineType.c nuitka/build/static_src/CompiledFrameType.c nuitka/build/static_src/CompiledFunctionType.c nuitka/build/static_src/CompiledGeneratorType.c nuitka/build/static_src/CompiledGeneratorTypeUncompiledIntegration.c nuitka/build/static_src/CompiledMethodType.c nuitka/build/static_src/HelpersAttributes.c nuitka/build/static_src/HelpersBuiltin.c nuitka/build/static_src/HelpersBuiltinTypeMethods.c nuitka/build/static_src/HelpersCalling.c nuitka/build/static_src/HelpersCalling2.c nuitka/build/static_src/HelpersClasses.c nuitka/build/static_src/HelpersComparisonEq.c nuitka/build/static_src/HelpersComparisonEqUtils.c nuitka/build/static_src/HelpersComparisonGe.c nuitka/build/static_src/HelpersComparisonGt.c nuitka/build/static_src/HelpersComparisonLe.c nuitka/build/static_src/HelpersComparisonLt.c nuitka/build/static_src/HelpersComparisonNe.c nuitka/build/static_src/HelpersConstantsBlob.c nuitka/build/static_src/HelpersDeepcopy.c nuitka/build/static_src/HelpersDictionaries.c nuitka/build/static_src/HelpersExceptions.c nuitka/build/static_src/HelpersHeapStorage.c nuitka/build/static_src/HelpersImport.c nuitka/build/static_src/HelpersImportHard.c nuitka/build/static_src/HelpersLists.c nuitka/build/static_src/HelpersOperationBinaryAdd.c nuitka/build/static_src/HelpersOperationBinaryAddUtils.c nuitka/build/static_src/HelpersOperationBinaryBitand.c nuitka/build/static_src/HelpersOperationBinaryBitor.c nuitka/build/static_src/HelpersOperationBinaryBitxor.c nuitka/build/static_src/HelpersOperationBinaryDivmod.c nuitka/build/static_src/HelpersOperationBinaryDivmodUtils.c nuitka/build/static_src/HelpersOperationBinaryFloordiv.c nuitka/build/static_src/HelpersOperationBinaryInplaceAdd.c nuitka/build/static_src/HelpersOperationBinaryLshift.c nuitka/build/static_src/HelpersOperationBinaryMatmult.c nuitka/build/static_src/HelpersOperationBinaryMod.c nuitka/build/static_src/HelpersOperationBinaryMult.c nuitka/build/static_src/HelpersOperationBinaryMultUtils.c nuitka/build/static_src/HelpersOperationBinaryOlddiv.c nuitka/build/static_src/HelpersOperationBinaryPow.c nuitka/build/static_src/HelpersOperationBinaryPowUtils.c nuitka/build/static_src/HelpersOperationBinaryRshift.c nuitka/build/static_src/HelpersOperationBinarySub.c nuitka/build/static_src/HelpersOperationBinaryTruediv.c nuitka/build/static_src/HelpersOperationInplaceAdd.c nuitka/build/static_src/HelpersOperationInplaceAddUtils.c nuitka/build/static_src/HelpersOperationInplaceBitand.c nuitka/build/static_src/HelpersOperationInplaceBitor.c nuitka/build/static_src/HelpersOperationInplaceBitxor.c nuitka/build/static_src/HelpersOperationInplaceFloordiv.c nuitka/build/static_src/HelpersOperationInplaceLshift.c nuitka/build/static_src/HelpersOperationInplaceMatmult.c nuitka/build/static_src/HelpersOperationInplaceMod.c nuitka/build/static_src/HelpersOperationInplaceMult.c nuitka/build/static_src/HelpersOperationInplaceOlddiv.c nuitka/build/static_src/HelpersOperationInplacePow.c nuitka/build/static_src/HelpersOperationInplaceRshift.c nuitka/build/static_src/HelpersOperationInplaceSub.c nuitka/build/static_src/HelpersOperationInplaceTruediv.c nuitka/build/static_src/HelpersProfiling.c nuitka/build/static_src/HelpersPythonPgo.c nuitka/build/static_src/HelpersRaising.c nuitka/build/static_src/HelpersSafeStrings.c nuitka/build/static_src/HelpersStrings.c nuitka/build/static_src/InspectPatcher.c nuitka/build/static_src/MainProgram.c nuitka/build/static_src/MetaPathBasedLoader.c nuitka/build/static_src/OnefileBootstrap.c nuitka/build/static_src/OnefileSplashScreen.cpp nuitka/codegen/AsyncgenCodes.py nuitka/codegen/AttributeCodes.py nuitka/codegen/BranchCodes.py nuitka/codegen/BuiltinCodes.py nuitka/codegen/CallCodes.py nuitka/codegen/ClassCodes.py nuitka/codegen/CodeGeneration.py nuitka/codegen/CodeHelpers.py nuitka/codegen/CodeObjectCodes.py nuitka/codegen/ComparisonCodes.py nuitka/codegen/ConditionalCodes.py nuitka/codegen/ConstantCodes.py nuitka/codegen/Contexts.py nuitka/codegen/CoroutineCodes.py nuitka/codegen/DictCodes.py nuitka/codegen/Emission.py nuitka/codegen/ErrorCodes.py nuitka/codegen/EvalCodes.py nuitka/codegen/ExceptionCodes.py nuitka/codegen/ExpressionCodes.py nuitka/codegen/FrameCodes.py nuitka/codegen/FunctionCodes.py nuitka/codegen/GeneratorCodes.py nuitka/codegen/GlobalConstants.py nuitka/codegen/GlobalsLocalsCodes.py nuitka/codegen/HelperDefinitions.py nuitka/codegen/IdCodes.py nuitka/codegen/ImportCodes.py nuitka/codegen/Indentation.py nuitka/codegen/IndexCodes.py nuitka/codegen/IntegerCodes.py nuitka/codegen/IteratorCodes.py nuitka/codegen/LabelCodes.py nuitka/codegen/LineNumberCodes.py nuitka/codegen/ListCodes.py nuitka/codegen/LoaderCodes.py nuitka/codegen/LocalsDictCodes.py nuitka/codegen/LoopCodes.py nuitka/codegen/ModuleCodes.py nuitka/codegen/Namify.py nuitka/codegen/OperationCodes.py nuitka/codegen/OperatorCodes.py nuitka/codegen/PrintCodes.py nuitka/codegen/PythonAPICodes.py nuitka/codegen/RaisingCodes.py nuitka/codegen/Reports.py nuitka/codegen/ReturnCodes.py nuitka/codegen/SetCodes.py nuitka/codegen/SliceCodes.py nuitka/codegen/StringCodes.py nuitka/codegen/SubscriptCodes.py nuitka/codegen/TryCodes.py nuitka/codegen/TupleCodes.py nuitka/codegen/VariableCodes.py nuitka/codegen/VariableDeclarations.py nuitka/codegen/YieldCodes.py nuitka/codegen/__init__.py nuitka/codegen/c_types/CTypeBases.py nuitka/codegen/c_types/CTypeBools.py nuitka/codegen/c_types/CTypeModuleDictVariables.py nuitka/codegen/c_types/CTypeNuitkaBools.py nuitka/codegen/c_types/CTypeNuitkaInts.py nuitka/codegen/c_types/CTypePyObjectPtrs.py nuitka/codegen/c_types/CTypeVoids.py nuitka/codegen/c_types/__init__.py nuitka/codegen/templates/CodeTemplatesAsyncgens.py nuitka/codegen/templates/CodeTemplatesConstants.py nuitka/codegen/templates/CodeTemplatesCoroutines.py nuitka/codegen/templates/CodeTemplatesExceptions.py nuitka/codegen/templates/CodeTemplatesFrames.py nuitka/codegen/templates/CodeTemplatesFunction.py nuitka/codegen/templates/CodeTemplatesGeneratorFunction.py nuitka/codegen/templates/CodeTemplatesIterators.py nuitka/codegen/templates/CodeTemplatesLoader.py nuitka/codegen/templates/CodeTemplatesModules.py nuitka/codegen/templates/CodeTemplatesVariables.py nuitka/codegen/templates/TemplateDebugWrapper.py nuitka/codegen/templates/__init__.py nuitka/codegen/templates_c/CodeTemplateCallsMethodPositional.c.j2 nuitka/codegen/templates_c/CodeTemplateCallsMixed.c.j2 nuitka/codegen/templates_c/CodeTemplateCallsPositional.c.j2 nuitka/codegen/templates_c/CodeTemplateCallsPositionalMethodDescr.c.j2 nuitka/codegen/templates_c/HelperBuiltinMethodOperation.c.j2 nuitka/codegen/templates_c/HelperImportHard.c.j2 nuitka/codegen/templates_c/HelperObjectTools.c.j2 nuitka/codegen/templates_c/HelperOperationBinary.c.j2 nuitka/codegen/templates_c/HelperOperationComparison.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonBytes.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonFloat.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonInt.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonList.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonLong.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonStr.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonTuple.c.j2 nuitka/codegen/templates_c/HelperOperationComparisonUnicode.c.j2 nuitka/codegen/templates_c/HelperOperationInplace.c.j2 nuitka/codegen/templates_c/HelperSlotsBinary.c.j2 nuitka/codegen/templates_c/HelperSlotsBytes.c.j2 nuitka/codegen/templates_c/HelperSlotsCommon.c.j2 nuitka/codegen/templates_c/HelperSlotsFloat.c.j2 nuitka/codegen/templates_c/HelperSlotsInt.c.j2 nuitka/codegen/templates_c/HelperSlotsList.c.j2 nuitka/codegen/templates_c/HelperSlotsLong.c.j2 nuitka/codegen/templates_c/HelperSlotsSet.c.j2 nuitka/codegen/templates_c/HelperSlotsStr.c.j2 nuitka/codegen/templates_c/HelperSlotsTuple.c.j2 nuitka/codegen/templates_c/HelperSlotsUnicode.c.j2 nuitka/constants/Serialization.py nuitka/constants/__init__.py nuitka/containers/__init__.py nuitka/containers/odict.py nuitka/containers/oset.py nuitka/distutils/Build.py nuitka/distutils/DistutilCommands.py nuitka/distutils/__init__.py nuitka/finalizations/Finalization.py nuitka/finalizations/FinalizeMarkups.py nuitka/finalizations/__init__.py nuitka/freezer/DependsExe.py nuitka/freezer/IncludedDataFiles.py nuitka/freezer/IncludedEntryPoints.py nuitka/freezer/Onefile.py nuitka/freezer/RuntimeTracing.py nuitka/freezer/Standalone.py nuitka/freezer/__init__.py nuitka/importing/IgnoreListing.py nuitka/importing/ImportCache.py nuitka/importing/ImportResolving.py nuitka/importing/Importing.py nuitka/importing/PreloadedPackages.py nuitka/importing/Recursion.py nuitka/importing/StandardLibrary.py nuitka/importing/__init__.py nuitka/nodes/AssignNodes.py nuitka/nodes/AsyncgenNodes.py nuitka/nodes/AttributeLookupNodes.py nuitka/nodes/AttributeNodes.py nuitka/nodes/AttributeNodesGenerated.py nuitka/nodes/BuiltinAllNodes.py nuitka/nodes/BuiltinAnyNodes.py nuitka/nodes/BuiltinComplexNodes.py nuitka/nodes/BuiltinDecodingNodes.py nuitka/nodes/BuiltinDecoratorNodes.py nuitka/nodes/BuiltinDictNodes.py nuitka/nodes/BuiltinFormatNodes.py nuitka/nodes/BuiltinHashNodes.py nuitka/nodes/BuiltinIntegerNodes.py nuitka/nodes/BuiltinIteratorNodes.py nuitka/nodes/BuiltinLenNodes.py nuitka/nodes/BuiltinNextNodes.py nuitka/nodes/BuiltinOpenNodes.py nuitka/nodes/BuiltinRangeNodes.py nuitka/nodes/BuiltinRefNodes.py nuitka/nodes/BuiltinSumNodes.py nuitka/nodes/BuiltinTypeNodes.py nuitka/nodes/BuiltinVarsNodes.py nuitka/nodes/CallNodes.py nuitka/nodes/Checkers.py nuitka/nodes/ClassNodes.py nuitka/nodes/CodeObjectSpecs.py nuitka/nodes/ComparisonNodes.py nuitka/nodes/ConditionalNodes.py nuitka/nodes/ConstantRefNodes.py nuitka/nodes/ContainerMakingNodes.py nuitka/nodes/ContainerOperationNodes.py nuitka/nodes/CoroutineNodes.py nuitka/nodes/DictionaryNodes.py nuitka/nodes/ExceptionNodes.py nuitka/nodes/ExecEvalNodes.py nuitka/nodes/ExpressionBases.py nuitka/nodes/ExpressionShapeMixins.py nuitka/nodes/FrameNodes.py nuitka/nodes/FunctionAttributeNodes.py nuitka/nodes/FunctionNodes.py nuitka/nodes/FutureSpecs.py nuitka/nodes/GeneratorNodes.py nuitka/nodes/GlobalsLocalsNodes.py nuitka/nodes/ImportNodes.py nuitka/nodes/IndicatorMixins.py nuitka/nodes/IterationHandles.py nuitka/nodes/LocalsDictNodes.py nuitka/nodes/LocalsScopes.py nuitka/nodes/LoopNodes.py nuitka/nodes/ModuleAttributeNodes.py nuitka/nodes/ModuleNodes.py nuitka/nodes/NodeBases.py nuitka/nodes/NodeMakingHelpers.py nuitka/nodes/NodeMetaClasses.py nuitka/nodes/OperatorNodes.py nuitka/nodes/OperatorNodesUnary.py nuitka/nodes/OutlineNodes.py nuitka/nodes/PrintNodes.py nuitka/nodes/ReturnNodes.py nuitka/nodes/SideEffectNodes.py nuitka/nodes/SliceNodes.py nuitka/nodes/StatementNodes.py nuitka/nodes/StrNodes.py nuitka/nodes/StringConcatenationNodes.py nuitka/nodes/SubscriptNodes.py nuitka/nodes/TryNodes.py nuitka/nodes/TypeMatchNodes.py nuitka/nodes/TypeNodes.py nuitka/nodes/VariableRefNodes.py nuitka/nodes/YieldNodes.py nuitka/nodes/__init__.py nuitka/nodes/shapes/BuiltinTypeShapes.py nuitka/nodes/shapes/ControlFlowDescriptions.py nuitka/nodes/shapes/ShapeMixins.py nuitka/nodes/shapes/StandardShapes.py nuitka/nodes/shapes/__init__.py nuitka/optimizations/BytecodeDemotion.py nuitka/optimizations/FunctionInlining.py nuitka/optimizations/Graphs.py nuitka/optimizations/Optimization.py nuitka/optimizations/OptimizeBuiltinCalls.py nuitka/optimizations/Tags.py nuitka/optimizations/TraceCollections.py nuitka/optimizations/ValueTraces.py nuitka/optimizations/__init__.py nuitka/pgo/PGO.py nuitka/pgo/__init__.py nuitka/plugins/PluginBase.py nuitka/plugins/Plugins.py nuitka/plugins/__init__.py nuitka/plugins/commercial/__init__.py nuitka/plugins/standard/AntiBloat.py nuitka/plugins/standard/ConsiderPyLintAnnotationsPlugin.py nuitka/plugins/standard/DataFileCollectorPlugin.py nuitka/plugins/standard/DillPlugin.py nuitka/plugins/standard/EnumPlugin.py nuitka/plugins/standard/EventletPlugin.py nuitka/plugins/standard/GeventPlugin.py nuitka/plugins/standard/GiPlugin.py nuitka/plugins/standard/GlfwPlugin.py nuitka/plugins/standard/ImplicitImports.py nuitka/plugins/standard/KivyPlugin.py nuitka/plugins/standard/MatplotlibPlugin.py nuitka/plugins/standard/MultiprocessingPlugin.py nuitka/plugins/standard/NumpyPlugin.py nuitka/plugins/standard/PbrPlugin.py nuitka/plugins/standard/PkgResourcesPlugin.py nuitka/plugins/standard/PmwPlugin.py nuitka/plugins/standard/PySidePyQtPlugin.py nuitka/plugins/standard/PywebViewPlugin.py nuitka/plugins/standard/TensorflowPlugin.py nuitka/plugins/standard/TkinterPlugin.py nuitka/plugins/standard/TorchPlugin.py nuitka/plugins/standard/TrioPlugin.py nuitka/plugins/standard/ZmqPlugin.py nuitka/plugins/standard/__init__.py nuitka/plugins/standard/anti-bloat.yml nuitka/plugins/standard/data-files.yml nuitka/plugins/standard/implicit-imports.yml nuitka/specs/BuiltinDictOperationSpecs.py nuitka/specs/BuiltinParameterSpecs.py nuitka/specs/BuiltinStrOperationSpecs.py nuitka/specs/BuiltinUnicodeOperationSpecs.py nuitka/specs/ParameterSpecs.py nuitka/specs/__init__.py nuitka/tools/Basics.py nuitka/tools/__init__.py nuitka/tools/commercial/__init__.py nuitka/tools/data_composer/DataComposer.py nuitka/tools/data_composer/__init__.py nuitka/tools/data_composer/__main__.py nuitka/tools/general/__init__.py nuitka/tools/general/dll_report/__init__.py nuitka/tools/general/dll_report/__main__.py nuitka/tools/profiler/__init__.py nuitka/tools/profiler/__main__.py nuitka/tools/specialize/Common.py nuitka/tools/specialize/SpecializeC.py nuitka/tools/specialize/SpecializePython.py nuitka/tools/specialize/__init__.py nuitka/tools/testing/Common.py nuitka/tools/testing/Constructs.py nuitka/tools/testing/OutputComparison.py nuitka/tools/testing/SearchModes.py nuitka/tools/testing/Valgrind.py nuitka/tools/testing/Virtualenv.py nuitka/tools/testing/__init__.py nuitka/tools/testing/check_reference_counts/__init__.py nuitka/tools/testing/check_reference_counts/__main__.py nuitka/tools/testing/compare_with_cpython/__init__.py nuitka/tools/testing/compare_with_cpython/__main__.py nuitka/tools/testing/find_sxs_modules/__init__.py nuitka/tools/testing/find_sxs_modules/__main__.py nuitka/tools/testing/measure_construct_performance/__init__.py nuitka/tools/testing/measure_construct_performance/__main__.py nuitka/tools/testing/run_nuitka_tests/__init__.py nuitka/tools/testing/run_nuitka_tests/__main__.py nuitka/tree/Building.py nuitka/tree/ComplexCallHelperFunctions.py nuitka/tree/Extractions.py nuitka/tree/InternalModule.py nuitka/tree/Operations.py nuitka/tree/ReformulationAssertStatements.py nuitka/tree/ReformulationAssignmentStatements.py nuitka/tree/ReformulationBooleanExpressions.py nuitka/tree/ReformulationCallExpressions.py nuitka/tree/ReformulationClasses.py nuitka/tree/ReformulationClasses3.py nuitka/tree/ReformulationComparisonExpressions.py nuitka/tree/ReformulationContractionExpressions.py nuitka/tree/ReformulationDictionaryCreation.py nuitka/tree/ReformulationExecStatements.py nuitka/tree/ReformulationForLoopStatements.py nuitka/tree/ReformulationFunctionStatements.py nuitka/tree/ReformulationImportStatements.py nuitka/tree/ReformulationLambdaExpressions.py nuitka/tree/ReformulationMatchStatements.py nuitka/tree/ReformulationNamespacePackages.py nuitka/tree/ReformulationPrintStatements.py nuitka/tree/ReformulationSequenceCreation.py nuitka/tree/ReformulationSubscriptExpressions.py nuitka/tree/ReformulationTryExceptStatements.py nuitka/tree/ReformulationTryFinallyStatements.py nuitka/tree/ReformulationWhileLoopStatements.py nuitka/tree/ReformulationWithStatements.py nuitka/tree/ReformulationYieldExpressions.py nuitka/tree/SourceReading.py nuitka/tree/SyntaxErrors.py nuitka/tree/TreeHelpers.py nuitka/tree/VariableClosure.py nuitka/tree/__init__.py nuitka/utils/AppDirs.py nuitka/utils/CStrings.py nuitka/utils/Download.py nuitka/utils/Execution.py nuitka/utils/FileOperations.py nuitka/utils/Images.py nuitka/utils/Importing.py nuitka/utils/InstanceCounters.py nuitka/utils/Jinja2.py nuitka/utils/Json.py nuitka/utils/MacOSApp.py nuitka/utils/MemoryUsage.py nuitka/utils/ModuleNames.py nuitka/utils/ReExecute.py nuitka/utils/Rest.py nuitka/utils/SharedLibraries.py nuitka/utils/Shebang.py nuitka/utils/Signing.py nuitka/utils/StaticLibraries.py nuitka/utils/ThreadedExecutor.py nuitka/utils/Timing.py nuitka/utils/Utils.py nuitka/utils/WindowsFileUsage.py nuitka/utils/WindowsResources.py nuitka/utils/Yaml.py nuitka/utils/__init__.py tests/run-tests tests/basics/Asserts.py tests/basics/Assignments.py tests/basics/Assignments32.py tests/basics/Branching.py tests/basics/BuiltinOverload.py tests/basics/BuiltinSuper.py tests/basics/BuiltinsTest.py tests/basics/ClassMinimal.py tests/basics/Classes.py tests/basics/Classes32.py tests/basics/Classes34.py tests/basics/ComparisonChains.py tests/basics/Constants.py tests/basics/Constants27.py tests/basics/Decorators.py tests/basics/DefaultParameters.py tests/basics/DoubleDeletions.py tests/basics/Empty.py tests/basics/ExceptionRaising.py tests/basics/ExceptionRaising32.py tests/basics/ExceptionRaising33.py tests/basics/ExecEval.py tests/basics/ExtremeClosure.py tests/basics/FunctionObjects.py tests/basics/Functions.py tests/basics/Functions32.py tests/basics/Functions_2.py tests/basics/Future32.py tests/basics/GeneratorExpressions.py tests/basics/GeneratorExpressions_37.py tests/basics/GlobalStatement.py tests/basics/HelloWorld_2.py tests/basics/Importing.py tests/basics/InplaceOperations.py tests/basics/Inspection.py tests/basics/Inspection_35.py tests/basics/Inspection_36.py tests/basics/Lamdas.py tests/basics/LateClosureAssignment.py tests/basics/ListContractions.py tests/basics/Looping.py tests/basics/MainPrograms.py tests/basics/ModuleAttributes.py tests/basics/Operators.py tests/basics/OrderChecks.py tests/basics/OrderChecks27.py tests/basics/OverflowFunctions_2.py tests/basics/ParameterErrors.py tests/basics/ParameterErrors32.py tests/basics/PrintFuture.py tests/basics/Printing_2.py tests/basics/RecursionTest.py tests/basics/Referencing.py tests/basics/Referencing27.py tests/basics/Referencing33.py tests/basics/Referencing35.py tests/basics/Referencing36.py tests/basics/Referencing_2.py tests/basics/Slots.py tests/basics/ThreadedGenerators.py tests/basics/TrickAssignments32.py tests/basics/TrickAssignments35.py tests/basics/TrickAssignments_2.py tests/basics/TryContinueFinally.py tests/basics/TryExceptContinue.py tests/basics/TryExceptFinally.py tests/basics/TryExceptFrames.py tests/basics/TryReturnFinally.py tests/basics/TryYieldFinally.py tests/basics/Unicode.py tests/basics/Unpacking35.py tests/basics/Varargs.py tests/basics/WithStatements.py tests/basics/YieldFrom33.py tests/basics/run_all.py tests/basics/run_xml.py tests/onefile/HelloWorldTest.py tests/onefile/KeyboardInteruptTest.py tests/onefile/run_all.py tests/optimizations/ArgumentTypes.py tests/optimizations/Attributes.py tests/optimizations/Calls.py tests/optimizations/Conditions.py tests/optimizations/DecodingOperations.py tests/optimizations/FormatStrings36.py tests/optimizations/HardImports.py tests/optimizations/HardImports_2.py tests/optimizations/Iterations.py tests/optimizations/Len.py tests/optimizations/Operations.py tests/optimizations/Subscripts.py tests/optimizations/run_all.py tests/packages/run_all.py tests/packages/package_import_success_after_failure/PackageImportSuccessAfterFailure.py tests/packages/package_import_success_after_failure/variable_package/SomeModule.py tests/packages/package_import_success_after_failure/variable_package/__init__.py tests/packages/sub_package/kitty/__init__.py tests/packages/sub_package/kitty/bigkitty.py tests/packages/sub_package/kitty/smallkitty.py tests/packages/sub_package/kitty/speak/__init__.py tests/packages/sub_package/kitty/speak/hello.py tests/packages/sub_package/kitty/speak/miau.py tests/packages/sub_package/kitty/speak/purr.py tests/plugins/run_all.py tests/plugins/parameters/ParametersMain.py tests/plugins/parameters/parameter-using-plugin.py tests/programs/run_all.py tests/programs/absolute_import/AbsoluteImportMain.py tests/programs/absolute_import/foobar/__init__.py tests/programs/absolute_import/foobar/foobar.py tests/programs/absolute_import/foobar/local.py tests/programs/absolute_import/foobar/util.py tests/programs/case_imports1/CasedImportingMain.py tests/programs/case_imports1/path1/Some_Module.py tests/programs/case_imports1/path1/Some_Package/__init__.py tests/programs/case_imports1/path2/some_module.py tests/programs/case_imports1/path2/some_package/__init__.py tests/programs/case_imports2/CasedImportingMain.py tests/programs/case_imports2/path1/some_module.py tests/programs/case_imports2/path1/some_package/__init__.py tests/programs/case_imports2/path2/Some_Module.py tests/programs/case_imports2/path2/Some_Package/__init__.py tests/programs/case_imports3/CasedImportingMain.py tests/programs/case_imports3/path1/Some_Module.py tests/programs/case_imports3/path1/Some_Package/__init__.py tests/programs/case_imports3/path2/Some_Module.py tests/programs/case_imports3/path2/Some_Package/__init__.py tests/programs/cyclic_imports/CyclicImportsMain.py tests/programs/cyclic_imports/cyclic_importing_package/Child1.py tests/programs/cyclic_imports/cyclic_importing_package/Child2.py tests/programs/cyclic_imports/cyclic_importing_package/__init__.py tests/programs/dash_import/DashImportMain.py tests/programs/dash_import/dash-module.py tests/programs/dash_import/plus+module.py tests/programs/dash_main/Dash-Main.py tests/programs/deep/DeepProgramMain.py tests/programs/deep/some_package/DeepBrother.py tests/programs/deep/some_package/DeepChild.py tests/programs/deep/some_package/__init__.py tests/programs/deep/some_package/deep_package/DeepDeepChild.py tests/programs/deep/some_package/deep_package/__init__.py tests/programs/dunderinit_imports/DunderInitImportsMain.py tests/programs/dunderinit_imports/package/SubModule.py tests/programs/dunderinit_imports/package/__init__.py tests/programs/import_variants/ImportVariationsMain.py tests/programs/import_variants/some_package/Child1.py tests/programs/import_variants/some_package/Child2.py tests/programs/import_variants/some_package/Child3.py tests/programs/import_variants/some_package/__init__.py tests/programs/main_raises/ErrorMain.py tests/programs/main_raises/ErrorRaising.py tests/programs/main_raises2/ErrorInFunctionMain.py tests/programs/main_raises2/ErrorRaising.py tests/programs/module_attributes/ModuleAttributesMain.py tests/programs/module_attributes/package_level1/Nearby1.py tests/programs/module_attributes/package_level1/__init__.py tests/programs/module_attributes/package_level1/package_level2/Nearby2.py tests/programs/module_attributes/package_level1/package_level2/__init__.py tests/programs/module_attributes/package_level1/package_level2/package_level3/Nearby3.py tests/programs/module_attributes/package_level1/package_level2/package_level3/__init__.py tests/programs/module_exits/ErrorExitingModule.py tests/programs/module_exits/Main.py tests/programs/multiprocessing_using/MultiprocessingUsingMain.py tests/programs/multiprocessing_using/foo/__init__.py tests/programs/multiprocessing_using/foo/__main__.py tests/programs/multiprocessing_using/foo/entry.py tests/programs/named_imports/NamedImportsMain.py tests/programs/named_imports/some_package/SomeModule.py tests/programs/named_imports/some_package/__init__.py tests/programs/named_imports/some_package/sub_package/SomeModule.py tests/programs/package_code/PackageInitCodeMain.py tests/programs/package_code/some_package/SomeModule.py tests/programs/package_code/some_package/__init__.py tests/programs/package_contains_main/PackageContainsMain.py tests/programs/package_contains_main/__init__.py tests/programs/package_contains_main/local.py tests/programs/package_init_import/PackageInitImportMain.py tests/programs/package_init_import/some_package/PackageLocal.py tests/programs/package_init_import/some_package/__init__.py tests/programs/package_init_issue/PackageInitIssueMain.py tests/programs/package_init_issue/some_package/__init__.py tests/programs/package_init_issue/some_package/child_package/SomeModule.py tests/programs/package_init_issue/some_package/child_package/__init__.py tests/programs/package_missing_init/PackageMissingInitMain.py tests/programs/package_missing_init/some_package/some_module.py tests/programs/package_missing_init/some_package/sub_package/some_sub_module.py tests/programs/package_module_collision/PackageAndModuleNamedSameMain.py tests/programs/package_module_collision/something.py tests/programs/package_module_collision/Something/__init__.py tests/programs/package_overload/Main.py tests/programs/package_overload/foo/__init__.py tests/programs/package_overload/foo/bar.py tests/programs/package_overload/foo/bar2.py tests/programs/package_prevents_submodule/PackagePreventsSubmoduleMain.py tests/programs/package_prevents_submodule/some_package/__init__.py tests/programs/package_prevents_submodule/some_package/some_module.py tests/programs/package_program/PackageAsMain/__init__.py tests/programs/package_program/PackageAsMain/__main__.py tests/programs/pkgutil_itermodules/PkgUtilIterModulesMain.py tests/programs/pkgutil_itermodules/some_package/__init__.py tests/programs/pkgutil_itermodules/some_package/sub_package1/SomeModuleC.py tests/programs/pkgutil_itermodules/some_package/sub_package1/SomeModuleD.py tests/programs/pkgutil_itermodules/some_package/sub_package1/__init__.py tests/programs/pkgutil_itermodules/some_package/sub_package2/SomeModuleA.py tests/programs/pkgutil_itermodules/some_package/sub_package2/SomeModuleB.py tests/programs/pkgutil_itermodules/some_package/sub_package2/__init__.py tests/programs/pkgutil_usage/PkgUtilUsageMain.py tests/programs/pkgutil_usage/package/DATA_FILE.txt tests/programs/pkgutil_usage/package/__init__.py tests/programs/plugin_import/PluginImportMain.py tests/programs/plugin_import/some_package/__init__.py tests/programs/plugin_import/some_package/some_module.py tests/programs/reimport_main_dynamic/ImportItselfDynamicMain.py tests/programs/reimport_main_static/ImportItselfStaticMain.py tests/programs/relative_import/RelativeImportMain.py tests/programs/relative_import/dircache.py tests/programs/stdlib_overload/StdlibOverloadMain.py tests/programs/stdlib_overload/pyexpat.py tests/programs/stdlib_overload/some_package/__init__.py tests/programs/stdlib_overload/some_package/normal_importing.py tests/programs/stdlib_overload/some_package/pyexpat.py tests/programs/stdlib_overload/some_package/star_importing.py tests/programs/syntax_errors/IndentationErroring.py tests/programs/syntax_errors/SyntaxErroring.py tests/programs/syntax_errors/SyntaxErrorsMain.py tests/programs/unicode_bom/UnicodeBomMain.py tests/programs/unicode_bom/unicode_bom.py tests/programs/with space/Space Main.py tests/reflected/compile_itself.py tests/standalone/BrotliUsing.py tests/standalone/CtypesUsing.py tests/standalone/FlaskUsing.py tests/standalone/GlfwUsing.py tests/standalone/GtkUsing.py tests/standalone/IdnaUsing.py tests/standalone/Issue116_2.py tests/standalone/LxmlUsing.py tests/standalone/MatplotlibUsing.py tests/standalone/NumpyUsing.py tests/standalone/OpenGLUsing.py tests/standalone/PandasUsing.py tests/standalone/PasslibUsing.py tests/standalone/PendulumUsing.py tests/standalone/PmwUsing.py tests/standalone/PyQt5Plugins.py tests/standalone/PyQt5SSLSupport.py tests/standalone/PyQt5Using.py tests/standalone/PySide6Using.py tests/standalone/RsaUsing.py tests/standalone/ShlibUsing.py tests/standalone/SocketUsing.py tests/standalone/TkInterUsing.py tests/standalone/Urllib3Using.py tests/standalone/Win32ComUsing.py tests/standalone/run_all.py tests/standalone/zip_importer/ZipImporterMain.py tests/syntax/AsyncgenReturn36.py tests/syntax/BreakWithoutLoop.py tests/syntax/ClassReturn.py tests/syntax/ClosureDel_2.py tests/syntax/ContinueWithoutLoop.py tests/syntax/DuplicateArgument.py tests/syntax/ExecWithNesting_2.py tests/syntax/FutureBraces.py tests/syntax/FutureUnknown.py tests/syntax/GeneratorExpressions38.py tests/syntax/GeneratorReturn_2.py tests/syntax/GlobalForParameter.py tests/syntax/Importing32.py tests/syntax/IndentationError.py tests/syntax/LateFutureImport.py tests/syntax/MisplacedFutureImport.py tests/syntax/ModuleReturn.py tests/syntax/NonAsciiWithoutEncoding_2.py tests/syntax/NonlocalForParameter32.py tests/syntax/NonlocalNotFound32.py tests/syntax/StarImportExtra.py tests/syntax/SyntaxError.py tests/syntax/TryExceptAllNotLast.py tests/syntax/TryFinallyContinue_37.py tests/syntax/UnpackNoTuple.py tests/syntax/UnpackTwoStars32.py tests/syntax/YieldFromInModule.py tests/syntax/YieldInAsync35.py tests/syntax/YieldInGenexp38.py tests/syntax/YieldInModule.py tests/syntax/run_all.pyNuitka-0.6.19.1/Nuitka.egg-info/PKG-INFO0000600000372100037210000021252214167275622024323 0ustar nuitka-buildslavenuitka-buildslave00000000000000Metadata-Version: 2.1 Name: Nuitka Version: 0.6.19.1 Summary: Python compiler with full language support and CPython compatibility Home-page: https://nuitka.net Author: Kay Hayen Author-email: Kay.Hayen@gmail.com License: Apache License, Version 2.0 Project-URL: Support, https://nuitka.net/pages/support.html Project-URL: Documentation, https://nuitka.net/doc/user-manual.html Project-URL: Commercial, https://nuitka.net/doc/commercial.html Project-URL: Source, https://github.com/Nuitka/Nuitka Project-URL: Donations, https://nuitka.net/pages/donations.html Project-URL: Twitter, https://twitter.com/KayHayen Description: #################### Nuitka User Manual #################### ********** Overview ********** This document is the recommended first read if you are interested in using Nuitka, understand its use cases, check what you can expect, license, requirements, credits, etc. Nuitka is **the** Python compiler. It is written in Python. It is a seamless replacement or extension to the Python interpreter and compiles **every** construct that CPython 2.6, 2.7, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 have, when itself run with that Python version. It then executes uncompiled code and compiled code together in an extremely compatible manner. You can use all Python library modules and all extension modules freely. Nuitka translates the Python modules into a C level program that then uses ``libpython`` and static C files of its own to execute in the same way as CPython does. All optimization is aimed at avoiding overhead, where it's unnecessary. None is aimed at removing compatibility, although slight improvements will occasionally be done, where not every bug of standard Python is emulated, e.g. more complete error messages are given, but there is a full compatibility mode to disable even that. ******* Usage ******* Requirements ============ - C Compiler: You need a compiler with support for C11 or alternatively for C++03 [#]_ Currently this means, you need to use one of these compilers: - The MinGW64 C11 compiler on Windows, must be based on gcc 11.2 or higher. It will be *automatically* downloaded if no usable C compiler is found, which is the recommended way of installing it, as Nuitka will also upgrade it for you. - Visual Studio 2022 or higher on Windows [#]_, older versions will work but only supported for commercial users. Configure to use the English language pack for best results (Nuitka filters away garbage outputs, but only for English language). It will be used by default if installed. - On all other platforms, the ``gcc`` compiler of at least version 5.1, and below that the ``g++`` compiler of at least version 4.4 as an alternative. - The ``clang`` compiler on macOS X and most FreeBSD architectures. - On Windows the ``clang-cl`` compiler on Windows can be used if provided by the Visual Studio installer. - Python: Version 2.6, 2.7 or 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 .. admonition:: For Python 3.3/3.4 and *only* those, we need other Python version as a *compile time* dependency. Nuitka itself is fully compatible with all listed versions, but Scons as an internally used tool is not. For these versions, you *need* a Python2 or Python 3.5 or higher installed as well, but only during the compile time only. That is for use with Scons (which orchestrates the C compilation), which does not support the same Python versions as Nuitka. In addition, on Windows, Python2 cannot be used because ``clcache`` does not work with it, there a Python 3.5 or higher needs to be installed. Nuitka finds these needed Python versions (on Windows via registry) and you shouldn't notice it as long as they are installed. .. admonition:: Moving binaries to other machines The created binaries can be made executable independent of the Python installation, with ``--standalone`` and ``--onefile`` options. .. admonition:: Binary filename suffix The created binaries have an ``.exe`` suffix on Windows. On other platforms they have no suffix for standalone mode, or ``.bin`` suffix, that you are free to remove or change, or specify with the ``-o`` option. The suffix for acceleration mode is added just to be sure that the original script name and the binary name do not ever collide, so we can safely do an overwrite without destroying the original source file. .. admonition:: It **has to** be CPython, Anaconda Python. You need the standard Python implementation, called "CPython", to execute Nuitka, because it is closely tied to implementation details of it. .. admonition:: It **cannot be** from Windows app store It is known that Windows app store Python definitely does not work, it's checked against. And on macOS "pyenv" likely does **not** work. - Operating System: Linux, FreeBSD, NetBSD, macOS X, and Windows (32/64 bits). Others may work as well. The portability is expected to be generally good, but the e.g. Scons usage may have to be adapted. Make sure to match Windows Python and C compiler architecture, or else you will get cryptic error messages. - Architectures: x86, x86_64 (amd64), and arm, likely many more Other architectures are expected to also work, out of the box, as Nuitka is generally not using any hardware specifics. These are just the ones tested and known to be good. Feedback is welcome. Generally, the architectures that Debian supports can be considered good and tested too. .. [#] Support for this C11 is a given with gcc 5.x or higher or any clang version. The MSVC compiler doesn't do it yet. But as a workaround, as the C++03 language standard is very overlapping with C11, it is then used instead where the C compiler is too old. Nuitka used to require a C++ compiler in the past, but it changed. .. [#] Download for free from https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx (the community editions work just fine). The latest version is recommended but not required. On the other hand, there is no need to except pre-Windows 10 support, and they might work for you, but support of these configurations is only available to commercial users. Command Line ============ The recommended way of executing Nuitka is `` -m nuitka`` to be absolutely certain which Python interpreter you are using, so it is easier to match with what Nuitka has. The next best way of executing Nuitka bare that is from a source checkout or archive, with no environment variable changes, most noteworthy, you do not have to mess with ``PYTHONPATH`` at all for Nuitka. You just execute the ``nuitka`` and ``nuitka-run`` scripts directly without any changes to the environment. You may want to add the ``bin`` directory to your ``PATH`` for your convenience, but that step is optional. Moreover, if you want to execute with the right interpreter, in that case, be sure to execute `` bin/nuitka`` and be good. .. admonition:: Pick the right Interpreter If you encounter a ``SyntaxError`` you absolutely most certainly have picked the wrong interpreter for the program you are compiling. Nuitka has a ``--help`` option to output what it can do: .. code:: bash nuitka --help The ``nuitka-run`` command is the same as ``nuitka``, but with a different default. It tries to compile *and* directly execute a Python script: .. code:: bash nuitka-run --help This option that is different is ``--run``, and passing on arguments after the first non-option to the created binary, so it is somewhat more similar to what plain ``python`` will do. Installation ============ For most systems, there will be packages on the `download page `__ of Nuitka. But you can also install it from source code as described above, but also like any other Python program it can be installed via the normal ``python setup.py install`` routine. License ======= Nuitka is licensed under the Apache License, Version 2.0; you may not use it except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ************************************* Tutorial Setup and build on Windows ************************************* This is basic steps if you have nothing installed, of course if you have any of the parts, just skip it. Setup ===== Install Python -------------- - Download and install from https://www.python.org/downloads/windows - Select one of ``Windows x86-64 web-based installer`` (64 bits Python, recommended) or ``x86 executable`` (32 bits Python) installer. - Verify using command ``python --version``. Install Nuitka -------------- - ``python -m pip install nuitka`` - Verify using command ``python -m nuitka --version`` Write some code and test ======================== Create a folder for the Python code ----------------------------------- - mkdir HelloWorld - make a python file named **hello.py** .. code:: python def talk(message): return "Talk " + message def main(): print(talk("Hello World")) if __name__ == "__main__": main() Test your program ----------------- Do as you normally would. Running Nuitka on code that works incorrectly is not easier to debug. .. code:: bash python hello.py ---- Build it using -------------- .. code:: bash python -m nuitka hello.py .. note:: This will prompt you to download a C caching tool (to speed up repeated compilation of generated C code) and a MinGW64 based C compiler unless you have a suitable MSVC installed. Say ``yes`` to both those questions. Run it ------ Execute the ``hello.exe`` created near ``hello.py``. Distribute ---------- To distribute, build with ``--standalone`` option, which will not output a single executable, but a whole folder. Copy the resulting ``hello.dist`` folder to the other machine and run it. You may also try ``--onefile`` which does create a single file, but make sure that the mere standalone is working, before turning to it, as it will make the debugging only harder, e.g. in case of missing data files. *********** Use Cases *********** Use Case 1 - Program compilation with all modules embedded ========================================================== If you want to compile a whole program recursively, and not only the single file that is the main program, do it like this: .. code:: bash python -m nuitka --follow-imports program.py .. note:: There are more fine grained controls than ``--follow-imports`` available. Consider the output of ``nuitka --help``. Including less modules into the compilation, but instead using normal Python for it will make it faster to compile. In case you have a source directory with dynamically loaded files, i.e. one which cannot be found by recursing after normal import statements via the ``PYTHONPATH`` (which would be the recommended way), you can always require that a given directory shall also be included in the executable: .. code:: bash python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py .. note:: If you don't do any dynamic imports, simply setting your ``PYTHONPATH`` at compilation time is what you should do. Use ``--include-plugin-directory`` only if you make ``__import__()`` calls that Nuitka cannot predict, because they e.g. depend on command line parameters. Nuitka also warns about these, and point to the option. .. note:: The resulting filename will be ``program.exe`` on Windows, ``program.bin`` on other platforms. .. note:: The resulting binary still depend on CPython and used C extension modules being installed. If you want to be able to copy it to another machine, use ``--standalone`` and copy the created ``program.dist`` directory and execute the ``program.exe`` (Windows) or ``program`` (other platforms) put inside. Use Case 2 - Extension Module compilation ========================================= If you want to compile a single extension module, all you have to do is this: .. code:: bash python -m nuitka --module some_module.py The resulting file ``some_module.so`` can then be used instead of ``some_module.py``. .. note:: It's left as an exercise to the reader, to find out what happens if both are present. .. note:: The option ``--follow-imports`` and other variants work as well, but the included modules will only become importable *after* you imported the ``some_module`` name. .. note:: The resulting extension module can only be loaded into a CPython of the same version and doesn't include other extension modules. Use Case 3 - Package compilation ================================ If you need to compile a whole package and embed all modules, that is also feasible, use Nuitka like this: .. code:: bash python -m nuitka --module some_package --include-package=some_package .. note:: The inclusion of the package contents needs to be provided manually, otherwise, the package is empty. You can be more specific if you want, and only include part of it. Data files located inside the package will not be embedded by this process, you need to copy them yourself with this approach. Use Case 4 - Program Distribution ================================= For distribution to other systems, there is the standalone mode which produces a folder for which you can specify ``--standalone``. .. code:: bash python -m nuitka --standalone program.py Follow all imports is default in this mode. You can selectively exclude modules by specifically saying ``--nofollow-import-to``, but then an ``ImportError`` will be raised when import of it is attempted at program runtime. For data files to be included, use the option ``--include-data-file==`` where the source is a file system path, but target has to be specified relative. For standalone you can also copy them manually, but this can do extra checks, and for onefile mode, there is no manual copying possible. To copy some or all file in a directory, use the option ``--include-data-file=/etc/*.txt=etc/`` where you get to specify shell patterns for the files, and a subdirectory where to put them, indicated by the trailing slash. To copy a whole folder with all files, you can use ``--include-data-dir=/path/to/images=images`` which will copy all files including a potential subdirectory structure. You cannot filter here, i.e. if you want only a partial copy, remove the files beforehand. For package data, there is a better way, using ``--include-package-data`` which detects data files of packages automatically and copies them over. It even accepts patterns in shell style. With data files, you are largely on your own. Nuitka keeps track of ones that are needed by popular packages, but it might be incomplete. Raise issues if you encounter something in these. When that is working, you can use the onefile mode if you so desire. .. code:: bash python -m nuitka --onefile program.py This will create a single binary, which on Linux will not even unpack itself, but instead loop back mount its contents as a filesystem and use that. .. code:: bash # Create a binary that unpacks into a temporary folder python -m nuitka --onefile program.py .. note:: There are more platform specific options, e.g. related to icons, splash screen, and version information, consider the ``--help`` output for the details of these and check the section "Good Looks". Again, on Windows, for the temporary file directory, by default the user one is used, however this is overridable with a path specification given in ``--windows-onefile-tempdir-spec=%TEMP%\\onefile_%PID%_%TIME%`` which is the default and asserts that the temporary directories created cannot collide. Currently these expanded tokens are available: +-----------+--------------------------------------+-----------------------------------+ | Token | What this Expands to | Example | +===========+======================================+===================================+ | %TEMP% | User temporary file directory | C:\Users\...\AppData\Locals\Temp | +-----------+--------------------------------------+-----------------------------------+ | %PID% | Process ID | 2772 | +-----------+--------------------------------------+-----------------------------------+ | %TIME% | Time in seconds since the epoch. | 1299852985 | +-----------+--------------------------------------+-----------------------------------+ | %PROGRAM% | Full program filename of executable. | C:\SomeWhere\YourOnefile.exe | +-----------+--------------------------------------+-----------------------------------+ .. note:: It is your responsibility to make the path provided unique, on Windows a running program will be locked, and while using a fixed folder name is possible, it can cause locking issues in that case, where the program gets restarted. Usually you need to use ``%TIME%`` or at least ``%PID%`` to make a path unique, and this is mainly intended for use cases, where e.g. you want things to reside in a place you choose or abide your naming conventions. Use Case 5 - Setuptools Wheels ============================== If you have a ``setup.py``, ``setup.cfg`` or ``pyproject.toml`` driven creation of wheels for your software in place, putting Nuitka to use is extremely easy. Lets start with the most common ``setuptools`` approach, you can - having Nuitka installed of course, simply execute the target ``bdist_nuitka`` rather than the ``bdist_wheel``. It takes all the options and allows you to specify some more, that are specific to Nuitka. .. code:: python # For setup.py if not you't use other build systems: setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': True, # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': 'anti-bloat', # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ["*.tests", "*.distutils"], } }, ) # For setup.py with other build systems: # The tuple nature of the arguments is required by the dark nature of # "setuptools" and plugins to it, that insist on full compatibility, # e.g. "setuptools_rust" setup( ..., command_options={ 'nuitka': { # boolean option, e.g. if you cared for C commands '--show-scons': ("setup.py", True), # options without value, e.g. enforce using Clang '--clang': ("setup.py", None), # options with single values, e.g. enable a plugin of Nuitka '--enable-plugin': ("setup.py", 'anti-bloat'), # options with several values, e.g. avoiding including modules '--nofollow-import-to' : ("setup.py", ["*.tests", "*.distutils"]), } }, ) If for some reason, you cannot or do not what to change the target, you can add this to your ``setup.py``. .. code:: python # For setup.py setup( ..., build_with_nuitka=True ) .. note:: To temporarily disable the compilation, you could remove above line, or edit the value to ``False`` by or take its value from an environment variable if you so choose, e.g. ``bool(os.environ.get("USE_NUITKA", "True"))``. This is up to you. Or you could put it in your ``setup.cfg`` .. code:: toml [metadata] build_with_nuitka = True And last, but not least, Nuitka also supports the new ``build`` meta, so when you have a ``pyproject.toml`` already, simple replace or add this value: .. code:: toml [build-system] requires = ["setuptools>=42", "wheel", "nuitka"] build-backend = "nuitka.distutils.Build" ******** Tweaks ******** Icons ===== For good looks, you may specify icons. On Windows, you can provide an icon file, a template executable, or a PNG file. All of these will work and may even be combined: .. code:: bash # These create binaries with icons: python -m nuitka --onefile --windows-icon-from-ico=your-icon.png program.py python -m nuitka --onefile --windows-icon-from-ico=your-icon.ico program.py python -m nuitka --onefile --windows-icon-template-exe=your-icon.ico program.py Splash screen ============= Splash screens are useful when program startup is slow. Onefile startup itself is not slow, but your program may be, and you cannot really know how fast the computer used will be, so it might be a good idea to have them. Luckily with Nuitka, they are easy to add for Windows. For splash screen, you need to specify it as an PNG file, and then make sure to disable the splash screen when your program is ready, e.g. has complete the imports, prepared the window, connected to the database, and wants the splash screen to go away. Here we are using the project syntax to combine the code with the creation, compile this: .. code:: python # nuitka-project: --onefile # nuitka-project: --onefile-windows-splash-screen-image={MAIN_DIRECTORY}/Splash-Screen.png # Whatever this is obviously print("Delaying startup by 10s...") import time time.sleep(10) # Use this code to signal the splash screen removal. if "NUITKA_ONEFILE_PARENT" in os.environ: splash_filename = os.path.join( tempfile.gettempdir(), "onefile_%d_splash_feedback.tmp" % int(os.environ["NUITKA_ONEFILE_PARENT"]), ) if os.path.exists(splash_filename): os.unlink(splash_filename) print("Done... splash should be gone.") ... # Rest of your program goes here. ****************** Typical Problems ****************** Memory issues and compiler bugs =============================== Sometimes the C compilers will crash saying they cannot allocate memory or that some input was truncated, or similar error messages, clearly from it. There are several options you can explore here: Ask Nuitka to use less memory ----------------------------- There is a dedicated option ``--low-memory`` which influces decisions of Nuitka, such that it avoids high usage of memory during compilation at the cost of increased compile time. Avoid 32 bit C compiler/assembler memory limits ----------------------------------------------- Do not use a 32 bits compiler, but a 64 bit one. If you are using Python with 32 bits on Windows, you most definitely ought to use MSVC as the C compiler, and not MinGW64. The MSVC is a cross compiler, and can use more memory than gcc on that platform. If you are not on Windows, that is not an option of course. Also using the 64 bits Python will work. Use LTO compilation or not -------------------------- With ``--lto=yes`` or ``--lto=no`` you can switch the C compilation to only produce bytecode, and not assembler code and machine code directly, but make a whole program optimization at the end. This will change the memory usage pretty dramatically, and if you error is coming from the assembler, using LTO will most definitely avoid that. Switch the C compiler to clang ------------------------------ People have reported that programs that fail to compile with gcc due to its bugs or memory usage work fine with clang on Linux. On Windows, this could still be an option, but it needs to be implemented first for the automatic downloaded gcc, that would contain it. Since MSVC is known to be more memory effective anyway, you should go there, and if you want to use Clang, there is support for the one contained in MSVC. Add a larger swap file to your embedded Linux --------------------------------------------- On systems with not enough RAM, you need to use swap space. Running out of it is possibly a cause, and adding more swap space, or one at all, might solve the issue, but beware that it will make things extremely slow when the compilers swap back and forth, so consider the next tip first or on top of it. Limit the amount of compilation jobs ------------------------------------ With the ``--jobs`` option of Nuitka, it will not start many C compiler instances at once, each competing for the scarce resource of RAM. By picking a value of one, only one C compiler instance will be running, and on a 8 core system, that reduces the amount of memory by factor 8, so that's a natural choice right there. Dynamic ``sys.path`` ==================== If your script modifies ``sys.path`` to e.g. insert directories with source code relative to it, Nuitka will currently not be able to see those. However, if you set the ``PYTHONPATH`` to the resulting value, you will be able to compile it. Missing data files in standalone ================================ If your program fails to file data, it can cause all kinds of different behaviours, e.g. a package might complain it is not the right version, because a ``VERSION`` file check defaulted to unknown. The absence of icon files or help texts, may raise strange errors. Often the error paths for files not being present are even buggy and will reveal programming errors like unbound local variables. Please look carefully at these exceptions keeping in mind that this can be the cause. If you program works without standalone, chances are data files might be cause. Missing DLLs in standalone ========================== Nuitka has plugins that deal with copying DLLs. For NumPy, SciPy, Tkinter, etc. These need special treatment to be able to run on other systems. Manually copying them is not enough and will given strange errors. Sometimes newer version of packages, esp. NumPy can be unsupported. In this case you will have to raise an issue, and use the older one. Dependency creep in standalone ============================== Some packages are a single import, but to Nuitka mean that more than a thousand packages (literally) are to be included. The prime example of Pandas, which does want to plug and use just about everything you can imagine. Multiple frameworks for syntax highlighting everything imaginable take time. Nuitka will have to learn effective caching to deal with this in the future. Right now, you will have to deal with huge compilation times for these. For now, a major weapon in fighting dependency creap should be applied, namely the ``anti-bloat`` plugin, which offers interesting abilities, that can be put to use and block unneeded imports, giving an error for where they occur. Use it e.g. like this ``--enable-plugin=anti-bloat --noinclude-pytest-mode=nofollow --noinclude-setuptools-mode=nofollow`` and check its help output. It can take for each module of your choice, e.g. forcing also that PyQt5 is considered uninstalled for standalone mode. Onefile: Finding files ====================== There is a difference between ``sys.argv[0]`` and ``__file__`` of the main module for onefile more, that is caused by using a bootstrap to a temporary location. The first one will be the original executable path, where as the second one will be the temporary or permanent path the bootstrap executable unpacks to. Data files will be in the later location, your original environment files will be in the former location. Given 2 files, one which you expect to be near your executable, and one which you expect to be inside the onefile binary, access them like this. .. code:: python # This will find a file near your onefile.exe open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt")) # This will find a file inside your onefile.exe open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt")) Windows Programs without console give no errors =============================================== For debugging purposes, remove ``--windows-disable-console`` or use the options ``--windows-force-stdout-spec`` and ``--windows-force-stderr-spec`` with paths as documented for ``--windows-onefile-tempdir-spec`` above. ****** Tips ****** Nuitka Options in the code ========================== There is support for conditional options, and options using pre-defined variables, this is an example: .. code:: python # Compilation mode, support OS specific. # nuitka-project-if: {OS} in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --onefile # nuitka-project-if: {OS} not in ("Windows", "Linux", "Darwin", "FreeBSD"): # nuitka-project: --standalone # The PySide2 plugin covers qt-plugins # nuitka-project: --enable-plugin=pyside2 # nuitka-project: --include-qt-plugins=sensible,qml The comments must be a start of line, and indentation is to be used, to end a conditional block, much like in Python. There are currently no other keywords than the used ones demonstrated above. You can put abitrary Python expressions there, and if you wanted to e.g. access a version information of a package, you could simply use ``__import__("module_name").__version__`` if that would be required to e.g. enable or disable certain Nuitka settings. The only thing Nuitka does that makes this not Python expressions, is expanding ``{variable}`` for a pre-defined set of variables: Table with supported variables: +------------------+--------------------------------+------------------------------------------+ | Variable | What this Expands to | Example | +==================+================================+==========================================+ | {OS} | Name of the OS used | Linux, Windows, Darwin, FreeBSD, OpenBSD | +------------------+--------------------------------+------------------------------------------+ | {Version} | Version of Nuitka | e.g. (0, 6, 16) | +------------------+--------------------------------+------------------------------------------+ | {Commercial} | Version of Nuitka Commercial | e.g. (0, 9, 4) | +------------------+--------------------------------+------------------------------------------+ | {Arch} | Architecture used | x86_64, arm64, etc. | +------------------+--------------------------------+------------------------------------------+ | {MAIN_DIRECTORY} | Directory of the compiled file | some_dir/maybe_relative | +------------------+--------------------------------+------------------------------------------+ | {Flavor} | Variant of Python | e.g. Debian Python, Anaconda Python | +------------------+--------------------------------+------------------------------------------+ Python command line flags ========================= For passing things like ``-O`` or ``-S`` to Python, to your compiled program, there is a command line option name ``--python-flag=`` which makes Nuitka emulate these options. The most important ones are supported, more can certainly be added. Caching compilation results =========================== The C compiler, when invoked with the same input files, will take a long time and much CPU to compile over and over. Make sure you are having ``ccache`` installed and configured when using gcc (even on Windows). It will make repeated compilations much faster, even if things are not yet not perfect, i.e. changes to the program can cause many C files to change, requiring a new compilation instead of using the cached result. On Windows, with gcc Nuitka supports using ``ccache.exe`` which it will offer to download from an official source and it automatically. This is the recommended way of using it on Windows, as other versions can e.g. hang. Nuitka will pick up ``ccache`` if it's in found in system ``PATH``, and it will also be possible to provide if by setting ``NUITKA_CCACHE_BINARY`` to the full path of the binary, this is for use in CI systems. For the MSVC compilers and ClangCL setups, using the ``clcache`` is automatic and included in Nuitka. Control where Caches live ========================= The storage for cache results of all kinds, downloads, cached compilation results from C and Nuitka, is done in a platform dependent directory as determined by the ``appdirs`` package. However, you can override it with setting the environment variable ``NUITKA_CACHE_DIR`` to a base directory. This is for use in environments where the home directory is not persisted, but other paths are. Runners ======= Avoid running the ``nuitka`` binary, doing ``python -m nuitka`` will make a 100% sure you are using what you think you are. Using the wrong Python will make it give you ``SyntaxError`` for good code or ``ImportError`` for installed modules. That is happening, when you run Nuitka with Python2 on Python3 code and vice versa. By explicitly calling the same Python interpreter binary, you avoid that issue entirely. Fastest C Compilers =================== The fastest binaries of ``pystone.exe`` on Windows with 64 bits Python proved to be significantly faster with MinGW64, roughly 20% better score. So it is recommended for use over MSVC. Using ``clang-cl.exe`` of Clang7 was faster than MSVC, but still significantly slower than MinGW64, and it will be harder to use, so it is not recommended. On Linux for ``pystone.bin`` the binary produced by ``clang6`` was faster than ``gcc-6.3``, but not by a significant margin. Since gcc is more often already installed, that is recommended to use for now. Differences in C compilation times have not yet been examined. Unexpected Slowdowns ==================== Using the Python DLL, like standard CPython does can lead to unexpected slowdowns, e.g. in uncompiled code that works with Unicode strings. This is because calling to the DLL rather than residing in the DLL causes overhead, and this even happens to the DLL with itself, being slower, than a Python all contained in one binary. So if feasible, aim at static linking, which is currently only possible with Anaconda Python on non-Windows, Debian Python2, self compiled Pythons (do not activate ``--enable-shared``, not needed), and installs created with ``pyenv``. .. note:: On Anaconda, you may need to execute ``conda install -c conda-forge libpython-static`` Standalone executables and dependencies ======================================= The process of making standalone executables for Windows traditionally involves using an external dependency walker in order to copy necessary libraries along with the compiled executables to the distribution folder. There is plenty of ways to find that something is missing. Do not manually copy things into the folder, esp. not DLLs, as that's not going to work. Instead make bug reports to get these handled by Nuitka properly. Windows errors with resources ============================= On Windows, the Windows Defender tool and the Windows Indexing Service both scan the freshly created binaries, while Nuitka wants to work with it, e.g. adding more resources, and then preventing operations randomly due to holding locks. Make sure to exclude your compilation stage from these services. Windows standalone program redistribuation ========================================== Whether compiling with MingW or MSVC, the standalone programs have external dependencies to Visual C Runtime libraries. Nuitka tries to ship those dependent DLLs by copying them from your system. Beginning with Microsoft Windows 10, Microsoft ships ``ucrt.dll`` (Universal C Runtime libraries) which rehook calls to ``api-ms-crt-*.dll``. With earlier Windows platforms (and wine/ReactOS), you should consider installing Visual C Runtime libraries before executing a Nuitka standalone compiled program. Depending on the used C compiler, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | Visual C version | Redist Year | CPython | +==================+=============+===============================+ | 14.2 | 2019 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ | 14.1 | 2017 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 14.0 | 2015 | 3.5, 3.6, 3.7, 3.8 | +------------------+-------------+-------------------------------+ | 10.0 | 2010 | 3.3, 3.4 | +------------------+-------------+-------------------------------+ | 9.0 | 2008 | 2.6, 2.7 | +------------------+-------------+-------------------------------+ When using MingGW64, you'll need the following redist versions: +------------------+-------------+-------------------------------+ | MingGW64 version | Redist Year | CPython | +==================+=============+===============================+ | 8.1.0 | 2015 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 | +------------------+-------------+-------------------------------+ Once the corresponding runtime libraries are installed on the target system, you may remove all ``api-ms-crt-*.dll`` files from your Nuitka compiled dist folder. Detecting Nuitka at run time ============================ It doesn't set ``sys.frozen`` unlike other tools. For Nuitka, we have the module attribute ``__compiled__`` to test if a specific module was compiled. ************* Performance ************* This chapter gives an overview, of what to currently expect in terms of performance from Nuitka. It's a work in progress and is updated as we go. The current focus for performance measurements is Python 2.7, but 3.x is going to follow later. pystone results =============== The results are the top value from this kind of output, running pystone 1000 times and taking the minimal value. The idea is that the fastest run is most meanigful, and eliminates usage spikes. .. code:: bash echo "Uncompiled Python2" for i in {1..100}; do BENCH=1 python2 tests/benchmarks/pystone.py ; done | sort -n -r | head -n 1 python2 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone.py echo "Compiled Python2" for i in {1..100}; do BENCH=1 ./pystone.bin ; done | sort -n -r | head -n 1 echo "Uncompiled Python3" for i in {1..100}; do BENCH=1 python3 tests/benchmarks/pystone3.py ; done | sort -n -r | head -n 1 python3 -m nuitka --lto=yes --pgo=yes tests/benchmarks/pystone3.py echo "Compiled Python3" for i in {1..100}; do BENCH=1 ./pystone3.bin ; done | sort -n -r | head -n 1 +-------------------+-------------------+----------------------+---------------------+ | Python | Uncompiled | Compiled LTO | Compiled PGO | +===================+===================+======================+=====================+ | Debian Python 2.7 | 137497.87 (1.000) | 460995.20 (3.353) | 503681.91 (3.663) | +-------------------+-------------------+----------------------+---------------------+ | Nuitka Python 2.7 | 144074.78 (1.048) | 479271.51 (3.486) | 511247.44 (3.718) | +-------------------+-------------------+----------------------+---------------------+ ****************** Where to go next ****************** Remember, this project is not completed yet. Although the CPython test suite works near perfect, there is still more work needed, esp. to make it do more optimization. Try it out. Follow me on Twitter ==================== Nuitka announcements and interesting stuff is pointed to on the Twitter account, but obviously with not too many details. `@KayHayen `_. Report issues or bugs ===================== Should you encounter any issues, bugs, or ideas, please visit the `Nuitka bug tracker `__ and report them. Best practices for reporting bugs: - Please always include the following information in your report, for the underlying Python version. You can easily copy&paste this into your report. .. code:: bash python -m nuitka --version - Try to make your example minimal. That is, try to remove code that does not contribute to the issue as much as possible. Ideally come up with a small reproducing program that illustrates the issue, using ``print`` with different results when that programs runs compiled or native. - If the problem occurs spuriously (i.e. not each time), try to set the environment variable ``PYTHONHASHSEED`` to ``0``, disabling hash randomization. If that makes the problem go away, try increasing in steps of 1 to a hash seed value that makes it happen every time, include it in your report. - Do not include the created code in your report. Given proper input, it's redundant, and it's not likely that I will look at it without the ability to change the Python or Nuitka source and re-run it. - Do not send screenshots of text, that is bad and lazy. Instead, capture text outputs from the console. Word of Warning =============== Consider using this software with caution. Even though many tests are applied before releases, things are potentially breaking. Your feedback and patches to Nuitka are very welcome. ************* Join Nuitka ************* You are more than welcome to join Nuitka development and help to complete the project in all minor and major ways. The development of Nuitka occurs in git. We currently have these 3 branches: - ``main`` This branch contains the stable release to which only hotfixes for bugs will be done. It is supposed to work at all times and is supported. - ``develop`` This branch contains the ongoing development. It may at times contain little regressions, but also new features. On this branch, the integration work is done, whereas new features might be developed on feature branches. - ``factory`` This branch contains unfinished and incomplete work. It is very frequently subject to ``git rebase`` and the public staging ground, where my work for develop branch lives first. It is intended for testing only and recommended to base any of your own development on. When updating it, you very often will get merge conflicts. Simply resolve those by doing ``git reset --hard origin/factory`` and switch to the latest version. .. note:: The `Developer Manual `__ explains the coding rules, branching model used, with feature branches and hotfix releases, the Nuitka design and much more. Consider reading it to become a contributor. This document is intended for Nuitka users. *********** Donations *********** Should you feel that you cannot help Nuitka directly, but still want to support, please consider `making a donation `__ and help this way. *************************** Unsupported functionality *************************** The ``co_code`` attribute of code objects ========================================= The code objects are empty for native compiled functions. There is no bytecode with Nuitka's compiled function objects, so there is no way to provide it. PDB === There is no tracing of compiled functions to attach a debugger to. ************** Optimization ************** Constant Folding ================ The most important form of optimization is the constant folding. This is when an operation can be fully predicted at compile time. Currently, Nuitka does these for some built-ins (but not all yet, somebody to look at this more closely will be very welcome!), and it does it e.g. for binary/unary operations and comparisons. Constants currently recognized: .. code:: python 5 + 6 # binary operations not 7 # unary operations 5 < 6 # comparisons range(3) # built-ins Literals are the one obvious source of constants, but also most likely other optimization steps like constant propagation or function inlining will be. So this one should not be underestimated and a very important step of successful optimizations. Every option to produce a constant may impact the generated code quality a lot. .. admonition:: Status The folding of constants is considered implemented, but it might be incomplete in that not all possible cases are caught. Please report it as a bug when you find an operation in Nuitka that has only constants as input and is not folded. Constant Propagation ==================== At the core of optimizations, there is an attempt to determine the values of variables at run time and predictions of assignments. It determines if their inputs are constants or of similar values. An expression, e.g. a module variable access, an expensive operation, may be constant across the module of the function scope and then there needs to be none or no repeated module variable look-up. Consider e.g. the module attribute ``__name__`` which likely is only ever read, so its value could be predicted to a constant string known at compile time. This can then be used as input to the constant folding. .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() .. admonition:: Status From modules attributes, only ``__name__`` is currently actually optimized. Also possible would be at least ``__doc__``. In the future, this may improve as SSA is expanded to module variables. Built-in Name Lookups ===================== Also, built-in exception name references are optimized if they are used as a module level read-only variables: .. code:: python try: something() except ValueError: # The ValueError is a slow global name lookup normally. pass .. admonition:: Status This works for all built-in names. When an assignment is done to such a name, or it's even local, then, of course, it is not done. Built-in Call Prediction ======================== For built-in calls like ``type``, ``len``, or ``range`` it is often possible to predict the result at compile time, esp. for constant inputs the resulting value often can be precomputed by Nuitka. It can simply determine the result or the raised exception and replace the built-in call with that value, allowing for more constant folding or code path reduction. .. code:: python type("string") # predictable result, builtin type str. len([1, 2]) # predictable result range(3, 9, 2) # predictable result range(3, 9, 0) # predictable exception, range raises due to 0. .. admonition:: Status The built-in call prediction is considered implemented. We can simply during compile time emulate the call and use its result or raised exception. But we may not cover all the built-ins there are yet. Sometimes the result of a built-in should not be predicted when the result is big. A ``range()`` call e.g. may give too big values to include the result in the binary. Then it is not done. .. code:: python range(100000) # We do not want this one to be expanded .. admonition:: Status This is considered mostly implemented. Please file bugs for built-ins that are pre-computed, but should not be computed by Nuitka at compile time with specific values. Conditional Statement Prediction ================================ For conditional statements, some branches may not ever be taken, because of the conditions being possible to predict. In these cases, the branch not taken and the condition check is removed. This can typically predict code like this: .. code:: python if __name__ == "__main__": # Your test code might be here use_something_not_use_by_program() or .. code:: python if False: # Your deactivated code might be here use_something_not_use_by_program() It will also benefit from constant propagations, or enable them because once some branches have been removed, other things may become more predictable, so this can trigger other optimization to become possible. Every branch removed makes optimization more likely. With some code branches removed, access patterns may be more friendly. Imagine e.g. that a function is only called in a removed branch. It may be possible to remove it entirely, and that may have other consequences too. .. admonition:: Status This is considered implemented, but for the maximum benefit, more constants need to be determined at compile time. Exception Propagation ===================== For exceptions that are determined at compile time, there is an expression that will simply do raise the exception. These can be propagated upwards, collecting potentially "side effects", i.e. parts of expressions that were executed before it occurred, and still have to be executed. Consider the following code: .. code:: python print(side_effect_having() + (1 / 0)) print(something_else()) The ``(1 / 0)`` can be predicted to raise a ``ZeroDivisionError`` exception, which will be propagated through the ``+`` operation. That part is just Constant Propagation as normal. The call ``side_effect_having()`` will have to be retained though, but the ``print`` does not and can be turned into an explicit raise. The statement sequence can then be aborted and as such the ``something_else`` call needs no code generation or consideration anymore. To that end, Nuitka works with a special node that raises an exception and is wrapped with a so-called "side_effects" expression, but yet can be used in the code as an expression having a value. .. admonition:: Status The propagation of exceptions is mostly implemented but needs handling in every kind of operations, and not all of them might do it already. As work progresses or examples arise, the coverage will be extended. Feel free to generate bug reports with non-working examples. Exception Scope Reduction ========================= Consider the following code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) The ``try`` block is bigger than it needs to be. The statement ``b = 8`` cannot cause a ``ValueError`` to be raised. As such it can be moved to outside the try without any risk. .. code:: python b = 8 try: print(range(3, b, 0)) print("Will not be executed") except ValueError as e: print(e) .. admonition:: Status This is considered done. For every kind of operation, we trace if it may raise an exception. We do however *not* track properly yet, what can do a ``ValueError`` and what cannot. Exception Block Inlining ======================== With the exception propagation, it then becomes possible to transform this code: .. code:: python try: b = 8 print(range(3, b, 0)) print("Will not be executed!") except ValueError as e: print(e) .. code:: python try: raise ValueError("range() step argument must not be zero") except ValueError as e: print(e) Which then can be lowered in complexity by avoiding the raise and catch of the exception, making it: .. code:: python e = ValueError("range() step argument must not be zero") print(e) .. admonition:: Status This is not implemented yet. Empty Branch Removal ==================== For loops and conditional statements that contain only code without effect, it should be possible to remove the whole construct: .. code:: python for i in range(1000): pass The loop could be removed, at maximum, it should be considered an assignment of variable ``i`` to ``999`` and no more. .. admonition:: Status This is not implemented yet, as it requires us to track iterators, and their side effects, as well as loop values, and exit conditions. Too much yet, but we will get there. Another example: .. code:: python if side_effect_free: pass The condition check should be removed in this case, as its evaluation is not needed. It may be difficult to predict that ``side_effect_free`` has no side effects, but many times this might be possible. .. admonition:: Status This is considered implemented. The conditional statement nature is removed if both branches are empty, only the condition is evaluated and checked for truth (in cases that could raise an exception). Unpacking Prediction ==================== When the length of the right-hand side of an assignment to a sequence can be predicted, the unpacking can be replaced with multiple assignments. .. code:: python a, b, c = 1, side_effect_free(), 3 .. code:: python a = 1 b = side_effect_free() c = 3 This is of course only really safe if the left-hand side cannot raise an exception while building the assignment targets. We do this now, but only for constants, because we currently have no ability to predict if an expression can raise an exception or not. .. admonition:: Status Not implemented yet. Will need us to see through the unpacking of what is an iteration over a tuple, we created ourselves. We are not there yet, but we will get there. Built-in Type Inference ======================= When a construct like ``in xrange()`` or ``in range()`` is used, it is possible to know what the iteration does and represent that so that iterator users can use that instead. I consider that: .. code:: python for i in xrange(1000): something(i) could translate ``xrange(1000)`` into an object of a special class that does the integer looping more efficiently. In case ``i`` is only assigned from there, this could be a nice case for a dedicated class. .. admonition:: Status Future work, not even started. Quicker Function Calls ====================== Functions are structured so that their parameter parsing and ``tp_call`` interface is separate from the actual function code. This way the call can be optimized away. One problem is that the evaluation order can differ. .. code:: python def f(a, b, c): return a, b, c f(c=get1(), b=get2(), a=get3()) This will have to evaluate first ``get1()``, then ``get2()`` and only then ``get3()`` and then make the function call with these values. Therefore it will be necessary to have a staging of the parameters before making the actual call, to avoid a re-ordering of the calls to ``get1()``, ``get2()``, and ``get3()``. .. admonition:: Status Not even started. A re-formulation that avoids the dictionary to call the function, and instead uses temporary variables appears to be relatively straight forward once we do that kind of parameter analysis. Lowering of iterated Container Types ==================================== In some cases, accesses to ``list`` constants can become ``tuple`` constants instead. Consider that: .. code:: python for x in [a, b, c]: something(x) Can be optimized into this: .. code:: python for x in (a, b, c): something(x) This allows for simpler, faster code to be generated, and fewer checks needed, because e.g. the ``tuple`` is clearly immutable, whereas the ``list`` needs a check to assert that. This is also possible for sets. .. admonition:: Status Implemented, even works for non-constants. Needs other optimization to become generally useful, and will itself help other optimization to become possible. This allows us to e.g. only treat iteration over tuples, and not care about sets. In theory, something similar is also possible for ``dict``. For the later, it will be non-trivial though to maintain the order of execution without temporary values introduced. The same thing is done for pure constants of these types, they change to ``tuple`` values when iterated. ************************* Updates for this Manual ************************* This document is written in REST. That is an ASCII format which is readable to human, but easily used to generate PDF or HTML documents. You will find the current version at: https://nuitka.net/doc/user-manual.html And the current PDF under: https://nuitka.net/doc/README.pdf Keywords: compiler,python,nuitka Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Topic :: Software Development :: Compilers Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: System :: Software Distribution Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: C Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: POSIX :: BSD :: FreeBSD Classifier: Operating System :: POSIX :: BSD :: NetBSD Classifier: Operating System :: POSIX :: BSD :: OpenBSD Classifier: Operating System :: Microsoft :: Windows Classifier: License :: OSI Approved :: Apache Software License Description-Content-Type: text/x-rst